diff --git src/ioc/db/dbLink.c src/ioc/db/dbLink.c index 822daf7..af135cf 100644 --- src/ioc/db/dbLink.c +++ src/ioc/db/dbLink.c @@ -23,6 +23,7 @@ #include "cvtFast.h" #include "dbDefs.h" #include "ellLib.h" +#include "epicsStdlib.h" #include "epicsThread.h" #include "epicsTime.h" #include "errlog.h" @@ -96,6 +97,103 @@ static const char * link_field_name(const struct link *plink) /***************************** Constant Links *****************************/ +/* Convert functions */ + +/* The difference between these and dbFastConvert is that constants + * may contain hex numbers, whereas database conversions can't. + */ + +/* Copy to STRING */ +static long cvt_st_st(const char *from, void *pfield, const dbAddr *paddr) +{ + char *to = pfield; + size_t size; + + if (paddr && paddr->field_size < MAX_STRING_SIZE) { + size = paddr->field_size - 1; + } else { + size = MAX_STRING_SIZE - 1; + } + strncpy(to, from, size); + to[size] = 0; + return 0; +} + +/* Most integer conversions are identical */ +#define cvt_st_int(TYPE) static long \ +cvt_st_ ## TYPE(const char *from, void *pfield, const dbAddr *paddr) { \ + epics##TYPE *to = pfield; \ + char *end; \ +\ + if (*from == 0) { \ + *to = 0; \ + return 0; \ + } \ + return epicsParse##TYPE(from, to, 0, &end); \ +} + +/* Instanciate for CHAR, UCHAR, SHORT, USHORT and LONG */ +cvt_st_int(Int8) +cvt_st_int(UInt8) +cvt_st_int(Int16) +cvt_st_int(UInt16) +cvt_st_int(Int32) + +/* Conversion for ULONG is different... */ +static long cvt_st_UInt32(const char *from, void *pfield, const dbAddr *paddr) +{ + epicsUInt32 *to = pfield; + char *end; + long status; + + if (*from == 0) { + *to = 0; + return 0; + } + status = epicsParseUInt32(from, to, 0, &end); + if (status == S_stdlib_noConversion || + (!status && (*end == '.' || *end == 'e' || *end == 'E'))) { + /* + * Convert via double so numbers like 1.0e3 convert properly. + * db_access pretends ULONG fields are DOUBLE. + */ + double dval; + + status = epicsParseFloat64(from, &dval, &end); + if (!status && + dval >=0 && + dval <= ULONG_MAX) + *to = dval; + } + return status; +} + +/* Float conversions are identical */ +#define cvt_st_float(TYPE) static long \ +cvt_st_ ## TYPE(const char *from, void *pfield, const dbAddr *paddr) { \ + epics##TYPE *to = pfield; \ + char *end; \ +\ + if (*from == 0) { \ + *to = 0; \ + return 0; \ + } \ + return epicsParse##TYPE(from, to, &end); \ +} + +/* Instanciate for FLOAT32 and FLOAT64 */ +cvt_st_float(Float32) +cvt_st_float(Float64) + + +static long (*convert[DBF_DOUBLE+1])(const char *, void *, const dbAddr *) = { + cvt_st_st, + cvt_st_Int8, cvt_st_UInt8, + cvt_st_Int16, cvt_st_UInt16, + cvt_st_Int32, cvt_st_UInt32, + cvt_st_Float32, cvt_st_Float64 +}; + static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer) { if (!plink->value.constantStr) @@ -105,8 +203,7 @@ static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer) if (dbrType== DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE) dbrType = DBF_USHORT; - return dbFastPutConvertRoutine[DBR_STRING][dbrType] - (plink->value.constantStr, pbuffer, NULL); + return convert[dbrType](plink->value.constantStr, pbuffer, NULL); } static long dbConstGetNelements(const struct link *plink, long *nelements)