From 46f046c751ab7e9f2eeded2d96760a698580b5cf Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Tue, 15 Jul 2025 10:05:55 +0200 Subject: [PATCH] allow hex and octal strings in dbPut Setting EPICS_DB_CONVERT_DECIMAL_ONLY turns dbPut/dbGet string to integer conversions back the the old decimal only policy. --- documentation/new-notes/PR-678.md | 13 ++++++++ modules/database/src/ioc/db/dbConvert.c | 34 ++++++++++---------- modules/database/src/ioc/db/dbFastLinkConv.c | 20 ++++++------ modules/database/src/ioc/misc/iocInit.c | 11 +++++++ 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..bd95b4c08 --- /dev/null +++ b/documentation/new-notes/PR-678.md @@ -0,0 +1,13 @@ +### 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 anything except the empty string or +strings starting with `n`, `N`, `f`, `F` or `0` 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..fb39688cc 100644 --- a/modules/database/src/ioc/misc/iocInit.c +++ b/modules/database/src/ioc/misc/iocInit.c @@ -59,6 +59,7 @@ #include "devSup.h" #include "drvSup.h" #include "epicsRelease.h" +#include "epicsConvert.h" #include "initHooks.h" #include "iocInit.h" #include "link.h" @@ -129,6 +130,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 set and does not look like meaning no/false/0 */ + const char* dec_only = getenv("EPICS_DB_CONVERT_DECIMAL_ONLY"); + if (dec_only && *dec_only && !strchr("nNfF0", *dec_only)) { + 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..82e0dfcf0 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 set. +*/ +LIBCOM_API extern int dbConvertBase; + #ifdef __cplusplus } #endif