/* * $Id$ * * MACROS for rapid conversion between HOST data formats and those used * by the IOCs (NETWORK). * * Author: J. Hill * * The conversion routines are used in both ca lib * and the IOC ca server (base/rsrv). * The latter, however, cannot include os_depen.h so * I extracted the conversion specific code from there * and put it in this "now stand alone" net_convert.h * 8-22-96 -kuk- * * * joh 09-13-90 force MIT sign to zero if exponent is zero * to prevent a reseved operand fault. * * joh 03-16-94 Added double fp * joh 11-02-94 Moved all fp cvrt to functions in * convert.c * * */ #ifndef _NET_CONVERT_H #define _NET_CONVERT_H #include "db_access.h" #include "shareLib.h" #ifdef __cplusplus extern "C" { #endif /* * Here are the definitions for architecture dependent byte ordering * and floating point format */ #if defined (_M_IX86) || defined (_X86_) || defined (__i386__) # define CA_FLOAT_IEEE # define CA_LITTLE_ENDIAN #elif defined (VAX) # define CA_FLOAT_MIT # define CA_LITTLE_ENDIAN #elif ( defined (__ALPHA) || defined (__alpha) ) && ( defined (VMS) || defined (__VMS) ) # define CA_FLOAT_MIT # define CA_LITTLE_ENDIAN #elif ( defined (__ALPHA) || defined (__alpha) ) && defined (UNIX) # define CA_FLOAT_IEEE # define CA_LITTLE_ENDIAN #else # define CA_FLOAT_IEEE # define CA_BIG_ENDIAN #endif /* * some architecture sanity checks */ #if defined(CA_BIG_ENDIAN) && defined(CA_LITTLE_ENDIAN) #error defined(CA_BIG_ENDIAN) && defined(CA_LITTLE_ENDIAN) #endif #if !defined(CA_BIG_ENDIAN) && !defined(CA_LITTLE_ENDIAN) #error !defined(CA_BIG_ENDIAN) && !defined(CA_LITTLE_ENDIAN) #endif #if defined(CA_FLOAT_IEEE) && defined(CA_FLOAT_MIT) #error defined(CA_FLOAT_IEEE) && defined(CA_FLOAT_MIT) #endif #if !defined(CA_FLOAT_IEEE) && !defined(CA_FLOAT_MIT) #error !defined(CA_FLOAT_IEEE) && !defined(CA_FLOAT_MIT) #endif /* * CONVERSION_REQUIRED is set if either the byte order * or the floating point does not match */ #if !defined(CA_FLOAT_IEEE) || !defined(CA_BIG_ENDIAN) #define CONVERSION_REQUIRED #endif /* * if hton is true then it is a host to network conversion * otherwise vise-versa * * net format: big endian and IEEE float */ typedef void CACVRTFUNC (const void *pSrc, void *pDest, int hton, unsigned long count); #ifdef CONVERSION_REQUIRED /* cvrt is (array of) (pointer to) (function returning) int */ epicsShareExtern CACVRTFUNC *cac_dbr_cvrt[LAST_BUFFER_TYPE+1]; #endif /* * Macros ... * * This is also used in the ca server on pc486 archs, * where source and destination buffers are identical, * so we need a tmp variable in e.g. 'double' conversions. */ #if defined(CA_LITTLE_ENDIAN) #if 0 ( (dbr_short_t) ((((dbr_ushort_t)SHORT)>>8) | (((dbr_ushort_t)SHORT)<<8)) # ifndef ntohs # define ntohs(SHORT)\ ( (dbr_short_t)\ ((((dbr_ushort_t)SHORT) & (dbr_ushort_t) 0x00ff) << 8 |\ (((dbr_ushort_t)SHORT) & (dbr_ushort_t) 0xff00) >> 8) ) # endif # ifndef htons # define htons(SHORT)\ ( (dbr_short_t)\ ((((dbr_ushort_t)SHORT) & (dbr_ushort_t) 0x00ff) << 8 |\ (((dbr_ushort_t)SHORT) & (dbr_ushort_t) 0xff00) >> 8) ) # endif #endif #else # ifndef ntohs # define ntohs(SHORT) (SHORT) # endif # ifndef htons # define htons(SHORT) (SHORT) # endif #endif #if defined(CA_LITTLE_ENDIAN) #if 0 # ifndef ntohl # define ntohl(LONG)\ ( (dbr_long_t) (\ ( ((dbr_ulong_t)LONG) & 0xff000000 ) >> 24u |\ ( ((dbr_ulong_t)LONG) & 0x000000ff ) << 24u |\ ( ((dbr_ulong_t)LONG) & 0x0000ff00 ) << 8u |\ ( ((dbr_ulong_t)LONG) & 0x00ff0000 ) >> 8u )\ ) # endif # ifndef htonl # define htonl(LONG)\ ( (dbr_long_t) (\ ( ((dbr_ulong_t)(LONG)) & 0x000000ff ) << 24u |\ ( ((dbr_ulong_t)(LONG)) & 0xff000000 ) >> 24u |\ ( ((dbr_ulong_t)(LONG)) & 0x00ff0000 ) >> 8u |\ ( ((dbr_ulong_t)(LONG)) & 0x0000ff00 ) << 8u )\ ) # endif #endif #else # ifndef ntohl # define ntohl(LONG) (LONG) # endif # ifndef htonl # define htonl(LONG) (LONG) # endif #endif #if defined(CA_FLOAT_IEEE) && !defined(CA_LITTLE_ENDIAN) # define dbr_htond(IEEEhost, IEEEnet) \ (*(dbr_double_t *)(IEEEnet) = *(dbr_double_t *)(IEEEhost)) # define dbr_ntohd(IEEEnet, IEEEhost) \ (*(dbr_double_t *)(IEEEhost) = *(dbr_double_t *)(IEEEnet)) # define dbr_htonf(IEEEhost, IEEEnet) \ (*(dbr_float_t *)(IEEEnet) = *(dbr_float_t *)(IEEEhost)) # define dbr_ntohf(IEEEnet, IEEEhost) \ (*(dbr_float_t *)(IEEEhost) = *(dbr_float_t *)(IEEEnet)) #elif defined(CA_FLOAT_IEEE) && defined(CA_LITTLE_ENDIAN) && 0 # define dbr_ntohf(NET,HOST) \ {*((dbr_long_t *)(HOST)) = ntohl(*((dbr_long_t *)(NET )));} # define dbr_htonf(HOST,NET) \ {*((dbr_long_t *)(NET) ) = htonl(*((dbr_long_t *)(HOST)));} # define dbr_ntohd(NET,HOST) \ { \ dbr_long_t cvrt_tmp; \ cvrt_tmp = ntohl(((dbr_long_t *)(NET))[0]); \ ((dbr_long_t *)(HOST))[0] = ntohl(((dbr_long_t *)(NET))[1]); \ ((dbr_long_t *)(HOST))[1] = cvrt_tmp; \ } # define dbr_htond(HOST,NET) \ { \ dbr_long_t cvrt_tmp; \ cvrt_tmp = htonl(((dbr_long_t *)(HOST))[0]); \ ((dbr_long_t *)(NET))[0] = htonl(((dbr_long_t *)(HOST))[1]); \ ((dbr_long_t *)(NET))[1] = cvrt_tmp; \ } #else epicsShareFunc void dbr_htond(dbr_double_t *pHost, dbr_double_t *pNet); epicsShareFunc void dbr_ntohd(dbr_double_t *pNet, dbr_double_t *pHost); epicsShareFunc void dbr_htonf(dbr_float_t *pHost, dbr_float_t *pNet); epicsShareFunc void dbr_ntohf(dbr_float_t *pNet, dbr_float_t *pHost); #endif #ifdef __cplusplus } #endif #endif /* define _NET_CONVERT_H */