/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd * errSymLib.c * Author: Marty Kraimer * Date: 6-1-90 * errMessage.c - Handle error messages *************************************************************************** * This must ultimately be replaced by a facility that allows remote * nodes access to the error messages. A message handling communication * task should be written that allows multiple remote nodes to request * notification of all error messages. * For now lets just print messages and last errno via logMsg or printf *************************************************************************** */ #include #include #include #include #include #include #include #define epicsExportSharedSymbols #include "cantProceed.h" #include "epicsAssert.h" #include "dbDefs.h" #include "errMdef.h" #include "errSymTbl.h" #include "ellLib.h" #include "errlog.h" static unsigned short errhash(long errNum); typedef struct errnumnode { ELLNODE node; long errNum; struct errnumnode *hashnode; char *message; long pad; } ERRNUMNODE; #define NHASH 256 static ELLLIST errnumlist = ELLLIST_INIT; static ERRNUMNODE **hashtable; static int initialized = FALSE; extern ERRSYMTAB_ID errSymTbl; /**************************************************************** * ERRSYMBLD * * Create the normal ell LIST of sorted error messages nodes * Followed by linked hash lists - that link together those * ell nodes that have a common hash number. * ***************************************************************/ int epicsShareAPI errSymBld(void) { ERRSYMBOL *errArray = errSymTbl->symbols; ERRNUMNODE *perrNumNode = NULL; ERRNUMNODE *pNextNode = NULL; ERRNUMNODE **phashnode = NULL; int i; int modnum; unsigned short hashInd; 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 */ 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; } *phashnode = perrNumNode; perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode); } initialized = TRUE; return(0); } /**************************************************************** * HASH * returns the hash index of errNum ****************************************************************/ static unsigned short errhash(long errNum) { unsigned short modnum; unsigned short errnum; modnum = (unsigned short) (errNum >> 16); errnum = (unsigned short) (errNum & 0xffff); return((unsigned short)(((modnum - 500) * 20) + errnum) % NHASH); } /**************************************************************** * ERRSYMBOLADD * adds symbols to the master errnumlist as compiled from errSymTbl.c ***************************************************************/ int epicsShareAPI errSymbolAdd (long errNum,char *name) { ERRNUMNODE *pNew; pNew = (ERRNUMNODE*)callocMustSucceed(1,sizeof(ERRNUMNODE),"errSymbolAdd"); pNew->errNum = errNum; pNew->message = name; ellAdd(&errnumlist,(ELLNODE*)pNew); return(0); } /**************************************************************** * errRawCopy ***************************************************************/ static void errRawCopy ( long statusToDecode, char *pBuf, unsigned bufLength ) { unsigned modnum, errnum; unsigned nChar; int status; modnum = (unsigned) statusToDecode; modnum >>= 16; modnum &= 0xffff; errnum = (unsigned) statusToDecode; errnum &= 0xffff; if ( bufLength ) { if ( modnum == 0 ) { if ( bufLength > 11 ) { status = sprintf ( pBuf, "err = %d", errnum ); } else if ( bufLength > 5 ) { status = sprintf ( pBuf, "%d", errnum ); } else { strncpy ( pBuf,"", bufLength ); pBuf[bufLength-1] = '\0'; status = 0; } } else { if ( bufLength > 50 ) { status = sprintf ( pBuf, "status = (%d,%d) not in symbol table", modnum, errnum ); } else if ( bufLength > 25 ) { status = sprintf ( pBuf, "status = (%d,%d)", modnum, errnum ); } else if ( bufLength > 15 ) { status = sprintf ( pBuf, "(%d,%d)", modnum, errnum ); } else { strncpy ( pBuf, "", bufLength); pBuf[bufLength-1] = '\0'; status = 0; } } assert (status >= 0 ); nChar = (unsigned) status; assert ( nChar < bufLength ); } } /**************************************************************** * errSymLookup ***************************************************************/ void epicsShareAPI errSymLookup (long status, char * pBuf, unsigned bufLength) { unsigned modNum; unsigned hashInd; ERRNUMNODE *pNextNode; ERRNUMNODE **phashnode = NULL; if(!initialized) errSymBld(); modNum = (unsigned) status; modNum >>= 16; modNum &= 0xffff; if ( modNum <= 500 ) { const char * pStr = strerror ((int) status); if ( pStr ) { strncpy(pBuf, pStr,bufLength); pBuf[bufLength-1] = '\0'; return; } } else { hashInd = errhash(status); phashnode = (ERRNUMNODE**)&hashtable[hashInd]; pNextNode = *phashnode; while(pNextNode) { if(pNextNode->errNum==status){ strncpy(pBuf, pNextNode->message, bufLength); pBuf[bufLength-1] = '\0'; return; } phashnode = &pNextNode->hashnode; pNextNode = *phashnode; } } errRawCopy(status, pBuf, bufLength); } /**************************************************************** * errSymDump ***************************************************************/ void epicsShareAPI errSymDump(void) { ERRNUMNODE **phashnode = NULL; ERRNUMNODE *pNextNode; int i; int modnum; int errnum; int msgcount; int firstTime; if (!initialized) errSymBld(); msgcount = 0; printf("errSymDump: number of hash slots=%d\n", NHASH); for ( i=0; i < NHASH; i++) { phashnode = &hashtable[i]; pNextNode = *phashnode; firstTime=1; while (pNextNode) { if (firstTime) { printf("HASHNODE=%d\n", i); firstTime=0; } modnum = pNextNode->errNum >> 16; errnum = pNextNode->errNum & 0xffff; printf("\tmod %d num %d \"%s\"\n" , modnum , errnum , pNextNode->message); msgcount++; phashnode = &pNextNode->hashnode; pNextNode = *phashnode; } } printf("\nerrSymDump: total number of error messages=%d\n", msgcount); } /**************************************************************** * errSymTestPrint ***************************************************************/ void epicsShareAPI errSymTestPrint(long errNum) { char message[256]; unsigned short modnum; unsigned short errnum; if (!initialized) errSymBld(); message[0] = '\0'; modnum = (unsigned short) (errNum >> 16); errnum = (unsigned short) (errNum & 0xffff); if (modnum < 501) { fprintf(stderr, "Usage: errSymTestPrint(long errNum) \n"); fprintf(stderr, "errSymTestPrint: module number < 501 \n"); return; } errSymLookup(errNum, message, sizeof(message)); if ( message[0] == '\0' ) return; printf("module %hu number %hu message=\"%s\"\n", modnum, errnum, message); return; } /**************************************************************** * ERRSYMTEST ****************************************************************/ void epicsShareAPI errSymTest(unsigned short modnum, unsigned short begErrNum, unsigned short endErrNum) { long errNum; unsigned short errnum; if(!initialized) errSymBld(); if (modnum < 501) return; /* print range of error messages */ for (errnum = begErrNum; errnum <= endErrNum; errnum++) { errNum = modnum << 16; errNum |= (errnum & 0xffff); errSymTestPrint(errNum); } }