GRASS 8 Programmer's Manual 8.6.0dev(2026)-f6f2c534ea
Loading...
Searching...
No Matches
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
68union 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};
77static union type_conv u;
78
79/* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
80static 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 */
83static unsigned char flt_cmpr[] = {0x3f, 0xaa, 0xa9, 0x93};
84static unsigned char off_t_cmpr[] = {0x01, 0x02, 0x03, 0x04,
85 0x05, 0x06, 0x07, 0x08};
86static unsigned char lng_cmpr[] = {0x01, 0x02, 0x03, 0x04};
87static unsigned char int_cmpr[] = {0x01, 0x02, 0x03, 0x04};
88static unsigned char shrt_cmpr[] = {0x01, 0x02};
89
90static char dbl_cnvrt[sizeof(double)];
91static char flt_cnvrt[sizeof(float)];
92static char off_t_cnvrt[sizeof(off_t)];
93static char lng_cnvrt[sizeof(long)];
94static char int_cnvrt[sizeof(int)];
95static char shrt_cnvrt[sizeof(short)];
96
97static int nat_dbl, nat_flt, nat_lng, nat_off_t, nat_int, nat_shrt, nat_char;
98
99/* function prototypes */
100static int find_offset(unsigned char *, unsigned char, int);
101static int dumpflags(void);
102
103int 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 */
323static 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
335static 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:417
#define ENDIAN_LITTLE
Endian check.
Definition gis.h:415
#define ENDIAN_BIG
Definition gis.h:416
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
#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)
int main(void)
Definition winlocale.c:201