GRASS Programmer's Manual
6.4.1(2011)
|
00001 /* 00002 **************************************************************************** 00003 * 00004 * MODULE: Vector library 00005 * 00006 * AUTHOR(S): Original author CERL, probably Dave Gerdes. 00007 * Update to GRASS 5.7 Radim Blazek. 00008 * 00009 * PURPOSE: Lower level functions for reading/writing/manipulating vectors. 00010 * 00011 * COPYRIGHT: (C) 2001 by the GRASS Development Team 00012 * 00013 * This program is free software under the GNU General Public 00014 * License (>=v2). Read the file COPYING that comes with GRASS 00015 * for details. 00016 * 00017 *****************************************************************************/ 00018 #include <stdio.h> 00019 #include <grass/Vect.h> 00020 00021 /* 00022 ** Written by Dave Gerdes 9/1988 00023 ** US Army Construction Engineering Research Lab 00024 */ 00025 00026 00027 /* 00028 ** 00029 ** This code is a quick hack to allow the writing of portable 00030 ** binary data files. 00031 ** The approach is to take known values and compare them against 00032 ** the current machine's internal representation. A cross reference 00033 ** table is then built, and then all file reads and writes must go through 00034 ** through these routines to correct the numbers if need be. 00035 ** 00036 ** As long as the byte switching is symetrical, the conversion routines 00037 ** will work both directions. 00038 00039 ** The integer test patterns are quite simple, and their choice was 00040 ** arbitrary, but the float and double valued were more critical. 00041 00042 ** I did not have a specification for IEEE to go by, so it is possible 00043 ** that I have missed something. My criteria were: 00044 ** 00045 ** First, true IEEE numbers had to be chosen to avoid getting an FPE. 00046 ** Second, every byte in the test pattern had to be unique. And 00047 ** finally, the number had to not be sensitive to rounding by the 00048 ** specific hardware implementation. 00049 ** 00050 ** By experimentation it was found that the number 1.3333 met 00051 ** all these criteria for both floats and doubles 00052 00053 ** See the discourse at the end of this file for more information 00054 ** 00055 ** 00056 */ 00057 00058 #define TEST_PATTERN 1.3333 00059 #define LONG_TEST 0x01020304 00060 #define INT_TEST 0x01020304 00061 #define SHORT_TEST 0x0102 00062 00063 union type_conv 00064 { 00065 double d; 00066 float f; 00067 long l; 00068 int i; 00069 short s; 00070 unsigned char c[PORT_DOUBLE]; 00071 }; 00072 static union type_conv u; 00073 00074 /* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */ 00075 static unsigned char dbl_cmpr[] = 00076 { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda }; 00077 /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */ 00078 static unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 }; 00079 static unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 }; 00080 static unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 }; 00081 static unsigned char shrt_cmpr[] = { 0x01, 0x02 }; 00082 00083 static char dbl_cnvrt[sizeof(double)]; 00084 static char flt_cnvrt[sizeof(float)]; 00085 static char lng_cnvrt[sizeof(long)]; 00086 static char int_cnvrt[sizeof(int)]; 00087 static char shrt_cnvrt[sizeof(short)]; 00088 00089 static int nat_dbl, nat_flt, nat_lng, nat_int, nat_shrt, nat_char; 00090 00091 00092 /* function prototypes */ 00093 static int find_offset(unsigned char *, unsigned char, int); 00094 static int dumpflags(void); 00095 00096 00097 int main(int argc, char **argv) 00098 { 00099 register int i; 00100 int tmp, tmp2; 00101 int err = 0; 00102 int dbl_order, flt_order, lng_order, int_order, shrt_order; 00103 00104 /* Find native sizes */ 00105 printf("\n/* Native machine sizes */\n"); 00106 printf("#define NATIVE_DOUBLE %d\n", (nat_dbl = sizeof(double))); 00107 printf("#define NATIVE_FLOAT %d\n", (nat_flt = sizeof(float))); 00108 printf("#define NATIVE_LONG %d\n", (nat_lng = sizeof(long))); 00109 printf("#define NATIVE_INT %d\n", (nat_int = sizeof(int))); 00110 printf("#define NATIVE_SHORT %d\n", (nat_shrt = sizeof(short))); 00111 printf("#define NATIVE_CHAR %d\n", (nat_char = sizeof(char))); 00112 00113 /* Following code checks only if all assumptions are fullfilled */ 00114 /* Check sizes */ 00115 if (nat_dbl != PORT_DOUBLE) { 00116 fprintf(stderr, "ERROR, sizeof (double) != %d\n", PORT_DOUBLE); 00117 err = 1; 00118 } 00119 if (nat_flt != PORT_FLOAT) { 00120 fprintf(stderr, "ERROR, sizeof (float) != %d\n", PORT_DOUBLE); 00121 err = 1; 00122 } 00123 if (nat_lng < PORT_LONG) { 00124 fprintf(stderr, "ERROR, sizeof (long) < %d\n", PORT_LONG); 00125 err = 1; 00126 } 00127 if (nat_int < PORT_INT) { 00128 fprintf(stderr, "ERROR, sizeof (int) < %d\n", PORT_INT); 00129 err = 1; 00130 } 00131 if (nat_shrt < PORT_SHORT) { 00132 fprintf(stderr, "ERROR, sizeof (short) < %d\n", PORT_SHORT); 00133 err = 1; 00134 } 00135 if (nat_char != PORT_CHAR) { 00136 fprintf(stderr, "ERROR, sizeof (char) != %d\n", PORT_CHAR); 00137 err = 1; 00138 } 00139 00140 /* Find for each byte in big endian test pattern (*_cmpr) 00141 * offset of corresponding byte in machine native order. 00142 * Look if native byte order is little or big or some other (pdp) 00143 * endian. 00144 */ 00145 /* Find double order */ 00146 u.d = TEST_PATTERN; 00147 for (i = 0; i < PORT_DOUBLE; i++) { 00148 tmp = find_offset(u.c, dbl_cmpr[i], PORT_DOUBLE); 00149 if (-1 == tmp) { 00150 fprintf(stderr, "ERROR, could not find '%x' in double\n", 00151 dbl_cmpr[i]); 00152 err = 1; 00153 } 00154 dbl_cnvrt[i] = tmp; 00155 } 00156 tmp = tmp2 = 1; 00157 for (i = 0; i < PORT_DOUBLE; i++) { 00158 if (dbl_cnvrt[i] != i) 00159 tmp = 0; /* isn't big endian */ 00160 if (dbl_cnvrt[i] != (PORT_DOUBLE - i - 1)) 00161 tmp2 = 0; /* isn't little endian */ 00162 } 00163 if (tmp) 00164 dbl_order = ENDIAN_BIG; 00165 else if (tmp2) 00166 dbl_order = ENDIAN_LITTLE; 00167 else 00168 dbl_order = ENDIAN_OTHER; 00169 00170 /* Find float order */ 00171 u.f = TEST_PATTERN; 00172 for (i = 0; i < PORT_FLOAT; i++) { 00173 tmp = find_offset(u.c, flt_cmpr[i], PORT_FLOAT); 00174 if (-1 == tmp) { 00175 fprintf(stderr, "ERROR, could not find '%x' in float\n", 00176 flt_cmpr[i]); 00177 err = 1; 00178 } 00179 flt_cnvrt[i] = tmp; 00180 } 00181 tmp = tmp2 = 1; 00182 for (i = 0; i < PORT_FLOAT; i++) { 00183 if (flt_cnvrt[i] != i) 00184 tmp = 0; 00185 if (flt_cnvrt[i] != (PORT_FLOAT - i - 1)) 00186 tmp2 = 0; 00187 } 00188 if (tmp) 00189 flt_order = ENDIAN_BIG; 00190 else if (tmp2) 00191 flt_order = ENDIAN_LITTLE; 00192 else 00193 flt_order = ENDIAN_OTHER; 00194 00195 /* Find long order */ 00196 u.l = LONG_TEST; 00197 for (i = 0; i < PORT_LONG; i++) { 00198 tmp = find_offset(u.c, lng_cmpr[i], nat_lng); 00199 if (-1 == tmp) { 00200 fprintf(stderr, "ERROR, could not find '%x' in long\n", 00201 lng_cmpr[i]); 00202 err = 1; 00203 } 00204 lng_cnvrt[i] = tmp; 00205 } 00206 tmp = tmp2 = 1; 00207 for (i = 0; i < PORT_LONG; i++) { 00208 if (lng_cnvrt[i] != (i + (nat_lng - PORT_LONG))) 00209 tmp = 0; 00210 if (lng_cnvrt[i] != (PORT_LONG - i - 1)) 00211 tmp2 = 0; 00212 } 00213 if (tmp) 00214 lng_order = ENDIAN_BIG; 00215 else if (tmp2) 00216 lng_order = ENDIAN_LITTLE; 00217 else 00218 lng_order = ENDIAN_OTHER; 00219 00220 /* Find int order */ 00221 u.i = INT_TEST; 00222 for (i = 0; i < PORT_INT; i++) { 00223 tmp = find_offset(u.c, int_cmpr[i], nat_int); 00224 if (-1 == tmp) { 00225 fprintf(stderr, "ERROR, could not find '%x' in int\n", 00226 int_cmpr[i]); 00227 err = 1; 00228 } 00229 int_cnvrt[i] = tmp; 00230 } 00231 tmp = tmp2 = 1; 00232 for (i = 0; i < PORT_INT; i++) { 00233 if (int_cnvrt[i] != (i + (nat_lng - PORT_LONG))) 00234 tmp = 0; 00235 if (int_cnvrt[i] != (PORT_INT - i - 1)) 00236 tmp2 = 0; 00237 } 00238 if (tmp) 00239 int_order = ENDIAN_BIG; 00240 else if (tmp2) 00241 int_order = ENDIAN_LITTLE; 00242 else 00243 int_order = ENDIAN_OTHER; 00244 00245 /* Find short order */ 00246 u.s = SHORT_TEST; 00247 for (i = 0; i < PORT_SHORT; i++) { 00248 tmp = find_offset(u.c, shrt_cmpr[i], nat_shrt); 00249 if (-1 == tmp) { 00250 fprintf(stderr, "ERROR, could not find '%x' in shrt\n", 00251 shrt_cmpr[i]); 00252 err = 1; 00253 } 00254 shrt_cnvrt[i] = tmp; 00255 } 00256 tmp = tmp2 = 1; 00257 for (i = 0; i < PORT_SHORT; i++) { 00258 if (shrt_cnvrt[i] != (i + (nat_shrt - PORT_SHORT))) 00259 tmp = 0; 00260 if (shrt_cnvrt[i] != (PORT_SHORT - i - 1)) 00261 tmp2 = 0; 00262 } 00263 if (tmp) 00264 shrt_order = ENDIAN_BIG; 00265 else if (tmp2) 00266 shrt_order = ENDIAN_LITTLE; 00267 else 00268 shrt_order = ENDIAN_OTHER; 00269 00270 printf("\n/* Native machine byte orders */\n"); 00271 printf("#define DOUBLE_ORDER %d\n", dbl_order); 00272 printf("#define FLOAT_ORDER %d\n", flt_order); 00273 printf("#define LONG_ORDER %d\n", lng_order); 00274 printf("#define INT_ORDER %d\n", int_order); 00275 printf("#define SHORT_ORDER %d\n", shrt_order); 00276 00277 printf("\n\n/* Translation matrices from big endian to native */\n"); 00278 dumpflags(); 00279 00280 return (err); 00281 } 00282 00283 00284 /* 00285 ** match search_value against each char in basis. 00286 ** return offset or -1 if not found 00287 */ 00288 static int 00289 find_offset(unsigned char *basis, unsigned char search_value, int size) 00290 { 00291 register int i; 00292 00293 for (i = 0; i < size; i++) 00294 if (basis[i] == search_value) 00295 return (i); 00296 00297 return (-1); 00298 } 00299 00300 00301 static int dumpflags(void) 00302 { 00303 int i; 00304 00305 fprintf(stdout, "\n/* Double format: */\nstatic int dbl_cnvrt[] = {"); 00306 i = 0; 00307 while (i < nat_dbl) { 00308 fprintf(stdout, "%d", dbl_cnvrt[i]); 00309 if (++i < nat_dbl) 00310 fprintf(stdout, ", "); 00311 } 00312 fprintf(stdout, "};\n\n"); 00313 00314 fprintf(stdout, "/* Float format : */\nstatic int flt_cnvrt[] = {"); 00315 i = 0; 00316 while (i < nat_flt) { 00317 fprintf(stdout, "%d", flt_cnvrt[i]); 00318 if (++i < nat_flt) 00319 fprintf(stdout, ", "); 00320 } 00321 fprintf(stdout, "};\n\n"); 00322 00323 fprintf(stdout, "/* Long format : */\nstatic int lng_cnvrt[] = {"); 00324 i = 0; 00325 while (i < nat_lng) { 00326 fprintf(stdout, "%d", lng_cnvrt[i]); 00327 if (++i < nat_lng) 00328 fprintf(stdout, ", "); 00329 } 00330 fprintf(stdout, "};\n\n"); 00331 00332 fprintf(stdout, "/* Int format : */\nstatic int int_cnvrt[] = {"); 00333 i = 0; 00334 while (i < nat_int) { 00335 fprintf(stdout, "%d", int_cnvrt[i]); 00336 if (++i < nat_int) 00337 fprintf(stdout, ", "); 00338 } 00339 fprintf(stdout, "};\n\n"); 00340 00341 fprintf(stdout, "/* Short format : */\nstatic int shrt_cnvrt[] = {"); 00342 i = 0; 00343 while (i < nat_shrt) { 00344 fprintf(stdout, "%d", shrt_cnvrt[i]); 00345 if (++i < nat_shrt) 00346 fprintf(stdout, ", "); 00347 } 00348 fprintf(stdout, "};\n\n"); 00349 00350 return 0; 00351 } 00352 00353 /* 00354 00355 The 3.0 dig, and dig_plus files are inherently non-portable. This 00356 can be seen in moving files between a SUN 386i and other SUN machines. 00357 The recommended way to transport files was always to convert to ASCII 00358 (b.a.vect) and copy the ASCII files: dig_ascii and dig_att to the 00359 destination machine. 00360 00361 The problem lies in the way that different architectures internally 00362 represent data. If a number is internally store as 0x01020304 on 00363 a 680x0 family machine, the same number will be stored as 00364 0x04030201 on an 80386 class machine. 00365 00366 The CERL port of GRASS to the Compaq 386 already has code to deal 00367 with this incompatibility. This code converts all files that are written 00368 out to conform to the 680x0 standard. These binary files can then be 00369 shared between machines without conversion. 00370 This code is designed to work with the majority of computers in use 00371 today that fit the following requirements: 00372 byte == 8 bits 00373 int == 4 bytes 00374 long == 4 bytes 00375 double == IEEE standard 64 bit 00376 float == IEEE standard 32 bit 00377 bytes can be swapped around in any reasonable way, but bits within each 00378 byte must be maintained in normal high to low ordering: 76543210 00379 00380 If this ability is desired on a SUN 386i, for example, you simply 00381 define the compiler flag CERL_PORTABLE in the src/CMD/makehead file 00382 and recompile all of the mapdev programs. 00383 00384 00385 Binary DLG files are NOT supported by this code, and will continue to 00386 be non-portable between different architectures. 00387 00388 00389 -dave gerdes 00390 */