port_test.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. ****************************************************************************
  3. *
  4. * MODULE: Vector library
  5. *
  6. * AUTHOR(S): Original author CERL, probably Dave Gerdes.
  7. * Update to GRASS 5.7 Radim Blazek.
  8. *
  9. * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
  10. *
  11. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <grass/vector.h>
  21. /*
  22. ** Written by Dave Gerdes 9/1988
  23. ** US Army Construction Engineering Research Lab
  24. */
  25. /*
  26. **
  27. ** This code is a quick hack to allow the writing of portable
  28. ** binary data files.
  29. ** The approach is to take known values and compare them against
  30. ** the current machine's internal representation. A cross reference
  31. ** table is then built, and then all file reads and writes must go through
  32. ** through these routines to correct the numbers if need be.
  33. **
  34. ** As long as the byte switching is symmetrical, the conversion routines
  35. ** will work both directions.
  36. ** The integer test patterns are quite simple, and their choice was
  37. ** arbitrary, but the float and double valued were more critical.
  38. ** I did not have a specification for IEEE to go by, so it is possible
  39. ** that I have missed something. My criteria were:
  40. **
  41. ** First, true IEEE numbers had to be chosen to avoid getting an FPE.
  42. ** Second, every byte in the test pattern had to be unique. And
  43. ** finally, the number had to not be sensitive to rounding by the
  44. ** specific hardware implementation.
  45. **
  46. ** By experimentation it was found that the number 1.3333 met
  47. ** all these criteria for both floats and doubles
  48. ** See the discourse at the end of this file for more information
  49. **
  50. **
  51. */
  52. #define TEST_PATTERN 1.3333
  53. #ifdef HAVE_LONG_LONG_INT
  54. #define OFF_T_TEST 0x0102030405060708LL
  55. #else
  56. #define OFF_T_TEST 0x01020304
  57. #endif
  58. #define LONG_TEST 0x01020304
  59. #define INT_TEST 0x01020304
  60. #define SHORT_TEST 0x0102
  61. union type_conv
  62. {
  63. double d;
  64. float f;
  65. off_t o;
  66. long l;
  67. int i;
  68. short s;
  69. unsigned char c[PORT_DOUBLE];
  70. };
  71. static union type_conv u;
  72. /* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
  73. static unsigned char dbl_cmpr[] =
  74. { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda };
  75. /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
  76. static unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 };
  77. static unsigned char off_t_cmpr[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
  78. static unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
  79. static unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
  80. static unsigned char shrt_cmpr[] = { 0x01, 0x02 };
  81. static char dbl_cnvrt[sizeof(double)];
  82. static char flt_cnvrt[sizeof(float)];
  83. static char off_t_cnvrt[sizeof(off_t)];
  84. static char lng_cnvrt[sizeof(long)];
  85. static char int_cnvrt[sizeof(int)];
  86. static char shrt_cnvrt[sizeof(short)];
  87. static int nat_dbl, nat_flt, nat_lng, nat_off_t, nat_int, nat_shrt, nat_char;
  88. /* function prototypes */
  89. static int find_offset(unsigned char *, unsigned char, int);
  90. static int dumpflags(void);
  91. int main(int argc, char **argv)
  92. {
  93. register int i;
  94. int tmp, tmp2;
  95. int err = 0;
  96. int dbl_order, flt_order, lng_order, int_order, shrt_order;
  97. /* Find native sizes */
  98. printf("\n/* Native machine sizes */\n");
  99. printf("#define NATIVE_DOUBLE %d\n", (nat_dbl = sizeof(double)));
  100. printf("#define NATIVE_FLOAT %d\n", (nat_flt = sizeof(float)));
  101. printf("#define NATIVE_OFF_T %d\n", (nat_off_t = sizeof(off_t)));
  102. printf("#define NATIVE_LONG %d\n", (nat_lng = sizeof(long)));
  103. printf("#define NATIVE_INT %d\n", (nat_int = sizeof(int)));
  104. printf("#define NATIVE_SHORT %d\n", (nat_shrt = sizeof(short)));
  105. printf("#define NATIVE_CHAR %d\n", (nat_char = sizeof(char)));
  106. /* Following code checks only if all assumptions are fulfilled */
  107. /* Check sizes */
  108. if (nat_dbl != PORT_DOUBLE) {
  109. fprintf(stderr, "ERROR, sizeof (double) != %d\n", PORT_DOUBLE);
  110. err = 1;
  111. }
  112. if (nat_flt != PORT_FLOAT) {
  113. fprintf(stderr, "ERROR, sizeof (float) != %d\n", PORT_FLOAT);
  114. err = 1;
  115. }
  116. /* port_off_t is variable */
  117. if (nat_lng < PORT_LONG) {
  118. fprintf(stderr, "ERROR, sizeof (long) < %d\n", PORT_LONG);
  119. err = 1;
  120. }
  121. if (nat_int < PORT_INT) {
  122. fprintf(stderr, "ERROR, sizeof (int) < %d\n", PORT_INT);
  123. err = 1;
  124. }
  125. if (nat_shrt < PORT_SHORT) {
  126. fprintf(stderr, "ERROR, sizeof (short) < %d\n", PORT_SHORT);
  127. err = 1;
  128. }
  129. if (nat_char != PORT_CHAR) {
  130. fprintf(stderr, "ERROR, sizeof (char) != %d\n", PORT_CHAR);
  131. err = 1;
  132. }
  133. /* Find for each byte in big endian test pattern (*_cmpr)
  134. * offset of corresponding byte in machine native order.
  135. * Look if native byte order is little or big or some other (pdp)
  136. * endian.
  137. */
  138. /* Find double order */
  139. u.d = TEST_PATTERN;
  140. for (i = 0; i < PORT_DOUBLE; i++) {
  141. tmp = find_offset(u.c, dbl_cmpr[i], PORT_DOUBLE);
  142. if (-1 == tmp) {
  143. fprintf(stderr, "ERROR, could not find '%x' in double\n",
  144. dbl_cmpr[i]);
  145. err = 1;
  146. }
  147. dbl_cnvrt[i] = tmp;
  148. }
  149. tmp = tmp2 = 1;
  150. for (i = 0; i < PORT_DOUBLE; i++) {
  151. if (dbl_cnvrt[i] != i)
  152. tmp = 0; /* isn't big endian */
  153. if (dbl_cnvrt[i] != (PORT_DOUBLE - i - 1))
  154. tmp2 = 0; /* isn't little endian */
  155. }
  156. if (tmp)
  157. dbl_order = ENDIAN_BIG;
  158. else if (tmp2)
  159. dbl_order = ENDIAN_LITTLE;
  160. else
  161. dbl_order = ENDIAN_OTHER;
  162. /* Find float order */
  163. u.f = TEST_PATTERN;
  164. for (i = 0; i < PORT_FLOAT; i++) {
  165. tmp = find_offset(u.c, flt_cmpr[i], PORT_FLOAT);
  166. if (-1 == tmp) {
  167. fprintf(stderr, "ERROR, could not find '%x' in float\n",
  168. flt_cmpr[i]);
  169. err = 1;
  170. }
  171. flt_cnvrt[i] = tmp;
  172. }
  173. tmp = tmp2 = 1;
  174. for (i = 0; i < PORT_FLOAT; i++) {
  175. if (flt_cnvrt[i] != i)
  176. tmp = 0;
  177. if (flt_cnvrt[i] != (PORT_FLOAT - i - 1))
  178. tmp2 = 0;
  179. }
  180. if (tmp)
  181. flt_order = ENDIAN_BIG;
  182. else if (tmp2)
  183. flt_order = ENDIAN_LITTLE;
  184. else
  185. flt_order = ENDIAN_OTHER;
  186. /* Find off_t order */
  187. if (nat_off_t == 8)
  188. u.o = OFF_T_TEST;
  189. else
  190. u.o = LONG_TEST;
  191. for (i = 0; i < nat_off_t; i++) {
  192. tmp = find_offset(u.c, off_t_cmpr[i], nat_off_t);
  193. if (-1 == tmp) {
  194. fprintf(stderr, "ERROR, could not find '%x' in off_t\n",
  195. off_t_cmpr[i]);
  196. err = 1;
  197. }
  198. off_t_cnvrt[i] = tmp;
  199. }
  200. tmp = tmp2 = 1;
  201. for (i = 0; i < nat_off_t; i++) {
  202. if (off_t_cnvrt[i] != (i + (nat_off_t - nat_off_t)))
  203. tmp = 0;
  204. if (off_t_cnvrt[i] != (nat_off_t - i - 1))
  205. tmp2 = 0;
  206. }
  207. if (tmp)
  208. off_t_order = ENDIAN_BIG;
  209. else if (tmp2)
  210. off_t_order = ENDIAN_LITTLE;
  211. else
  212. off_t_order = ENDIAN_OTHER;
  213. /* Find long order */
  214. u.l = LONG_TEST;
  215. for (i = 0; i < PORT_LONG; i++) {
  216. tmp = find_offset(u.c, lng_cmpr[i], nat_lng);
  217. if (-1 == tmp) {
  218. fprintf(stderr, "ERROR, could not find '%x' in long\n",
  219. lng_cmpr[i]);
  220. err = 1;
  221. }
  222. lng_cnvrt[i] = tmp;
  223. }
  224. tmp = tmp2 = 1;
  225. for (i = 0; i < PORT_LONG; i++) {
  226. if (lng_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
  227. tmp = 0;
  228. if (lng_cnvrt[i] != (PORT_LONG - i - 1))
  229. tmp2 = 0;
  230. }
  231. if (tmp)
  232. lng_order = ENDIAN_BIG;
  233. else if (tmp2)
  234. lng_order = ENDIAN_LITTLE;
  235. else
  236. lng_order = ENDIAN_OTHER;
  237. /* Find int order */
  238. u.i = INT_TEST;
  239. for (i = 0; i < PORT_INT; i++) {
  240. tmp = find_offset(u.c, int_cmpr[i], nat_int);
  241. if (-1 == tmp) {
  242. fprintf(stderr, "ERROR, could not find '%x' in int\n",
  243. int_cmpr[i]);
  244. err = 1;
  245. }
  246. int_cnvrt[i] = tmp;
  247. }
  248. tmp = tmp2 = 1;
  249. for (i = 0; i < PORT_INT; i++) {
  250. if (int_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
  251. tmp = 0;
  252. if (int_cnvrt[i] != (PORT_INT - i - 1))
  253. tmp2 = 0;
  254. }
  255. if (tmp)
  256. int_order = ENDIAN_BIG;
  257. else if (tmp2)
  258. int_order = ENDIAN_LITTLE;
  259. else
  260. int_order = ENDIAN_OTHER;
  261. /* Find short order */
  262. u.s = SHORT_TEST;
  263. for (i = 0; i < PORT_SHORT; i++) {
  264. tmp = find_offset(u.c, shrt_cmpr[i], nat_shrt);
  265. if (-1 == tmp) {
  266. fprintf(stderr, "ERROR, could not find '%x' in shrt\n",
  267. shrt_cmpr[i]);
  268. err = 1;
  269. }
  270. shrt_cnvrt[i] = tmp;
  271. }
  272. tmp = tmp2 = 1;
  273. for (i = 0; i < PORT_SHORT; i++) {
  274. if (shrt_cnvrt[i] != (i + (nat_shrt - PORT_SHORT)))
  275. tmp = 0;
  276. if (shrt_cnvrt[i] != (PORT_SHORT - i - 1))
  277. tmp2 = 0;
  278. }
  279. if (tmp)
  280. shrt_order = ENDIAN_BIG;
  281. else if (tmp2)
  282. shrt_order = ENDIAN_LITTLE;
  283. else
  284. shrt_order = ENDIAN_OTHER;
  285. printf("\n/* Native machine byte orders */\n");
  286. printf("#define DOUBLE_ORDER %d\n", dbl_order);
  287. printf("#define FLOAT_ORDER %d\n", flt_order);
  288. printf("#define OFF_T_ORDER %d\n", off_t_order);
  289. printf("#define LONG_ORDER %d\n", lng_order);
  290. printf("#define INT_ORDER %d\n", int_order);
  291. printf("#define SHORT_ORDER %d\n", shrt_order);
  292. printf("\n\n/* Translation matrices from big endian to native */\n");
  293. dumpflags();
  294. return (err);
  295. }
  296. /*
  297. ** match search_value against each char in basis.
  298. ** return offset or -1 if not found
  299. */
  300. static int
  301. find_offset(unsigned char *basis, unsigned char search_value, int size)
  302. {
  303. register int i;
  304. for (i = 0; i < size; i++)
  305. if (basis[i] == search_value)
  306. return (i);
  307. return (-1);
  308. }
  309. static int dumpflags(void)
  310. {
  311. int i;
  312. fprintf(stdout, "\n/* Double format: */\nstatic int dbl_cnvrt[] = {");
  313. i = 0;
  314. while (i < nat_dbl) {
  315. fprintf(stdout, "%d", dbl_cnvrt[i]);
  316. if (++i < nat_dbl)
  317. fprintf(stdout, ", ");
  318. }
  319. fprintf(stdout, "};\n\n");
  320. fprintf(stdout, "/* Float format : */\nstatic int flt_cnvrt[] = {");
  321. i = 0;
  322. while (i < nat_flt) {
  323. fprintf(stdout, "%d", flt_cnvrt[i]);
  324. if (++i < nat_flt)
  325. fprintf(stdout, ", ");
  326. }
  327. fprintf(stdout, "};\n\n");
  328. fprintf(stdout, "/* off_t format : */\nstatic int off_t_cnvrt[] = {");
  329. i = 0;
  330. while (i < nat_off_t) {
  331. fprintf(stdout, "%d", off_t_cnvrt[i]);
  332. if (++i < nat_off_t)
  333. fprintf(stdout, ", ");
  334. }
  335. fprintf(stdout, "};\n\n");
  336. fprintf(stdout, "/* Long format : */\nstatic int lng_cnvrt[] = {");
  337. i = 0;
  338. while (i < nat_lng) {
  339. fprintf(stdout, "%d", lng_cnvrt[i]);
  340. if (++i < nat_lng)
  341. fprintf(stdout, ", ");
  342. }
  343. fprintf(stdout, "};\n\n");
  344. fprintf(stdout, "/* Int format : */\nstatic int int_cnvrt[] = {");
  345. i = 0;
  346. while (i < nat_int) {
  347. fprintf(stdout, "%d", int_cnvrt[i]);
  348. if (++i < nat_int)
  349. fprintf(stdout, ", ");
  350. }
  351. fprintf(stdout, "};\n\n");
  352. fprintf(stdout, "/* Short format : */\nstatic int shrt_cnvrt[] = {");
  353. i = 0;
  354. while (i < nat_shrt) {
  355. fprintf(stdout, "%d", shrt_cnvrt[i]);
  356. if (++i < nat_shrt)
  357. fprintf(stdout, ", ");
  358. }
  359. fprintf(stdout, "};\n\n");
  360. return 0;
  361. }
  362. /*
  363. The 3.0 dig, and dig_plus files are inherently non-portable. This
  364. can be seen in moving files between a SUN 386i and other SUN machines.
  365. The recommended way to transport files was always to convert to ASCII
  366. (b.a.vect) and copy the ASCII files: dig_ascii and dig_att to the
  367. destination machine.
  368. The problem lies in the way that different architectures internally
  369. represent data. If a number is internally store as 0x01020304 on
  370. a 680x0 family machine, the same number will be stored as
  371. 0x04030201 on an 80386 class machine.
  372. The CERL port of GRASS to the Compaq 386 already has code to deal
  373. with this incompatibility. This code converts all files that are written
  374. out to conform to the 680x0 standard. These binary files can then be
  375. shared between machines without conversion.
  376. This code is designed to work with the majority of computers in use
  377. today that fit the following requirements:
  378. byte == 8 bits
  379. int == 4 bytes
  380. long == 4 bytes
  381. double == IEEE standard 64 bit
  382. float == IEEE standard 32 bit
  383. bytes can be swapped around in any reasonable way, but bits within each
  384. byte must be maintained in normal high to low ordering: 76543210
  385. If this ability is desired on a SUN 386i, for example, you simply
  386. define the compiler flag CERL_PORTABLE in the src/CMD/makehead file
  387. and recompile all of the mapdev programs.
  388. Binary DLG files are NOT supported by this code, and will continue to
  389. be non-portable between different architectures.
  390. -dave gerdes
  391. */