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