From 88bfd6f378dac38bf2751621d2c8633379aa092c Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 5 Nov 2025 17:11:06 +0100 Subject: [PATCH] Allow hex and octal strings in dbPut and dbGet Setting EPICS_DB_CONVERT_DECIMAL_ONLY to YES/yes change the dbPut() and dbGet() string to integer conversions to the original decimal only policy. --- documentation/new-notes/PR-678.md | 12 +++++++ modules/database/src/ioc/db/dbConvert.c | 34 ++++++++++---------- modules/database/src/ioc/db/dbFastLinkConv.c | 20 ++++++------ modules/database/src/ioc/misc/iocInit.c | 12 +++++++ modules/libcom/src/misc/epicsConvert.c | 2 ++ modules/libcom/src/misc/epicsConvert.h | 6 ++++ 6 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 documentation/new-notes/PR-678.md diff --git a/documentation/new-notes/PR-678.md b/documentation/new-notes/PR-678.md new file mode 100644 index 000000000..26b237186 --- /dev/null +++ b/documentation/new-notes/PR-678.md @@ -0,0 +1,12 @@ +### Allow hex and octal strings in dbPut and dbGet + +It is now possible to convert hex and octal strings to integer fields +with `dbPut()`, `dbGet()` and related functions like the iocsh command +`dbpf` or through database links. + +Possible incompatibility: Up to now, leading `0`s have been ignored, +now they switch to octal mode. + +For backward compatibility, this behavior can be switched off, returning +to the old decimal only conversions, by setting the environment variable +`EPICS_DB_CONVERT_DECIMAL_ONLY` to `YES` (case insensitive) before `iocInit`. diff --git a/modules/database/src/ioc/db/dbConvert.c b/modules/database/src/ioc/db/dbConvert.c index ee1b5cbeb..2b17358c4 100644 --- a/modules/database/src/ioc/db/dbConvert.c +++ b/modules/database/src/ioc/db/dbConvert.c @@ -171,7 +171,7 @@ static long getStringChar(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseInt8(psrc, pdst++, 10, &end); + long status = epicsParseInt8(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -195,7 +195,7 @@ static long getStringUchar(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseUInt8(psrc, pdst++, 10, &end); + long status = epicsParseUInt8(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -219,7 +219,7 @@ static long getStringShort(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseInt16(psrc, pdst++, 10, &end); + long status = epicsParseInt16(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -243,7 +243,7 @@ static long getStringUshort(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseUInt16(psrc, pdst++, 10, &end); + long status = epicsParseUInt16(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -267,7 +267,7 @@ static long getStringLong(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseInt32(psrc, pdst++, 10, &end); + long status = epicsParseInt32(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -291,7 +291,7 @@ static long getStringUlong(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseUInt32(psrc, pdst, 10, &end); + long status = epicsParseUInt32(psrc, pdst, dbConvertBase, &end); if (status == S_stdlib_noConversion || (!status && (*end == '.' || *end == 'e' || *end == 'E'))) { @@ -328,7 +328,7 @@ static long getStringInt64(const dbAddr *paddr, *pdst++ = 0; else { char *end; - long status = epicsParseInt64(psrc, pdst++, 10, &end); + long status = epicsParseInt64(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -946,7 +946,7 @@ static long putStringChar(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseInt8(psrc, pdst++, 10, &end); + long status = epicsParseInt8(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -965,7 +965,7 @@ static long putStringUchar(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseUInt8(psrc, pdst++, 10, &end); + long status = epicsParseUInt8(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -984,7 +984,7 @@ static long putStringShort(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseInt16(psrc, pdst++, 10, &end); + long status = epicsParseInt16(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -1003,7 +1003,7 @@ static long putStringUshort(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseUInt16(psrc, pdst++, 10, &end); + long status = epicsParseUInt16(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -1022,7 +1022,7 @@ static long putStringLong(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseInt32(psrc, pdst++, 10, &end); + long status = epicsParseInt32(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -1041,7 +1041,7 @@ static long putStringUlong(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseUInt32(psrc, pdst, 10, &end); + long status = epicsParseUInt32(psrc, pdst, dbConvertBase, &end); if (status == S_stdlib_noConversion || (!status && (*end == '.' || *end == 'e' || *end == 'E'))) { @@ -1074,7 +1074,7 @@ static long putStringInt64(dbAddr *paddr, while (nRequest--) { char *end; - long status = epicsParseInt64(psrc, pdst++, 10, &end); + long status = epicsParseInt64(psrc, pdst++, dbConvertBase, &end); if (status) return status; @@ -1178,7 +1178,7 @@ static long putStringEnum(dbAddr *paddr, epicsEnum16 val; char *end; - status = epicsParseUInt16(pfrom, &val, 10, &end); + status = epicsParseUInt16(pfrom, &val, dbConvertBase, &end); if (!status && val < enumStrs.no_str) { *pfield = val; return 0; @@ -1219,7 +1219,7 @@ static long putStringMenu(dbAddr *paddr, } } - if (!epicsParseUInt16(pfrom, &val, 10, NULL) + if (!epicsParseUInt16(pfrom, &val, dbConvertBase, NULL) && val < nChoice) { *pfield = val; return 0; @@ -1258,7 +1258,7 @@ static long putStringDevice(dbAddr *paddr, } } - if (!epicsParseUInt16(pfrom, &val, 10, NULL) && val < nChoice) { + if (!epicsParseUInt16(pfrom, &val, dbConvertBase, NULL) && val < nChoice) { *pfield = val; return 0; } diff --git a/modules/database/src/ioc/db/dbFastLinkConv.c b/modules/database/src/ioc/db/dbFastLinkConv.c index 48339f549..890c6732f 100644 --- a/modules/database/src/ioc/db/dbFastLinkConv.c +++ b/modules/database/src/ioc/db/dbFastLinkConv.c @@ -98,7 +98,7 @@ static long cvt_st_c(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - return epicsParseInt8(from, to, 10, &end); + return epicsParseInt8(from, to, dbConvertBase, &end); } /* Convert String to Unsigned Char */ @@ -112,7 +112,7 @@ static long cvt_st_uc(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - return epicsParseUInt8(from, to, 10, &end); + return epicsParseUInt8(from, to, dbConvertBase, &end); } /* Convert String to Short */ @@ -126,7 +126,7 @@ static long cvt_st_s(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - return epicsParseInt16(from, to, 10, &end); + return epicsParseInt16(from, to, dbConvertBase, &end); } /* Convert String to Unsigned Short */ @@ -140,7 +140,7 @@ static long cvt_st_us(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - return epicsParseUInt16(from, to, 10, &end); + return epicsParseUInt16(from, to, dbConvertBase, &end); } /* Convert String to Long */ @@ -154,7 +154,7 @@ static long cvt_st_l(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - return epicsParseInt32(from, to, 10, &end); + return epicsParseInt32(from, to, dbConvertBase, &end); } /* Convert String to Unsigned Long */ @@ -169,7 +169,7 @@ static long cvt_st_ul(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - status = epicsParseUInt32(from, to, 10, &end); + status = epicsParseUInt32(from, to, dbConvertBase, &end); if (status == S_stdlib_noConversion || (!status && (*end == '.' || *end == 'e' || *end == 'E'))) { /* @@ -198,7 +198,7 @@ static long cvt_st_q(const void *f, void *t, const dbAddr *paddr) *to = 0; return 0; } - return epicsParseInt64(from, to, 10, &end); + return epicsParseInt64(from, to, dbConvertBase, &end); } /* Convert String to UInt64 */ @@ -269,7 +269,7 @@ static long cvt_st_e(const void *f, void *t, const dbAddr *paddr) if (!status) { epicsEnum16 val; - status = epicsParseUInt16(from, &val, 10, NULL); + status = epicsParseUInt16(from, &val, dbConvertBase, NULL); if (!status && val < enumStrs.no_str) { *to = val; return 0; @@ -306,7 +306,7 @@ static long cvt_st_menu(const void *f, void *t, const dbAddr *paddr) } } - if (!epicsParseUInt16(from, &val, 10, NULL) && val < nChoice) { + if (!epicsParseUInt16(from, &val, dbConvertBase, NULL) && val < nChoice) { *to = val; return 0; } @@ -339,7 +339,7 @@ static long cvt_st_device(const void *f, void *t, const dbAddr *paddr) } } - if (!epicsParseUInt16(from, &val, 10, NULL) && val < nChoice) { + if (!epicsParseUInt16(from, &val, dbConvertBase, NULL) && val < nChoice) { *to = val; return 0; } diff --git a/modules/database/src/ioc/misc/iocInit.c b/modules/database/src/ioc/misc/iocInit.c index ac89495f0..57f141014 100644 --- a/modules/database/src/ioc/misc/iocInit.c +++ b/modules/database/src/ioc/misc/iocInit.c @@ -31,6 +31,7 @@ #include "epicsPrint.h" #include "epicsSignal.h" #include "epicsThread.h" +#include "epicsString.h" #include "errMdef.h" #include "iocsh.h" #include "taskwd.h" @@ -59,6 +60,7 @@ #include "devSup.h" #include "drvSup.h" #include "epicsRelease.h" +#include "epicsConvert.h" #include "initHooks.h" #include "iocInit.h" #include "link.h" @@ -129,6 +131,16 @@ static int iocBuild_1(void) errlogPrintf("iocBuild: " ERL_ERROR " Aborting, bad database definition (DBD)!\n"); return -1; } + + { + /* fall back to "old" decimal-only conversion if + EPICS_DB_CONVERT_DECIMAL_ONLY is YES (case insensitive). */ + const char* dec_only = getenv("EPICS_DB_CONVERT_DECIMAL_ONLY"); + if (dec_only && epicsStrCaseCmp(dec_only, "YES") == 0) { + dbConvertBase = 10; + } + } + epicsSignalInstallSigHupIgnore(); initHookAnnounce(initHookAtBeginning); diff --git a/modules/libcom/src/misc/epicsConvert.c b/modules/libcom/src/misc/epicsConvert.c index be4290932..380c04f76 100644 --- a/modules/libcom/src/misc/epicsConvert.c +++ b/modules/libcom/src/misc/epicsConvert.c @@ -33,3 +33,5 @@ LIBCOM_API float epicsConvertDoubleToFloat(double value) return (float) value; } + +int dbConvertBase = 0; diff --git a/modules/libcom/src/misc/epicsConvert.h b/modules/libcom/src/misc/epicsConvert.h index 52876dfd8..6be4b5eb6 100644 --- a/modules/libcom/src/misc/epicsConvert.h +++ b/modules/libcom/src/misc/epicsConvert.h @@ -20,6 +20,12 @@ extern "C" { LIBCOM_API float epicsConvertDoubleToFloat(double value); +/* dbConvertBase is used in dbPut and dbGet string to integer conversions. + It defaults to 0 but is set to 10 if the EPICS_DB_CONVERT_DECIMAL_ONLY + environment variable is YES (case insensitive). +*/ +LIBCOM_API extern int dbConvertBase; + #ifdef __cplusplus } #endif