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