GRASS Programmer's Manual  6.4.1(2011)
port_test.c
Go to the documentation of this file.
00001 /*
00002  ****************************************************************************
00003  *
00004  * MODULE:       Vector library 
00005  *              
00006  * AUTHOR(S):    Original author CERL, probably Dave Gerdes.
00007  *               Update to GRASS 5.7 Radim Blazek.
00008  *
00009  * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
00010  *
00011  * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00012  *
00013  *               This program is free software under the GNU General Public
00014  *              License (>=v2). Read the file COPYING that comes with GRASS
00015  *              for details.
00016  *
00017  *****************************************************************************/
00018 #include <stdio.h>
00019 #include <grass/Vect.h>
00020 
00021 /*
00022  **  Written by Dave Gerdes  9/1988
00023  **  US Army Construction Engineering Research Lab
00024  */
00025 
00026 
00027 /* 
00028  ** 
00029  **  This code is a quick hack to allow the writing of portable
00030  **  binary data files.
00031  **  The approach is to take known values and compare them against
00032  **  the current machine's internal representation.   A cross reference
00033  **  table is then built, and then all file reads and writes must go through
00034  **  through these routines to correct the numbers if need be.
00035  **
00036  **  As long as the byte switching is symetrical, the conversion routines
00037  **  will work both directions.
00038 
00039  **  The integer test patterns are quite simple, and their choice was
00040  **  arbitrary, but the float and double valued were more critical.
00041 
00042  **  I did not have a specification for IEEE to go by, so it is possible
00043  **  that I have missed something.  My criteria were:
00044  **
00045  **  First, true IEEE numbers had to be chosen to avoid getting an FPE.
00046  **  Second, every byte in the test pattern had to be unique.   And
00047  **  finally, the number had to not be sensitive to rounding by the 
00048  **  specific hardware implementation.
00049  **
00050  **  By experimentation it was found that the number  1.3333  met
00051  **  all these criteria for both floats and doubles
00052 
00053  **  See the discourse at the end of this file for more information
00054  **  
00055  **
00056  */
00057 
00058 #define TEST_PATTERN 1.3333
00059 #define LONG_TEST 0x01020304
00060 #define INT_TEST 0x01020304
00061 #define SHORT_TEST 0x0102
00062 
00063 union type_conv
00064 {
00065     double d;
00066     float f;
00067     long l;
00068     int i;
00069     short s;
00070     unsigned char c[PORT_DOUBLE];
00071 };
00072 static union type_conv u;
00073 
00074 /* dbl_cmpr holds the bytes of an IEEE representation of  TEST_PATTERN */
00075 static unsigned char dbl_cmpr[] =
00076     { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda };
00077 /* flt_cmpr holds the bytes of an IEEE representation of  TEST_PATTERN */
00078 static unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 };
00079 static unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
00080 static unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
00081 static unsigned char shrt_cmpr[] = { 0x01, 0x02 };
00082 
00083 static char dbl_cnvrt[sizeof(double)];
00084 static char flt_cnvrt[sizeof(float)];
00085 static char lng_cnvrt[sizeof(long)];
00086 static char int_cnvrt[sizeof(int)];
00087 static char shrt_cnvrt[sizeof(short)];
00088 
00089 static int nat_dbl, nat_flt, nat_lng, nat_int, nat_shrt, nat_char;
00090 
00091 
00092 /* function prototypes */
00093 static int find_offset(unsigned char *, unsigned char, int);
00094 static int dumpflags(void);
00095 
00096 
00097 int main(int argc, char **argv)
00098 {
00099     register int i;
00100     int tmp, tmp2;
00101     int err = 0;
00102     int dbl_order, flt_order, lng_order, int_order, shrt_order;
00103 
00104     /* Find native sizes */
00105     printf("\n/* Native machine sizes */\n");
00106     printf("#define NATIVE_DOUBLE %d\n", (nat_dbl = sizeof(double)));
00107     printf("#define NATIVE_FLOAT  %d\n", (nat_flt = sizeof(float)));
00108     printf("#define NATIVE_LONG   %d\n", (nat_lng = sizeof(long)));
00109     printf("#define NATIVE_INT    %d\n", (nat_int = sizeof(int)));
00110     printf("#define NATIVE_SHORT  %d\n", (nat_shrt = sizeof(short)));
00111     printf("#define NATIVE_CHAR   %d\n", (nat_char = sizeof(char)));
00112 
00113     /* Following code checks only if all assumptions are fullfilled */
00114     /* Check sizes */
00115     if (nat_dbl != PORT_DOUBLE) {
00116         fprintf(stderr, "ERROR, sizeof (double) != %d\n", PORT_DOUBLE);
00117         err = 1;
00118     }
00119     if (nat_flt != PORT_FLOAT) {
00120         fprintf(stderr, "ERROR, sizeof (float) != %d\n", PORT_DOUBLE);
00121         err = 1;
00122     }
00123     if (nat_lng < PORT_LONG) {
00124         fprintf(stderr, "ERROR, sizeof (long) < %d\n", PORT_LONG);
00125         err = 1;
00126     }
00127     if (nat_int < PORT_INT) {
00128         fprintf(stderr, "ERROR, sizeof (int) < %d\n", PORT_INT);
00129         err = 1;
00130     }
00131     if (nat_shrt < PORT_SHORT) {
00132         fprintf(stderr, "ERROR, sizeof (short) < %d\n", PORT_SHORT);
00133         err = 1;
00134     }
00135     if (nat_char != PORT_CHAR) {
00136         fprintf(stderr, "ERROR, sizeof (char) != %d\n", PORT_CHAR);
00137         err = 1;
00138     }
00139 
00140     /* Find for each byte in big endian test pattern (*_cmpr) 
00141      * offset of corresponding byte in machine native order.
00142      * Look if native byte order is little or big or some other (pdp)
00143      * endian.
00144      */
00145     /* Find double order */
00146     u.d = TEST_PATTERN;
00147     for (i = 0; i < PORT_DOUBLE; i++) {
00148         tmp = find_offset(u.c, dbl_cmpr[i], PORT_DOUBLE);
00149         if (-1 == tmp) {
00150             fprintf(stderr, "ERROR, could not find '%x' in double\n",
00151                     dbl_cmpr[i]);
00152             err = 1;
00153         }
00154         dbl_cnvrt[i] = tmp;
00155     }
00156     tmp = tmp2 = 1;
00157     for (i = 0; i < PORT_DOUBLE; i++) {
00158         if (dbl_cnvrt[i] != i)
00159             tmp = 0;            /* isn't big endian */
00160         if (dbl_cnvrt[i] != (PORT_DOUBLE - i - 1))
00161             tmp2 = 0;           /* isn't little endian */
00162     }
00163     if (tmp)
00164         dbl_order = ENDIAN_BIG;
00165     else if (tmp2)
00166         dbl_order = ENDIAN_LITTLE;
00167     else
00168         dbl_order = ENDIAN_OTHER;
00169 
00170     /* Find float order */
00171     u.f = TEST_PATTERN;
00172     for (i = 0; i < PORT_FLOAT; i++) {
00173         tmp = find_offset(u.c, flt_cmpr[i], PORT_FLOAT);
00174         if (-1 == tmp) {
00175             fprintf(stderr, "ERROR, could not find '%x' in float\n",
00176                     flt_cmpr[i]);
00177             err = 1;
00178         }
00179         flt_cnvrt[i] = tmp;
00180     }
00181     tmp = tmp2 = 1;
00182     for (i = 0; i < PORT_FLOAT; i++) {
00183         if (flt_cnvrt[i] != i)
00184             tmp = 0;
00185         if (flt_cnvrt[i] != (PORT_FLOAT - i - 1))
00186             tmp2 = 0;
00187     }
00188     if (tmp)
00189         flt_order = ENDIAN_BIG;
00190     else if (tmp2)
00191         flt_order = ENDIAN_LITTLE;
00192     else
00193         flt_order = ENDIAN_OTHER;
00194 
00195     /* Find long order */
00196     u.l = LONG_TEST;
00197     for (i = 0; i < PORT_LONG; i++) {
00198         tmp = find_offset(u.c, lng_cmpr[i], nat_lng);
00199         if (-1 == tmp) {
00200             fprintf(stderr, "ERROR, could not find '%x' in long\n",
00201                     lng_cmpr[i]);
00202             err = 1;
00203         }
00204         lng_cnvrt[i] = tmp;
00205     }
00206     tmp = tmp2 = 1;
00207     for (i = 0; i < PORT_LONG; i++) {
00208         if (lng_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
00209             tmp = 0;
00210         if (lng_cnvrt[i] != (PORT_LONG - i - 1))
00211             tmp2 = 0;
00212     }
00213     if (tmp)
00214         lng_order = ENDIAN_BIG;
00215     else if (tmp2)
00216         lng_order = ENDIAN_LITTLE;
00217     else
00218         lng_order = ENDIAN_OTHER;
00219 
00220     /* Find int order */
00221     u.i = INT_TEST;
00222     for (i = 0; i < PORT_INT; i++) {
00223         tmp = find_offset(u.c, int_cmpr[i], nat_int);
00224         if (-1 == tmp) {
00225             fprintf(stderr, "ERROR, could not find '%x' in int\n",
00226                     int_cmpr[i]);
00227             err = 1;
00228         }
00229         int_cnvrt[i] = tmp;
00230     }
00231     tmp = tmp2 = 1;
00232     for (i = 0; i < PORT_INT; i++) {
00233         if (int_cnvrt[i] != (i + (nat_lng - PORT_LONG)))
00234             tmp = 0;
00235         if (int_cnvrt[i] != (PORT_INT - i - 1))
00236             tmp2 = 0;
00237     }
00238     if (tmp)
00239         int_order = ENDIAN_BIG;
00240     else if (tmp2)
00241         int_order = ENDIAN_LITTLE;
00242     else
00243         int_order = ENDIAN_OTHER;
00244 
00245     /* Find short order */
00246     u.s = SHORT_TEST;
00247     for (i = 0; i < PORT_SHORT; i++) {
00248         tmp = find_offset(u.c, shrt_cmpr[i], nat_shrt);
00249         if (-1 == tmp) {
00250             fprintf(stderr, "ERROR, could not find '%x' in shrt\n",
00251                     shrt_cmpr[i]);
00252             err = 1;
00253         }
00254         shrt_cnvrt[i] = tmp;
00255     }
00256     tmp = tmp2 = 1;
00257     for (i = 0; i < PORT_SHORT; i++) {
00258         if (shrt_cnvrt[i] != (i + (nat_shrt - PORT_SHORT)))
00259             tmp = 0;
00260         if (shrt_cnvrt[i] != (PORT_SHORT - i - 1))
00261             tmp2 = 0;
00262     }
00263     if (tmp)
00264         shrt_order = ENDIAN_BIG;
00265     else if (tmp2)
00266         shrt_order = ENDIAN_LITTLE;
00267     else
00268         shrt_order = ENDIAN_OTHER;
00269 
00270     printf("\n/* Native machine byte orders */\n");
00271     printf("#define DOUBLE_ORDER %d\n", dbl_order);
00272     printf("#define FLOAT_ORDER  %d\n", flt_order);
00273     printf("#define LONG_ORDER   %d\n", lng_order);
00274     printf("#define INT_ORDER    %d\n", int_order);
00275     printf("#define SHORT_ORDER  %d\n", shrt_order);
00276 
00277     printf("\n\n/* Translation matrices from big endian to native */\n");
00278     dumpflags();
00279 
00280     return (err);
00281 }
00282 
00283 
00284 /*
00285  ** match search_value against each char in basis. 
00286  ** return offset or -1 if not found
00287  */
00288 static int
00289 find_offset(unsigned char *basis, unsigned char search_value, int size)
00290 {
00291     register int i;
00292 
00293     for (i = 0; i < size; i++)
00294         if (basis[i] == search_value)
00295             return (i);
00296 
00297     return (-1);
00298 }
00299 
00300 
00301 static int dumpflags(void)
00302 {
00303     int i;
00304 
00305     fprintf(stdout, "\n/* Double format: */\nstatic int dbl_cnvrt[] = {");
00306     i = 0;
00307     while (i < nat_dbl) {
00308         fprintf(stdout, "%d", dbl_cnvrt[i]);
00309         if (++i < nat_dbl)
00310             fprintf(stdout, ", ");
00311     }
00312     fprintf(stdout, "};\n\n");
00313 
00314     fprintf(stdout, "/* Float format : */\nstatic int flt_cnvrt[] = {");
00315     i = 0;
00316     while (i < nat_flt) {
00317         fprintf(stdout, "%d", flt_cnvrt[i]);
00318         if (++i < nat_flt)
00319             fprintf(stdout, ", ");
00320     }
00321     fprintf(stdout, "};\n\n");
00322 
00323     fprintf(stdout, "/* Long format  : */\nstatic int lng_cnvrt[] = {");
00324     i = 0;
00325     while (i < nat_lng) {
00326         fprintf(stdout, "%d", lng_cnvrt[i]);
00327         if (++i < nat_lng)
00328             fprintf(stdout, ", ");
00329     }
00330     fprintf(stdout, "};\n\n");
00331 
00332     fprintf(stdout, "/* Int format  : */\nstatic int int_cnvrt[] = {");
00333     i = 0;
00334     while (i < nat_int) {
00335         fprintf(stdout, "%d", int_cnvrt[i]);
00336         if (++i < nat_int)
00337             fprintf(stdout, ", ");
00338     }
00339     fprintf(stdout, "};\n\n");
00340 
00341     fprintf(stdout, "/* Short format : */\nstatic int shrt_cnvrt[] = {");
00342     i = 0;
00343     while (i < nat_shrt) {
00344         fprintf(stdout, "%d", shrt_cnvrt[i]);
00345         if (++i < nat_shrt)
00346             fprintf(stdout, ", ");
00347     }
00348     fprintf(stdout, "};\n\n");
00349 
00350     return 0;
00351 }
00352 
00353 /*
00354 
00355    The 3.0 dig, and dig_plus files are inherently non-portable.  This 
00356    can be seen in moving files between a SUN 386i and other SUN machines.
00357    The recommended way to transport files was always to convert to ASCII
00358    (b.a.vect) and copy the ASCII files:  dig_ascii and dig_att to the 
00359    destination machine.
00360 
00361    The problem lies in the way that different architectures internally
00362    represent data.   If a number is internally store as  0x01020304 on
00363    a 680x0 family machine, the same number will be stored as
00364    0x04030201 on an 80386 class machine.
00365 
00366    The CERL port of GRASS to the Compaq 386 already has code to deal
00367    with this incompatibility.  This code converts all files that are written
00368    out to conform to the 680x0 standard.  These binary files can then be 
00369    shared between machines without conversion.
00370    This code is designed to work with the majority of computers in use
00371    today that fit the following requirements:
00372    byte     ==  8 bits
00373    int      ==  4 bytes
00374    long     ==  4 bytes
00375    double   ==  IEEE standard 64 bit
00376    float    ==  IEEE standard 32 bit
00377    bytes can be swapped around in any reasonable way, but bits within each
00378    byte must be maintained in normal high to low ordering:  76543210
00379 
00380    If this ability is desired on a SUN 386i, for example, you simply
00381    define the compiler flag  CERL_PORTABLE in the src/CMD/makehead  file
00382    and recompile all of the mapdev programs.
00383 
00384 
00385    Binary DLG files are NOT supported by this code, and will continue to
00386    be non-portable between different architectures.
00387 
00388 
00389    -dave gerdes
00390  */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines