File: port_test.c

package info (click to toggle)
grass 6.4.4-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 104,028 kB
  • ctags: 40,409
  • sloc: ansic: 419,980; python: 63,559; tcl: 46,692; cpp: 29,791; sh: 18,564; makefile: 7,000; xml: 3,505; yacc: 561; perl: 559; lex: 480; sed: 70; objc: 7
file content (390 lines) | stat: -rw-r--r-- 11,214 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
/*
 ****************************************************************************
 *
 * MODULE:       Vector library 
 *              
 * AUTHOR(S):    Original author CERL, probably Dave Gerdes.
 *               Update to GRASS 5.7 Radim Blazek.
 *
 * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
 *
 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *              License (>=v2). Read the file COPYING that comes with GRASS
 *              for details.
 *
 *****************************************************************************/
#include <stdio.h>
#include <grass/Vect.h>

/*
 **  Written by Dave Gerdes  9/1988
 **  US Army Construction Engineering Research Lab
 */


/* 
 ** 
 **  This code is a quick hack to allow the writing of portable
 **  binary data files.
 **  The approach is to take known values and compare them against
 **  the current machine's internal representation.   A cross reference
 **  table is then built, and then all file reads and writes must go through
 **  through these routines to correct the numbers if need be.
 **
 **  As long as the byte switching is symetrical, the conversion routines
 **  will work both directions.

 **  The integer test patterns are quite simple, and their choice was
 **  arbitrary, but the float and double valued were more critical.

 **  I did not have a specification for IEEE to go by, so it is possible
 **  that I have missed something.  My criteria were:
 **
 **  First, true IEEE numbers had to be chosen to avoid getting an FPE.
 **  Second, every byte in the test pattern had to be unique.   And
 **  finally, the number had to not be sensitive to rounding by the 
 **  specific hardware implementation.
 **
 **  By experimentation it was found that the number  1.3333  met
 **  all these criteria for both floats and doubles

 **  See the discourse at the end of this file for more information
 **  
 **
 */

#define TEST_PATTERN 1.3333
#define LONG_TEST 0x01020304
#define INT_TEST 0x01020304
#define SHORT_TEST 0x0102

union type_conv
{
    double d;
    float f;
    long l;
    int i;
    short s;
    unsigned char c[PORT_DOUBLE];
};
static union type_conv u;

/* dbl_cmpr holds the bytes of an IEEE representation of  TEST_PATTERN */
static unsigned char dbl_cmpr[] =
    { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda };
/* flt_cmpr holds the bytes of an IEEE representation of  TEST_PATTERN */
static unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 };
static unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
static unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
static unsigned char shrt_cmpr[] = { 0x01, 0x02 };

static char dbl_cnvrt[sizeof(double)];
static char flt_cnvrt[sizeof(float)];
static char lng_cnvrt[sizeof(long)];
static char int_cnvrt[sizeof(int)];
static char shrt_cnvrt[sizeof(short)];

static int nat_dbl, nat_flt, nat_lng, nat_int, nat_shrt, nat_char;


/* function prototypes */
static int find_offset(unsigned char *, unsigned char, int);
static int dumpflags(void);


