This is Unofficial EPICS BASE Doxygen Site
errSymLib.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * errSymLib.c
11  * Author: Marty Kraimer
12  * Date: 6-1-90
13  */
14 
15 #include <string.h>
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <math.h>
20 #include <limits.h>
21 
22 #include "cantProceed.h"
23 #include "epicsAssert.h"
24 #include "epicsStdio.h"
25 #include "errMdef.h"
26 #include "errSymTbl.h"
27 #include "ellLib.h"
28 #include "errlog.h"
29 
30 #define NHASH 256
31 
32 static epicsUInt16 errhash(long errNum);
33 
34 typedef struct errnumnode {
36  long errNum;
38  const char *message;
39  long pad;
40 } ERRNUMNODE;
41 
42 static ELLLIST errnumlist = ELLLIST_INIT;
43 static ERRNUMNODE **hashtable;
44 static int initialized = 0;
45 extern ERRSYMTAB_ID errSymTbl;
46 
47 /****************************************************************
48  * ERRSYMBLD
49  *
50  * Create the normal ell LIST of sorted error messages nodes
51  * Followed by linked hash lists - that link together those
52  * ell nodes that have a common hash number.
53  *
54  ***************************************************************/
55 int errSymBld(void)
56 {
57  ERRSYMBOL *errArray = errSymTbl->symbols;
58  ERRNUMNODE *perrNumNode = NULL;
59  ERRNUMNODE *pNextNode = NULL;
60  ERRNUMNODE **phashnode = NULL;
61  int i;
62  int modnum;
63 
64  if (initialized)
65  return(0);
66 
67  hashtable = (ERRNUMNODE**)callocMustSucceed
68  (NHASH, sizeof(ERRNUMNODE*),"errSymBld");
69  for (i = 0; i < errSymTbl->nsymbols; i++, errArray++) {
70  modnum = errArray->errNum >> 16;
71  if (modnum < 501) {
72  fprintf(stderr, "errSymBld: ERROR - Module number in errSymTbl < 501 was Module=%lx Name=%s\n",
73  errArray->errNum, errArray->name);
74  continue;
75  }
76  if ((errSymbolAdd(errArray->errNum, errArray->name)) < 0) {
77  fprintf(stderr, "errSymBld: ERROR - errSymbolAdd() failed \n");
78  continue;
79  }
80  }
81  perrNumNode = (ERRNUMNODE *) ellFirst(&errnumlist);
82  while (perrNumNode) {
83  /* hash each perrNumNode->errNum */
84  epicsUInt16 hashInd = errhash(perrNumNode->errNum);
85 
86  phashnode = (ERRNUMNODE**)&hashtable[hashInd];
87  pNextNode = (ERRNUMNODE*) *phashnode;
88  /* search for last node (NULL) of hashnode linked list */
89  while (pNextNode) {
90  phashnode = &pNextNode->hashnode;
91  pNextNode = *phashnode;
92  }
93  *phashnode = perrNumNode;
94  perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode);
95  }
96  initialized = 1;
97  return(0);
98 }
99 
100 /****************************************************************
101  * HASH
102  * returns the hash index of errNum
103 ****************************************************************/
104 static epicsUInt16 errhash(long errNum)
105 {
106  epicsUInt16 modnum;
107  epicsUInt16 errnum;
108 
109  modnum = (unsigned short) (errNum >> 16);
110  errnum = (unsigned short) (errNum & 0xffff);
111  return (((modnum - 500) * 20) + errnum) % NHASH;
112 }
113 
114 /****************************************************************
115  * ERRSYMBOLADD
116  * adds symbols to the master errnumlist as compiled from errSymTbl.c
117  ***************************************************************/
118 int errSymbolAdd(long errNum, const char *name)
119 {
121  sizeof(ERRNUMNODE), "errSymbolAdd");
122 
123  pNew->errNum = errNum;
124  pNew->message = name;
125  ellAdd(&errnumlist, (ELLNODE*)pNew);
126  return 0;
127 }
128 
129 /****************************************************************
130  * errRawCopy
131  ***************************************************************/
132 static void errRawCopy(long statusToDecode, char *pBuf, size_t bufLength)
133 {
134  epicsUInt16 modnum = (statusToDecode >>= 16) & 0xffff;
135  epicsUInt16 errnum = statusToDecode & 0xffff;
136 
137  assert(bufLength > 20);
138 
139  if (modnum == 0) {
140  epicsSnprintf(pBuf, bufLength, "Error #%u", errnum);
141  }
142  else {
143  epicsSnprintf(pBuf, bufLength, "Error (%u,%u)", modnum, errnum);
144  }
145 }
146 
147 static
148 const char* errSymLookupInternal(long status)
149 {
150  unsigned modNum;
151  ERRNUMNODE *pNextNode;
152  ERRNUMNODE **phashnode = NULL;
153 
154  if (!initialized)
155  errSymBld();
156 
157  modNum = (unsigned) status;
158  modNum >>= 16;
159  modNum &= 0xffff;
160  if (modNum <= 500) {
161  const char * pStr = strerror ((int) status);
162  if (pStr) {
163  return pStr;
164  }
165  }
166  else {
167  unsigned hashInd = errhash(status);
168  phashnode = (ERRNUMNODE**)&hashtable[hashInd];
169  pNextNode = *phashnode;
170  while (pNextNode) {
171  if (pNextNode->errNum==status){
172  return pNextNode->message;
173  }
174  phashnode = &pNextNode->hashnode;
175  pNextNode = *phashnode;
176  }
177  }
178  return NULL;
179 }
180 
181 const char* errSymMsg(long status)
182 {
183  const char* msg = errSymLookupInternal(status);
184  return msg ? msg : "<Unknown code>";
185 }
186 
187 /****************************************************************
188  * errSymLookup
189  ***************************************************************/
190 void errSymLookup(long status, char * pBuf, size_t bufLength)
191 {
192  const char* msg = errSymLookupInternal(status);
193  if(msg) {
194  strncpy(pBuf, msg, bufLength-1);
195  pBuf[bufLength-1] = '\0';
196  return;
197  }
198  errRawCopy(status, pBuf, bufLength);
199 }
200 
201 /****************************************************************
202  * errSymDump
203  ***************************************************************/
204 void errSymDump(void)
205 {
206  int i;
207  int msgcount = 0;
208 
209  if (!initialized) errSymBld();
210 
211  msgcount = 0;
212  printf("errSymDump: number of hash slots = %d\n", NHASH);
213  for (i = 0; i < NHASH; i++) {
214  ERRNUMNODE **phashnode = &hashtable[i];
215  ERRNUMNODE *pNextNode = *phashnode;
216  int count = 0;
217 
218  while (pNextNode) {
219  int modnum = pNextNode->errNum >> 16;
220  int errnum = pNextNode->errNum & 0xffff;
221 
222  if (!count++) {
223  printf("HASHNODE = %d\n", i);
224  }
225  printf("\tmod %d num %d \"%s\"\n",
226  modnum , errnum , pNextNode->message);
227  phashnode = &pNextNode->hashnode;
228  pNextNode = *phashnode;
229  }
230  msgcount += count;
231  }
232  printf("\nerrSymDump: total number of error messages = %d\n", msgcount);
233 }
234 
235 
236 /****************************************************************
237  * errSymTestPrint
238  ***************************************************************/
240 {
241  char message[256];
242  epicsUInt16 modnum;
243  epicsUInt16 errnum;
244 
245  if (!initialized) errSymBld();
246 
247  message[0] = '\0';
248  modnum = (epicsUInt16) (errNum >> 16);
249  errnum = (epicsUInt16) (errNum & 0xffff);
250  if (modnum < 501) {
251  fprintf(stderr, "Usage: errSymTestPrint(long errNum) \n");
252  fprintf(stderr, "errSymTestPrint: module number < 501 \n");
253  return;
254  }
255  errSymLookup(errNum, message, sizeof(message));
256  if ( message[0] == '\0' ) return;
257  printf("module %hu number %hu message=\"%s\"\n",
258  modnum, errnum, message);
259  return;
260 }
261 
262 /****************************************************************
263  * ERRSYMTEST
264 ****************************************************************/
265 void errSymTest(epicsUInt16 modnum, epicsUInt16 begErrNum,
266  epicsUInt16 endErrNum)
267 {
268  long errNum;
269  epicsUInt16 errnum;
270 
271  if (!initialized) errSymBld();
272  if (modnum < 501)
273  return;
274 
275  /* print range of error messages */
276  for (errnum = begErrNum; errnum <= endErrNum; errnum++) {
277  errNum = modnum << 16;
278  errNum |= (errnum & 0xffff);
279  errSymTestPrint(errNum);
280  }
281 }
long pad
Definition: errSymLib.c:39
ELLNODE node
Definition: errSymLib.c:35
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
An EPICS-specific replacement for ANSI C&#39;s assert.
void errSymTestPrint(long errNum)
Definition: errSymLib.c:239
int i
Definition: scan.c:967
struct errnumnode ERRNUMNODE
unsigned short epicsUInt16
Definition: epicsTypes.h:41
void errSymLookup(long status, char *pBuf, size_t bufLength)
Definition: errSymLib.c:190
ERRSYMTAB_ID errSymTbl
#define printf
Definition: epicsStdio.h:41
long errNum
Definition: errSymLib.c:36
#define NULL
Definition: catime.c:38
ERRSYMBOL * symbols
Definition: errSymTbl.h:27
const char * message
Definition: errSymLib.c:38
#define ELLLIST_INIT
Value of an empty list.
Definition: ellLib.h:63
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
long errNum
Definition: errSymTbl.h:20
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
Definition: cantProceed.c:22
List node type.
Definition: ellLib.h:45
const char * name
Definition: errSymTbl.h:21
int errSymBld(void)
Definition: errSymLib.c:55
int errSymbolAdd(long errNum, const char *name)
Definition: errSymLib.c:118
void errSymDump(void)
Definition: errSymLib.c:204
#define NHASH
Definition: errSymLib.c:30
Routines for code that can&#39;t continue or return after an error.
#define stderr
Definition: epicsStdio.h:32
struct errnumnode * hashnode
Definition: errSymLib.c:37
List header type.
Definition: ellLib.h:56
const char * errSymMsg(long status)
Definition: errSymLib.c:181
int nsymbols
Definition: errSymTbl.h:26
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3
void errSymTest(epicsUInt16 modnum, epicsUInt16 begErrNum, epicsUInt16 endErrNum)
Definition: errSymLib.c:265
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89