GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
port_test.c
Go to the documentation of this file.
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 <grass/Vect.h>
20 
21 /*
22  ** Written by Dave Gerdes 9/1988
23  ** US Army Construction Engineering Research Lab
24  */
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 symetrical, 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 #define LONG_TEST 0x01020304
60 #define INT_TEST 0x01020304
61 #define SHORT_TEST 0x0102
62 
63 union type_conv
64 {
65  double d;
66  float f;
67  long l;
68  int i;
69  short s;
70  unsigned char c[PORT_DOUBLE];
71 };
72 static union type_conv u;
73 
74 /* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
75 static unsigned char dbl_cmpr[] =
76  { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda };
77 /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
78 static unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 };
79 static unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
80 static unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
81 static unsigned char shrt_cmpr[] = { 0x01, 0x02 };
82 
83 static char dbl_cnvrt[sizeof(double)];
84 static char flt_cnvrt[sizeof(float)];
85 static char lng_cnvrt[sizeof(long)];
86 static char int_cnvrt[sizeof(int)];
87 static char shrt_cnvrt[sizeof(short)];
88 
89 static int nat_dbl, nat_flt, nat_lng, nat_int, nat_shrt, nat_char;
90 
91 
92 /* function prototypes */
93 static int find_offset(unsigned char *, unsigned char, int);
94 static int dumpflags(void);
95 
96 
97 int main(int argc, char **argv)
98 {
99  register int i;
100  int tmp, tmp2;
101  int err = 0;
103 
104  /* Find native sizes */
105  printf("\n/* Native machine sizes */\n");
106  printf("#define NATIVE_DOUBLE %d\n", (nat_dbl = sizeof(double)));
107  printf("#define NATIVE_FLOAT %d\n", (nat_flt = sizeof(float)));
108  printf("#define NATIVE_LONG %d\n", (nat_lng = sizeof(long)));
109  printf("#define NATIVE_INT %d\n", (nat_int = sizeof(int)));
110  printf("#define NATIVE_SHORT %d\n", (nat_shrt = sizeof(short)));
111  printf("#define NATIVE_CHAR %d\n", (nat_char = sizeof(char)));
112 
113  /* Following code checks only if all assumptions are fullfilled */
114  /* Check sizes */
115  if (nat_dbl != PORT_DOUBLE) {
116  fprintf(stderr, "ERROR, sizeof (double) != %d\n", PORT_DOUBLE);
117  err = 1;
118  }
119  if (nat_flt != PORT_FLOAT) {
120  fprintf(stderr, "ERROR, sizeof (float) != %d\n", PORT_DOUBLE);
121  err = 1;
122  }
123  if (nat_lng < PORT_LONG) {
124  fprintf(stderr, "ERROR, sizeof (long) < %d\n", PORT_LONG);
125  err = 1;
126  }
127  if (nat_int < PORT_INT) {
128  fprintf(stderr, "ERROR, sizeof (int) < %d\n", PORT_INT);
129  err = 1;
130  }
131  if (nat_shrt < PORT_SHORT) {
132  fprintf(stderr, "ERROR, sizeof (short) < %d\n", PORT_SHORT);
133  err = 1;
134  }
135  if (nat_char != PORT_CHAR) {
136  fprintf(stderr, "ERROR, sizeof (char) != %d\n", PORT_CHAR);
137  err = 1;
138  }
139 
140  /* Find for each byte in big endian test pattern (*_cmpr)
141  * offset of corresponding byte in machine native order.
142  * Look if native byte order is little or big or some other (pdp)
143  * endian.
144  */
145  /* Find double order */
146  u.d = TEST_PATTERN;
147  for (i = 0; i < PORT_DOUBLE; i++) {
148  tmp = find_offset(u.c, dbl_cmpr[i], PORT_DOUBLE);
149  if (-1 == tmp) {
150  fprintf(stderr, "ERROR, could not find '%x' in double\n",
151  dbl_cmpr[i]);
152  err = 1;
153  }
154  dbl_cnvrt[i] = tmp;
155  }
156  tmp = tmp2 = 1;
157  for (i = 0; i < PORT_DOUBLE; i++) {
158  if (dbl_cnvrt[i] != i)
159  tmp = 0; /* isn't big endian */
160  if (dbl_cnvrt[i] != (PORT_DOUBLE - i - 1))
161  tmp2 = 0; /* isn't little endian */
162  }
163  if (tmp)
164  dbl_order = ENDIAN_BIG;
165  else if (tmp2)
166  dbl_order = ENDIAN_LITTLE;
167  else
168  dbl_order = ENDIAN_OTHER;
169 
170  /* Find float order */
171  u.f = TEST_PATTERN;
172  for (i = 0; i < PORT_FLOAT; i++) {
173  tmp = find_offset(u.c, flt_cmpr[i], PORT_FLOAT);
174  if (-1 == tmp) {
175  fprintf(stderr, "ERROR, could not find '%x' in float\n",
176  flt_cmpr[i]);
177  err = 1;
178  }
179  flt_cnvrt[i] = tmp;
180  }
181  tmp = tmp2 = 1;
182  for (i = 0; i < PORT_FLOAT; i++) {
183  if (flt_cnvrt[i] != i)
184  tmp = 0;
185  if (flt_cnvrt[i] != (PORT_FLOAT - i - 1))
186  tmp2 = 0;
187  }
188  if (tmp)
189  flt_order = ENDIAN_BIG;
190  else if (tmp2)
191  flt_order = ENDIAN_LITTLE;
192  else
193  flt_order = ENDIAN_OTHER;
194 
195  /* Find long order */
196  u.l = LONG_TEST;
197  for (i = 0; i < PORT_LONG; i++) {
198  tmp = find_offset(u.c, lng_cmpr[i], nat_lng);
199  if (-1 == tmp) {
200  fprintf(stderr, "ERROR, could not find '%x' in long\n",
201  lng_cmpr[i]);
202  err = 1;
203  }
204  lng_cnvrt[i] = tmp;
205  }
206  tmp = tmp2 = 1;
207  for (i = 0; i < PORT_LONG; i++) {
208  if (lng_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
209  tmp = 0;
210  if (lng_cnvrt[i] != (PORT_LONG - i - 1))
211  tmp2 = 0;
212  }
213  if (tmp)
214  lng_order = ENDIAN_BIG;
215  else if (tmp2)
216  lng_order = ENDIAN_LITTLE;
217  else
218  lng_order = ENDIAN_OTHER;
219 
220  /* Find int order */
221  u.i = INT_TEST;
222  for (i = 0; i < PORT_INT; i++) {
223  tmp = find_offset(u.c, int_cmpr[i], nat_int);
224  if (-1 == tmp) {
225  fprintf(stderr, "ERROR, could not find '%x' in int\n",
226  int_cmpr[i]);
227  err = 1;
228  }
229  int_cnvrt[i] = tmp;
230  }
231  tmp = tmp2 = 1;
232  for (i = 0; i < PORT_INT; i++) {
233  if (int_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
234  tmp = 0;
235  if (int_cnvrt[i] != (PORT_INT - i - 1))
236  tmp2 = 0;
237  }
238  if (tmp)
239  int_order = ENDIAN_BIG;
240  else if (tmp2)
241  int_order = ENDIAN_LITTLE;
242  else
243  int_order = ENDIAN_OTHER;
244 
245  /* Find short order */
246  u.s = SHORT_TEST;
247  for (i = 0; i < PORT_SHORT; i++) {
248  tmp = find_offset(u.c, shrt_cmpr[i], nat_shrt);
249  if (-1 == tmp) {
250  fprintf(stderr, "ERROR, could not find '%x' in shrt\n",
251  shrt_cmpr[i]);
252  err = 1;
253  }
254  shrt_cnvrt[i] = tmp;
255  }
256  tmp = tmp2 = 1;
257  for (i = 0; i < PORT_SHORT; i++) {
258  if (shrt_cnvrt[i] != (i + (nat_shrt - PORT_SHORT)))
259  tmp = 0;
260  if (shrt_cnvrt[i] != (PORT_SHORT - i - 1))
261  tmp2 = 0;
262  }
263  if (tmp)
264  shrt_order = ENDIAN_BIG;
265  else if (tmp2)
266  shrt_order = ENDIAN_LITTLE;
267  else
268  shrt_order = ENDIAN_OTHER;
269 
270  printf("\n/* Native machine byte orders */\n");
271  printf("#define DOUBLE_ORDER %d\n", dbl_order);
272  printf("#define FLOAT_ORDER %d\n", flt_order);
273  printf("#define LONG_ORDER %d\n", lng_order);
274  printf("#define INT_ORDER %d\n", int_order);
275  printf("#define SHORT_ORDER %d\n", shrt_order);
276 
277  printf("\n\n/* Translation matrices from big endian to native */\n");
278  dumpflags();
279 
280  return (err);
281 }
282 
283 
284 /*
285  ** match search_value against each char in basis.
286  ** return offset or -1 if not found
287  */
288 static int
289 find_offset(unsigned char *basis, unsigned char search_value, int size)
290 {
291  register int i;
292 
293  for (i = 0; i < size; i++)
294  if (basis[i] == search_value)
295  return (i);
296 
297  return (-1);
298 }
299 
300 
301 static int dumpflags(void)
302 {
303  int i;
304 
305  fprintf(stdout, "\n/* Double format: */\nstatic int dbl_cnvrt[] = {");
306  i = 0;
307  while (i < nat_dbl) {
308  fprintf(stdout, "%d", dbl_cnvrt[i]);
309  if (++i < nat_dbl)
310  fprintf(stdout, ", ");
311  }
312  fprintf(stdout, "};\n\n");
313 
314  fprintf(stdout, "/* Float format : */\nstatic int flt_cnvrt[] = {");
315  i = 0;
316  while (i < nat_flt) {
317  fprintf(stdout, "%d", flt_cnvrt[i]);
318  if (++i < nat_flt)
319  fprintf(stdout, ", ");
320  }
321  fprintf(stdout, "};\n\n");
322 
323  fprintf(stdout, "/* Long format : */\nstatic int lng_cnvrt[] = {");
324  i = 0;
325  while (i < nat_lng) {
326  fprintf(stdout, "%d", lng_cnvrt[i]);
327  if (++i < nat_lng)
328  fprintf(stdout, ", ");
329  }
330  fprintf(stdout, "};\n\n");
331 
332  fprintf(stdout, "/* Int format : */\nstatic int int_cnvrt[] = {");
333  i = 0;
334  while (i < nat_int) {
335  fprintf(stdout, "%d", int_cnvrt[i]);
336  if (++i < nat_int)
337  fprintf(stdout, ", ");
338  }
339  fprintf(stdout, "};\n\n");
340 
341  fprintf(stdout, "/* Short format : */\nstatic int shrt_cnvrt[] = {");
342  i = 0;
343  while (i < nat_shrt) {
344  fprintf(stdout, "%d", shrt_cnvrt[i]);
345  if (++i < nat_shrt)
346  fprintf(stdout, ", ");
347  }
348  fprintf(stdout, "};\n\n");
349 
350  return 0;
351 }
352 
353 /*
354 
355  The 3.0 dig, and dig_plus files are inherently non-portable. This
356  can be seen in moving files between a SUN 386i and other SUN machines.
357  The recommended way to transport files was always to convert to ASCII
358  (b.a.vect) and copy the ASCII files: dig_ascii and dig_att to the
359  destination machine.
360 
361  The problem lies in the way that different architectures internally
362  represent data. If a number is internally store as 0x01020304 on
363  a 680x0 family machine, the same number will be stored as
364  0x04030201 on an 80386 class machine.
365 
366  The CERL port of GRASS to the Compaq 386 already has code to deal
367  with this incompatibility. This code converts all files that are written
368  out to conform to the 680x0 standard. These binary files can then be
369  shared between machines without conversion.
370  This code is designed to work with the majority of computers in use
371  today that fit the following requirements:
372  byte == 8 bits
373  int == 4 bytes
374  long == 4 bytes
375  double == IEEE standard 64 bit
376  float == IEEE standard 32 bit
377  bytes can be swapped around in any reasonable way, but bits within each
378  byte must be maintained in normal high to low ordering: 76543210
379 
380  If this ability is desired on a SUN 386i, for example, you simply
381  define the compiler flag CERL_PORTABLE in the src/CMD/makehead file
382  and recompile all of the mapdev programs.
383 
384 
385  Binary DLG files are NOT supported by this code, and will continue to
386  be non-portable between different architectures.
387 
388 
389  -dave gerdes
390  */
unsigned char lng_cnvrt[sizeof(long)]
Definition: port_init.c:93
double d
Definition: port_test.c:65
int nat_lng
Definition: port_init.c:81
int nat_dbl
Definition: port_init.c:79
const char * err
Definition: g3dcolor.c:50
int nat_flt
Definition: port_init.c:80
int flt_order
Definition: port_init.c:86
#define TEST_PATTERN
Definition: port_test.c:58
tuple size
value.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap)
Definition: tools.py:2334
int main(int argc, char *argv[])
Definition: gem/main.c:302
short s
Definition: port_test.c:69
float f
Definition: port_test.c:66
#define INT_TEST
Definition: port_test.c:60
unsigned char dbl_cnvrt[sizeof(double)]
Definition: port_init.c:91
int
Definition: g3dcolor.c:48
int dbl_order
Definition: port_init.c:85
int nat_shrt
Definition: port_init.c:83
int nat_int
Definition: port_init.c:82
#define SHORT_TEST
Definition: port_test.c:61
int int_order
Definition: port_init.c:88
int lng_order
Definition: port_init.c:87
long l
Definition: port_test.c:67
int shrt_order
Definition: port_init.c:89
unsigned char int_cnvrt[sizeof(int)]
Definition: port_init.c:94
unsigned char c[PORT_DOUBLE]
Definition: port_test.c:70
unsigned char shrt_cnvrt[sizeof(short)]
Definition: port_init.c:95
#define LONG_TEST
Definition: port_test.c:59
unsigned char flt_cnvrt[sizeof(float)]
Definition: port_init.c:92