int main(int argc, char **argv)
{
    register int i;
    int tmp, tmp2;
    int err = 0;
    int dbl_order, flt_order, lng_order, int_order, shrt_order;

    /* Find native sizes */
    printf("\n/* Native machine sizes */\n");
    printf("#define NATIVE_DOUBLE %d\n", (nat_dbl = sizeof(double)));
    printf("#define NATIVE_FLOAT  %d\n", (nat_flt = sizeof(float)));
    printf("#define NATIVE_LONG   %d\n", (nat_lng = sizeof(long)));
    printf("#define NATIVE_INT    %d\n", (nat_int = sizeof(int)));
    printf("#define NATIVE_SHORT  %d\n", (nat_shrt = sizeof(short)));
    printf("#define NATIVE_CHAR   %d\n", (nat_char = sizeof(char)));

    /* Following code checks only if all assumptions are fullfilled */
    /* Check sizes */
    if (nat_dbl != PORT_DOUBLE) {
	fprintf(stderr, "ERROR, sizeof (double) != %d\n", PORT_DOUBLE);
	err = 1;
    }
    if (nat_flt != PORT_FLOAT) {
	fprintf(stderr, "ERROR, sizeof (float) != %d\n", PORT_DOUBLE);
	err = 1;
    }
    if (nat_lng < PORT_LONG) {
	fprintf(stderr, "ERROR, sizeof (long) < %d\n", PORT_LONG);
	err = 1;
    }
    if (nat_int < PORT_INT) {
	fprintf(stderr, "ERROR, sizeof (int) < %d\n", PORT_INT);
	err = 1;
    }
    if (nat_shrt < PORT_SHORT) {
	fprintf(stderr, "ERROR, sizeof (short) < %d\n", PORT_SHORT);
	err = 1;
    }
    if (nat_char != PORT_CHAR) {
	fprintf(stderr, "ERROR, sizeof (char) != %d\n", PORT_CHAR);
	err = 1;
    }

    /* Find for each byte in big endian test pattern (*_cmpr) 
     * offset of corresponding byte in machine native order.
     * Look if native byte order is little or big or some other (pdp)
     * endian.
     */
    /* Find double order */
    u.d = TEST_PATTERN;
    for (i = 0; i < PORT_DOUBLE; i++) {
	tmp = find_offset(u.c, dbl_cmpr[i], PORT_DOUBLE);
	if (-1 == tmp) {
	    fprintf(stderr, "ERROR, could not find '%x' in double\n",
		    dbl_cmpr[i]);
	    err = 1;
	}
	dbl_cnvrt[i] = tmp;
    }
    tmp = tmp2 = 1;
    for (i = 0; i < PORT_DOUBLE; i++) {
	if (dbl_cnvrt[i] != i)
	    tmp = 0;		/* isn't big endian */
	if (dbl_cnvrt[i] != (PORT_DOUBLE - i - 1))
	    tmp2 = 0;		/* isn't little endian */
    }
    if (tmp)
	dbl_order = ENDIAN_BIG;
    else if (tmp2)
	dbl_order = ENDIAN_LITTLE;
    else
	dbl_order = ENDIAN_OTHER;

    /* Find float order */
    u.f = TEST_PATTERN;
    for (i = 0; i < PORT_FLOAT; i++) {
	tmp = find_offset(u.c, flt_cmpr[i], PORT_FLOAT);
	if (-1 == tmp) {
	    fprintf(stderr, "ERROR, could not find '%x' in float\n",
		    flt_cmpr[i]);
	    err = 1;
	}
	flt_cnvrt[i] = tmp;
    }
    tmp = tmp2 = 1;
    for (i = 0; i < PORT_FLOAT; i++) {
	if (flt_cnvrt[i] != i)
	    tmp = 0;
	if (flt_cnvrt[i] != (PORT_FLOAT - i - 1))
	    tmp2 = 0;
    }
    if (tmp)
	flt_order = ENDIAN_BIG;
    else if (tmp2)
	flt_order = ENDIAN_LITTLE;
    else
	flt_order = ENDIAN_OTHER;

    /* Find long order */
    u.l = LONG_TEST;
    for (i = 0; i < PORT_LONG; i++) {
	tmp = find_offset(u.c, lng_cmpr[i], nat_lng);
	if (-1 == tmp) {
	    fprintf(stderr, "ERROR, could not find '%x' in long\n",
		    lng_cmpr[i]);
	    err = 1;
	}
	lng_cnvrt[i] = tmp;
    }
    tmp = tmp2 = 1;
    for (i = 0; i < PORT_LONG; i++) {
	if (lng_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
	    tmp = 0;
	if (lng_cnvrt[i] != (PORT_LONG - i - 1))
	    tmp2 = 0;
    }
    if (tmp)
	lng_order = ENDIAN_BIG;
    else if (tmp2)
	lng_order = ENDIAN_LITTLE;
    else
	lng_order = ENDIAN_OTHER;

    /* Find int order */
    u.i = INT_TEST;
    for (i = 0; i < PORT_INT; i++) {
	tmp = find_offset(u.c, int_cmpr[i], nat_int);
	if (-1 == tmp) {
	    fprintf(stderr, "ERROR, could not find '%x' in int\n",
		    int_cmpr[i]);
	    err = 1;
	}
	int_cnvrt[i] = tmp;
    }
    tmp = tmp2 = 1;
    for (i = 0; i < PORT_INT; i++) {
	if (int_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
	    tmp = 0;
	if (int_cnvrt[i] != (PORT_INT - i - 1))
	    tmp2 = 0;
    }
    if (tmp)
	int_order = ENDIAN_BIG;
    else if (tmp2)
	int_order = ENDIAN_LITTLE;
    else
	int_order = ENDIAN_OTHER;

    /* Find short order */
    u.s = SHORT_TEST;
    for (i = 0; i < PORT_SHORT; i++) {
	tmp = find_offset(u.c, shrt_cmpr[i], nat_shrt);
	if (-1 == tmp) {
	    fprintf(stderr, "ERROR, could not find '%x' in shrt\n",
		    shrt_cmpr[i]);
	    err = 1;
	}
	shrt_cnvrt[i] = tmp;
    }
    tmp = tmp2 = 1;
    for (i = 0; i < PORT_SHORT; i++) {
	if (shrt_cnvrt[i] != (i + (nat_shrt - PORT_SHORT)))
	    tmp = 0;
	if (shrt_cnvrt[i] != (PORT_SHORT - i - 1))
	    tmp2 = 0;
    }
    if (tmp)
	shrt_order = ENDIAN_BIG;
    else if (tmp2)
	shrt_order = ENDIAN_LITTLE;
    else
	shrt_order = ENDIAN_OTHER;

    printf("\n/* Native machine byte orders */\n");
    printf("#define DOUBLE_ORDER %d\n", dbl_order);
    printf("#define FLOAT_ORDER  %d\n", flt_order);
    printf("#define LONG_ORDER   %d\n", lng_order);
    printf("#define INT_ORDER    %d\n", int_order);
    printf("#define SHORT_ORDER  %d\n", shrt_order);

    printf("\n\n/* Translation matrices from big endian to native */\n");
    dumpflags();

    return (err);
}


/*
 ** match search_value against each char in basis. 
 ** return offset or -1 if not found
 */
static int
find_offset(unsigned char *basis, unsigned char search_value, int size)
{
    register int i;

    for (i = 0; i < size; i++)
	if (basis[i] == search_value)
	    return (i);

    return (-1);
}


static int dumpflags(void)
{
    int i;

    fprintf(stdout, "\n/* Double format: */\nstatic int dbl_cnvrt[] = {");
    i = 0;
    while (i < nat_dbl) {
	fprintf(stdout, "%d", dbl_cnvrt[i]);
	if (++i < nat_dbl)
	    fprintf(stdout, ", ");
    }
    fprintf(stdout, "};\n\n");

    fprintf(stdout, "/* Float format : */\nstatic int flt_cnvrt[] = {");
    i = 0;
    while (i < nat_flt) {
	fprintf(stdout, "%d", flt_cnvrt[i]);
	if (++i < nat_flt)
	    fprintf(stdout, ", ");
    }
    fprintf(stdout, "};\n\n");

    fprintf(stdout, "/* Long format  : */\nstatic int lng_cnvrt[] = {");
    i = 0;
    while (i < nat_lng) {
	fprintf(stdout, "%d", lng_cnvrt[i]);
	if (++i < nat_lng)
	    fprintf(stdout, ", ");
    }
    fprintf(stdout, "};\n\n");

    fprintf(stdout, "/* Int format  : */\nstatic int int_cnvrt[] = {");
    i = 0;
    while (i < nat_int) {
	fprintf(stdout, "%d", int_cnvrt[i]);
	if (++i < nat_int)
	    fprintf(stdout, ", ");
    }
    fprintf(stdout, "};\n\n");

    fprintf(stdout, "/* Short format : */\nstatic int shrt_cnvrt[] = {");
    i = 0;
    while (i < nat_shrt) {
	fprintf(stdout, "%d", shrt_cnvrt[i]);
	if (++i < nat_shrt)
	    fprintf(stdout, ", ");
    }
    fprintf(stdout, "};\n\n");

    return 0;
}

/*

   The 3.0 dig, and dig_plus files are inherently non-portable.  This 
   can be seen in moving files between a SUN 386i and other SUN machines.
   The recommended way to transport files was always to convert to ASCII
   (b.a.vect) and copy the ASCII files:  dig_ascii and dig_att to the 
   destination machine.

   The problem lies in the way that different architectures internally
   represent data.   If a number is internally store as  0x01020304 on
   a 680x0 family machine, the same number will be stored as
   0x04030201 on an 80386 class machine.

   The CERL port of GRASS to the Compaq 386 already has code to deal
   with this incompatibility.  This code converts all files that are written
   out to conform to the 680x0 standard.  These binary files can then be 
   shared between machines without conversion.
   This code is designed to work with the majority of computers in use
   today that fit the following requirements:
   byte     ==  8 bits
   int      ==  4 bytes
   long     ==  4 bytes
   double   ==  IEEE standard 64 bit
   float    ==  IEEE standard 32 bit
   bytes can be swapped around in any reasonable way, but bits within each
   byte must be maintained in normal high to low ordering:  76543210

   If this ability is desired on a SUN 386i, for example, you simply
   define the compiler flag  CERL_PORTABLE in the src/CMD/makehead  file
   and recompile all of the mapdev programs.


   Binary DLG files are NOT supported by this code, and will continue to
   be non-portable between different architectures.


   -dave gerdes
 */