diff --git a/modules/libcom/src/error/Makefile b/modules/libcom/src/error/Makefile index 570974b95..f98ed4b24 100644 --- a/modules/libcom/src/error/Makefile +++ b/modules/libcom/src/error/Makefile @@ -26,6 +26,7 @@ ERR_S_FILES += $(LIBCOM)/as/asLib.h ERR_S_FILES += $(LIBCOM)/misc/epicsStdlib.h ERR_S_FILES += $(LIBCOM)/pool/epicsThreadPool.h ERR_S_FILES += $(LIBCOM)/error/errMdef.h +ERR_S_FILES += $(LIBCOM)/error/errSymTbl.h ERR_S_FILES += $(TOP)/modules/database/src/ioc/db/dbAccessDefs.h ERR_S_FILES += $(TOP)/modules/database/src/ioc/dbStatic/dbStaticLib.h diff --git a/modules/libcom/src/error/errMdef.h b/modules/libcom/src/error/errMdef.h index 1a9c47e33..afda69ca9 100644 --- a/modules/libcom/src/error/errMdef.h +++ b/modules/libcom/src/error/errMdef.h @@ -32,6 +32,7 @@ #define M_stdlib (504 << 16) /* EPICS Standard library */ #define M_pool (505 << 16) /* Thread pool */ #define M_time (506 << 16) /* epicsTime */ +#define M_err (507 << 16) /* Error */ /* ioc */ #define M_dbAccess (511 << 16) /* Database Access Routines */ diff --git a/modules/libcom/src/error/errSymLib.c b/modules/libcom/src/error/errSymLib.c index 14fa21904..deb59d4f8 100644 --- a/modules/libcom/src/error/errSymLib.c +++ b/modules/libcom/src/error/errSymLib.c @@ -33,14 +33,12 @@ static epicsUInt16 errhash(long errNum); typedef struct errnumnode { - ELLNODE node; long errNum; struct errnumnode *hashnode; const char *message; long pad; } ERRNUMNODE; -static ELLLIST errnumlist = ELLLIST_INIT; static ERRNUMNODE **hashtable; static int initialized = 0; extern ERRSYMTAB_ID errSymTbl; @@ -56,44 +54,20 @@ extern ERRSYMTAB_ID errSymTbl; int errSymBld(void) { ERRSYMBOL *errArray = errSymTbl->symbols; - ERRNUMNODE *perrNumNode = NULL; - ERRNUMNODE *pNextNode = NULL; - ERRNUMNODE **phashnode = NULL; int i; - int modnum; if (initialized) return(0); hashtable = (ERRNUMNODE**)callocMustSucceed (NHASH, sizeof(ERRNUMNODE*),"errSymBld"); - for (i = 0; i < errSymTbl->nsymbols; i++, errArray++) { - modnum = errArray->errNum >> 16; - if (modnum < 501) { - fprintf(stderr, "errSymBld: ERROR - Module number in errSymTbl < 501 was Module=%lx Name=%s\n", - errArray->errNum, errArray->name); - continue; - } - if ((errSymbolAdd(errArray->errNum, errArray->name)) < 0) { - fprintf(stderr, "errSymBld: ERROR - errSymbolAdd() failed \n"); - continue; - } - } - perrNumNode = (ERRNUMNODE *) ellFirst(&errnumlist); - while (perrNumNode) { - /* hash each perrNumNode->errNum */ - epicsUInt16 hashInd = errhash(perrNumNode->errNum); - phashnode = (ERRNUMNODE**)&hashtable[hashInd]; - pNextNode = (ERRNUMNODE*) *phashnode; - /* search for last node (NULL) of hashnode linked list */ - while (pNextNode) { - phashnode = &pNextNode->hashnode; - pNextNode = *phashnode; + for (i = 0; i < errSymTbl->nsymbols; i++, errArray++) { + if (errSymbolAdd(errArray->errNum, errArray->name)) { + fprintf(stderr, "errSymBld: ERROR - errSymbolAdd() failed \n"); } - *phashnode = perrNumNode; - perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode); } + initialized = 1; return(0); } @@ -114,16 +88,38 @@ static epicsUInt16 errhash(long errNum) /**************************************************************** * ERRSYMBOLADD - * adds symbols to the master errnumlist as compiled from errSymTbl.c + * adds symbols to the global error symbol hash table ***************************************************************/ int errSymbolAdd(long errNum, const char *name) { - ERRNUMNODE *pNew = (ERRNUMNODE*) callocMustSucceed(1, - sizeof(ERRNUMNODE), "errSymbolAdd"); + ERRNUMNODE *pNextNode = NULL; + ERRNUMNODE **phashnode = NULL; + ERRNUMNODE *pNew = NULL; + int modnum = (epicsUInt16) (errNum >> 16); + if (modnum < 501) + return S_err_invCode; + + epicsUInt16 hashInd = errhash(errNum); + + phashnode = (ERRNUMNODE**)&hashtable[hashInd]; + pNextNode = (ERRNUMNODE*) *phashnode; + + /* search for last node (NULL) of hashnode linked list */ + while (pNextNode) { + if (pNextNode->errNum == errNum) { + return S_err_codeExists; + } + phashnode = &pNextNode->hashnode; + pNextNode = *phashnode; + } + + pNew = (ERRNUMNODE*) callocMustSucceed( + 1, sizeof(ERRNUMNODE), "errSymbolAdd"); pNew->errNum = errNum; pNew->message = name; - ellAdd(&errnumlist, (ELLNODE*)pNew); + *phashnode = pNew; + return 0; } diff --git a/modules/libcom/src/error/errSymTbl.h b/modules/libcom/src/error/errSymTbl.h index 66dcf9de8..3c009ee60 100644 --- a/modules/libcom/src/error/errSymTbl.h +++ b/modules/libcom/src/error/errSymTbl.h @@ -16,6 +16,9 @@ #include "libComAPI.h" #include "epicsTypes.h" +#define S_err_invCode (M_err | 1) /* Invalid error symbol code */ +#define S_err_codeExists (M_err | 2) /* Error code already exists */ + /* ERRSYMBOL - entry in symbol table */ typedef struct { long errNum; /* errMessage symbol number */ diff --git a/modules/libcom/test/epicsErrlogTest.c b/modules/libcom/test/epicsErrlogTest.c index 16a04a73c..59a149cb5 100644 --- a/modules/libcom/test/epicsErrlogTest.c +++ b/modules/libcom/test/epicsErrlogTest.c @@ -29,6 +29,7 @@ #include "osiSock.h" #include "fdmgr.h" #include "epicsString.h" +#include "errSymTbl.h" /* private between errlog.c and this test */ LIBCOM_API @@ -197,13 +198,53 @@ void testANSIStrip(void) #undef testEscape } +static void testErrorMessageMatches(long status, const char *expected) +{ + const char *msg = errSymMsg(status); + testOk(strcmp(msg, expected) == 0, + "Error code %ld returns \"%s\", expected message \"%s\"", status, + msg, expected + ); +} + +static void testGettingExistingErrorSymbol() +{ + testErrorMessageMatches(S_err_invCode, "Invalid error symbol code"); +} + +static void testGettingNonExistingErrorSymbol() +{ + long invented_code = (0x7999 << 16) | 0x9998; + testErrorMessageMatches(invented_code, ""); +} + +static void testAddingErrorSymbol() +{ + long invented_code = (0x7999 << 16) | 0x9999; + errSymbolAdd(invented_code, "Invented Error Message"); + testErrorMessageMatches(invented_code, "Invented Error Message"); +} + +static void testAddingInvalidErrorSymbol() +{ + long invented_code = (500 << 16) | 0x1; + testOk(errSymbolAdd(invented_code, "No matter"), + "Adding error symbol with module code < 501 should fail"); +} + +static void testAddingExistingErrorSymbol() +{ + testOk(errSymbolAdd(S_err_invCode, "Duplicate"), + "Adding an error symbol with an existing error code should fail"); +} + MAIN(epicsErrlogTest) { size_t mlen, i, N; char msg[256]; clientPvt pvt, pvt2; - testPlan(48); + testPlan(53); testANSIStrip(); @@ -414,6 +455,12 @@ MAIN(epicsErrlogTest) testLogPrefix(); osiSockRelease(); + testGettingExistingErrorSymbol(); + testGettingNonExistingErrorSymbol(); + testAddingErrorSymbol(); + testAddingInvalidErrorSymbol(); + testAddingExistingErrorSymbol(); + return testDone(); } /*