#ifdef LAMMPS_XDR #include #include #include #include "xdr_compat.h" /* This file is needed for systems, that do not provide XDR support * in their system libraries. It was written for windows, but will * most probably work on other platforms too. better make sure you * test that the xtc files produced are ok before using it. * * It is also needed on BG/L and Cray XT3/XT4 as we don't have * XDR support in the lightweight kernel runtimes either. * * This file contains the definitions for Sun External Data * Representation (XDR) headers and routines. * * Although the rest of LAMPPS is GPL, you can copy and use the XDR * routines in any way you want as long as you obey Sun's license: * * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #ifdef __cplusplus extern "C" { #endif /* * for unit alignment */ static char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0}; static xdr_uint32_t xdr_swapbytes(xdr_uint32_t x) { xdr_uint32_t y; int i; char *px=(char *)&x; char *py=(char *)&y; for(i=0;i<4;i++) py[i]=px[3-i]; return y; } static xdr_uint32_t xdr_htonl(xdr_uint32_t x) { short s=0x0F00; if( *((char *)&s)==(char)0x0F) { /* bigendian, do nothing */ return x; } else { /* smallendian,swap bytes */ return xdr_swapbytes(x); } } static xdr_uint32_t xdr_ntohl(xdr_uint32_t x) { short s=0x0F00; if( *((char *)&s)==(char)0x0F) { /* bigendian, do nothing */ return x; } else { /* smallendian, swap bytes */ return xdr_swapbytes(x); } } /* * Free a data structure using XDR * Not a filter, but a convenient utility nonetheless */ void xdr_free (xdrproc_t proc, char *objp) { XDR x; x.x_op = XDR_FREE; (*proc) (&x, objp); } /* * XDR nothing */ bool_t xdr_void (void) { return TRUE; } /* * XDR integers */ bool_t xdr_int (XDR *xdrs, int *ip) { xdr_int32_t l; switch (xdrs->x_op) { case XDR_ENCODE: l = (xdr_int32_t) (*ip); return xdr_putint32 (xdrs, &l); case XDR_DECODE: if (!xdr_getint32 (xdrs, &l)) { return FALSE; } *ip = (int) l; case XDR_FREE: return TRUE; } return FALSE; } /* * XDR unsigned integers */ bool_t xdr_u_int (XDR *xdrs, unsigned int *up) { xdr_uint32_t l; switch (xdrs->x_op) { case XDR_ENCODE: l = (xdr_uint32_t) (*up); return xdr_putuint32 (xdrs, &l); case XDR_DECODE: if (!xdr_getuint32 (xdrs, &l)) { return FALSE; } *up = (unsigned int) l; case XDR_FREE: return TRUE; } return FALSE; } /* * XDR short integers */ bool_t xdr_short (XDR *xdrs, short *sp) { xdr_int32_t l; switch (xdrs->x_op) { case XDR_ENCODE: l = (xdr_int32_t) *sp; return xdr_putint32 (xdrs, &l); case XDR_DECODE: if (!xdr_getint32 (xdrs, &l)) { return FALSE; } *sp = (short) l; return TRUE; case XDR_FREE: return TRUE; } return FALSE; } /* * XDR unsigned short integers */ bool_t xdr_u_short (XDR *xdrs, unsigned short *usp) { xdr_uint32_t l; switch (xdrs->x_op) { case XDR_ENCODE: l = (xdr_uint32_t) *usp; return xdr_putuint32 (xdrs, &l); case XDR_DECODE: if (!xdr_getuint32 (xdrs, &l)) { return FALSE; } *usp = (unsigned short) l; return TRUE; case XDR_FREE: return TRUE; } return FALSE; } /* * XDR a char */ bool_t xdr_char (XDR *xdrs, char *cp) { int i; i = (*cp); if (!xdr_int (xdrs, &i)) { return FALSE; } *cp = i; return TRUE; } /* * XDR an unsigned char */ bool_t xdr_u_char (XDR *xdrs, unsigned char *cp) { unsigned int u; u = (*cp); if (!xdr_u_int (xdrs, &u)) { return FALSE; } *cp = u; return TRUE; } /* * XDR booleans */ bool_t xdr_bool (XDR *xdrs, int *bp) { #define XDR_FALSE ((xdr_int32_t) 0) #define XDR_TRUE ((xdr_int32_t) 1) xdr_int32_t lb; switch (xdrs->x_op) { case XDR_ENCODE: lb = *bp ? XDR_TRUE : XDR_FALSE; return xdr_putint32 (xdrs, &lb); case XDR_DECODE: if (!xdr_getint32 (xdrs, &lb)) { return FALSE; } *bp = (lb == XDR_FALSE) ? FALSE : TRUE; return TRUE; case XDR_FREE: return TRUE; } return FALSE; #undef XDR_FALSE #undef XDR_TRUE } /* * XDR opaque data * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ bool_t xdr_opaque (XDR *xdrs, char *cp, unsigned int cnt) { unsigned int rndup; static char crud[BYTES_PER_XDR_UNIT]; /* * if no data we are done */ if (cnt == 0) return TRUE; /* * round byte count to full xdr units */ rndup = cnt % BYTES_PER_XDR_UNIT; if (rndup > 0) rndup = BYTES_PER_XDR_UNIT - rndup; switch (xdrs->x_op) { case XDR_DECODE: if (!xdr_getbytes (xdrs, cp, cnt)) { return FALSE; } if (rndup == 0) return TRUE; return xdr_getbytes (xdrs, (char *)crud, rndup); case XDR_ENCODE: if (!xdr_putbytes (xdrs, cp, cnt)) { return FALSE; } if (rndup == 0) return TRUE; return xdr_putbytes (xdrs, xdr_zero, rndup); case XDR_FREE: return TRUE; } return FALSE; } /* * XDR null terminated ASCII strings * xdr_string deals with "C strings" - arrays of bytes that are * terminated by a NULL character. The parameter cpp references a * pointer to storage; If the pointer is null, then the necessary * storage is allocated. The last parameter is the max allowed length * of the string as specified by a protocol. */ bool_t xdr_string (XDR *xdrs, char **cpp, unsigned int maxsize) { char *sp = *cpp; /* sp is the actual string pointer */ unsigned int size = 0; unsigned int nodesize = 0; /* * first deal with the length since xdr strings are counted-strings */ switch (xdrs->x_op) { case XDR_FREE: if (sp == NULL) { return TRUE; /* already free */ } /* fall through... */ case XDR_ENCODE: if (sp == NULL) return FALSE; size = strlen (sp); break; case XDR_DECODE: break; } if (!xdr_u_int (xdrs, &size)) { return FALSE; } if (size > maxsize) { return FALSE; } nodesize = size + 1; /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (nodesize == 0) { return TRUE; } if (sp == NULL) *cpp = sp = (char *) malloc (nodesize); if (sp == NULL) { (void) fputs ("xdr_string: out of memory\n", stderr); return FALSE; } sp[size] = 0; /* fall into ... */ case XDR_ENCODE: return xdr_opaque (xdrs, sp, size); case XDR_FREE: free (sp); *cpp = NULL; return TRUE; } return FALSE; } /* Floating-point stuff */ bool_t xdr_float(XDR *xdrs, float *fp) { xdr_int32_t tmp; switch (xdrs->x_op) { case XDR_ENCODE: tmp = *(xdr_int32_t *)fp; return (xdr_putint32(xdrs, &tmp)); break; case XDR_DECODE: if (xdr_getint32(xdrs, &tmp)) { *(xdr_int32_t *)fp = tmp; return (TRUE); } break; case XDR_FREE: return (TRUE); } return (FALSE); } bool_t xdr_double(XDR *xdrs, double *dp) { /* Windows and some other systems dont define double-precision * word order in the header files, so unfortunately we have * to calculate it! */ static int LSW=-1; /* Least significant fp word */ int *ip; xdr_int32_t tmp[2]; if(LSW<0) { double x=0.987654321; /* Just a number */ /* Possible representations in IEEE double precision: * (S=small endian, B=big endian) * * Byte order, Word order, Hex * S S b8 56 0e 3c dd 9a ef 3f * B S 3c 0e 56 b8 3f ef 9a dd * S B dd 9a ef 3f b8 56 0e 3c * B B 3f ef 9a dd 3c 0e 56 b8 */ unsigned char ix = *((char *)&x); if(ix==0xdd || ix==0x3f) LSW=1; /* Big endian word order */ else if(ix==0xb8 || ix==0x3c) LSW=0; /* Small endian word order */ else { /* Catch strange errors */ printf("Error when detecting floating-point word order.\n" "Do you have a non-IEEE system?\n" "If possible, use the XDR libraries provided with your system,\n" "instead of the Gromacs fallback XDR source.\n"); exit(0); } } switch (xdrs->x_op) { case XDR_ENCODE: ip = (int *)dp; tmp[0] = ip[!LSW]; tmp[1] = ip[LSW]; return (xdr_putint32(xdrs, tmp) && xdr_putint32(xdrs, tmp+1)); break; case XDR_DECODE: ip = (int *)dp; if (xdr_getint32(xdrs, tmp+!LSW) && xdr_getint32(xdrs, tmp+LSW)) { ip[0] = tmp[0]; ip[1] = tmp[1]; return (TRUE); } break; case XDR_FREE: return (TRUE); } return (FALSE); } /* Array routines */ /* * xdr_vector(): * * XDR a fixed length array. Unlike variable-length arrays, * the storage of fixed length arrays is static and unfreeable. * > basep: base of the array * > size: size of the array * > elemsize: size of each element * > xdr_elem: routine to XDR each element */ bool_t xdr_vector (XDR *xdrs, char *basep, unsigned int nelem, unsigned int elemsize, xdrproc_t xdr_elem) { #define LASTUNSIGNED ((unsigned int)0-1) unsigned int i; char *elptr; elptr = basep; for (i = 0; i < nelem; i++) { if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) { return FALSE; } elptr += elemsize; } return TRUE; #undef LASTUNSIGNED } static bool_t xdrstdio_getbytes (XDR *, char *, unsigned int); static bool_t xdrstdio_putbytes (XDR *, char *, unsigned int); static unsigned int xdrstdio_getpos (XDR *); static bool_t xdrstdio_setpos (XDR *, unsigned int); static xdr_int32_t *xdrstdio_inline (XDR *, int); static void xdrstdio_destroy (XDR *); static bool_t xdrstdio_getint32 (XDR *, xdr_int32_t *); static bool_t xdrstdio_putint32 (XDR *, xdr_int32_t *); static bool_t xdrstdio_getuint32 (XDR *, xdr_uint32_t *); static bool_t xdrstdio_putuint32 (XDR *, xdr_uint32_t *); /* * Ops vector for stdio type XDR */ static const struct xdr_ops xdrstdio_ops = { xdrstdio_getbytes, /* deserialize counted bytes */ xdrstdio_putbytes, /* serialize counted bytes */ xdrstdio_getpos, /* get offset in the stream */ xdrstdio_setpos, /* set offset in the stream */ xdrstdio_inline, /* prime stream for inline macros */ xdrstdio_destroy, /* destroy stream */ xdrstdio_getint32, /* deserialize a int */ xdrstdio_putint32, /* serialize a int */ xdrstdio_getuint32, /* deserialize a int */ xdrstdio_putuint32 /* serialize a int */ }; /* * Initialize a stdio xdr stream. * Sets the xdr stream handle xdrs for use on the stream file. * Operation flag is set to op. */ void xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op) { xdrs->x_op = op; /* We have to add the const since the `struct xdr_ops' in `struct XDR' is not `const'. */ xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops; xdrs->x_private = (char *) file; xdrs->x_handy = 0; xdrs->x_base = 0; } /* * Destroy a stdio xdr stream. * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create. */ static void xdrstdio_destroy (XDR *xdrs) { (void) fflush ((FILE *) xdrs->x_private); /* xx should we close the file ?? */ } static bool_t xdrstdio_getbytes (XDR *xdrs, char *addr, unsigned int len) { if ((len != 0) && (fread (addr, (int) len, 1, (FILE *) xdrs->x_private) != 1)) return FALSE; return TRUE; } static bool_t xdrstdio_putbytes (XDR *xdrs, char *addr, unsigned int len) { if ((len != 0) && (fwrite (addr, (int) len, 1, (FILE *) xdrs->x_private) != 1)) return FALSE; return TRUE; } static unsigned int xdrstdio_getpos (XDR *xdrs) { return (unsigned int) ftell ((FILE *) xdrs->x_private); } static bool_t xdrstdio_setpos (XDR *xdrs, unsigned int pos) { return fseek ((FILE *) xdrs->x_private, (xdr_int32_t) pos, 0) < 0 ? FALSE : TRUE; } static xdr_int32_t * xdrstdio_inline (XDR *xdrs, int len) { /* * Must do some work to implement this: must insure * enough data in the underlying stdio buffer, * that the buffer is aligned so that we can indirect through a * long *, and stuff this pointer in xdrs->x_buf. Doing * a fread or fwrite to a scratch buffer would defeat * most of the gains to be had here and require storage * management on this buffer, so we don't do this. */ return NULL; } static bool_t xdrstdio_getint32 (XDR *xdrs, xdr_int32_t *ip) { xdr_int32_t mycopy; if (fread ((char *) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) return FALSE; *ip = xdr_ntohl (mycopy); return TRUE; } static bool_t xdrstdio_putint32 (XDR *xdrs, xdr_int32_t *ip) { xdr_int32_t mycopy = xdr_htonl (*ip); ip = &mycopy; if (fwrite ((char *) ip, 4, 1, (FILE *) xdrs->x_private) != 1) return FALSE; return TRUE; } static bool_t xdrstdio_getuint32 (XDR *xdrs, xdr_uint32_t *ip) { xdr_uint32_t mycopy; if (fread ((char *) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) return FALSE; *ip = xdr_ntohl (mycopy); return TRUE; } static bool_t xdrstdio_putuint32 (XDR *xdrs, xdr_uint32_t *ip) { xdr_uint32_t mycopy = xdr_htonl (*ip); ip = &mycopy; if (fwrite ((char *) ip, 4, 1, (FILE *) xdrs->x_private) != 1) return FALSE; return TRUE; } #ifdef __cplusplus } #endif #else /* satisfy compilers that do not like to compile empty files. */ static void i_am_a_dummy_subroutine(void) { return; } #endif