Endianness and byte-swapping in D/L Software -------------------------------------------- F. Masci, T. Hesselroth, 09-24-04, version 1.0. After much testing of at least three possible options in enabling big-endian I/O (native under Solaris-FORTE) on a little endian platform (e.g., Linux-Intel), the following has been identified as the simplest and fastest approach, requiring few changes to C/C++ code and _none_ to Fortran code. The methods are such that the same source code can be built using either an Intel or FORTE compiler. The following s/w (except iv.) has been identified as requiring updates. i. Pointing history client s/w. (BPHFs are native big-endian). ii. jrdb.c: s/w which updates job-manifest binary files (byte-order in manifest files will always be defined as big-endian) iii. APES workshop perl scripts which need to read/write big-endian manifests files on little endian platform. iv. SuperBoresight pointing history generation s/w (Fortran). Byte order in input and output BPHFs will always be defined in big-endian. No codes updates necessary for Fortran (see below). --------------------------------------------------------------------- C/C++ code: =========== Place the following macro at the top of your code or in an include file. /* Swap bytes in 32 bit value if on intel machine, otherwise leave alone. */ #ifdef __INTEL_COMPILER #define bswap_32_asm(x) \ asm("xchg %b0,%h0; roll $16,%0; xchg %b0,%h0" : "=q" ((x)) : "0" ((x))); #else #define bswap_32_asm(x) (x) #endif After reading any variable, say "x", from a "big-endian" binary file, you just call the function bswap_32_asm(x) to replace "x" with it's byte-swapped equivalent if on a platform which defines __INTEL_COMPILER, or do nothing to it otherwise (e.g., Solaris). EXAMPLE: see .../downlink/pipeline/b-s/src/getPH_online/getPH_online_exec.c Fortran code: ============= Prior to executing Fortran code on an Intel platform (in this case only the Superboresight generation s/w will parse native big-endian binary files), the following environment variable must be set: setenv F_UFMTENDIAN big This has been tested using a BPHF parser tool written by J. Fowler: EXAMPLE: sscpipe20:/scr/fmasci/module_tests/getPHoffline/testing \ /readptghistory/dmpphf3.F On execution, the Fortran READ operation will convert input big-endian into little endian for processing and the WRITE operation will write it back into big-endian. For pipeline operations on a Linux (Intel) platform, such an environment variable will be placed in the generic "operator.csh". Solaris ignores this variable. Unfortunately, no such environment variable exists for the Intel C-compilier (icc), hence the use of the macro above. Perl: ===== This seems pretty straight forward in perl, although the functions below have not been tested. In a broad (and lazy) sense, chapters 25/29 in "Programming Perl" (L. Wall et al.) tells you how. To determine your endianness, you could use either of these pattern matches. $is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; $is_little_endian = unpack("h*", pack("s", 1)) =~ /^1/; By definition however, manifest files will always be native big-endian. You can then use the unpack() and pack() functions with a specific byte order template depending on whether you want to read (and unpack into little-endian), or write (and pack into big-endian). ---END---