Move all under modules/libcom

This commit is contained in:
Ralph Lange
2018-06-19 11:24:03 +02:00
parent 49f42945b9
commit 833648c977
607 changed files with 0 additions and 101 deletions
+30
View File
@@ -0,0 +1,30 @@
#*************************************************************************
# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
# This is a Makefile fragment, see src/libCom/Makefile.
SRC_DIRS += $(LIBCOM)/error
INC += epicsPrint.h
INC += errMdef.h
INC += errSymTbl.h
INC += errlog.h
Com_SRCS += errlog.c
Com_SRCS += errSymLib.c
Com_SRCS += errSymTbl.c
# For bldErrSymTbl
#
ERR_S_FILES += $(LIBCOM)/osi/devLib.h
ERR_S_FILES += $(LIBCOM)/osi/epicsTime.h
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
CLEANS += errSymTbl.c
+11
View File
@@ -0,0 +1,11 @@
#*************************************************************************
# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
# This is a Makefile fragment, see src/libCom/Makefile.
errSymTbl.c: $(ERR_S_FILES) $(LIBCOM)/error/makeStatTbl.pl
$(PERL) $(LIBCOM)/error/makeStatTbl.pl $(ERR_S_FILES)
+18
View File
@@ -0,0 +1,18 @@
/*************************************************************************\
* 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.
\*************************************************************************/
/*epicsPrint.h */
/*This is now obsolete. Replaced by errlog.h */
#ifndef INCepicsPrintH
#define INCepicsPrintH
#include "errlog.h"
#endif /*INCepicsPrintH*/
+47
View File
@@ -0,0 +1,47 @@
/*************************************************************************\
* Copyright (c) 2014 UChicago Argonne LLC, 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 is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Error Handling definitions */
/*
* Author: Marty Kraimer
* Date: 6-1-90
*/
#ifndef INC_errMdef_H
#define INC_errMdef_H
#define RTN_SUCCESS(STATUS) ((STATUS)==0)
/* Module numbers start above 500 for compatibility with vxWorks errnoLib */
/* FIXME: M_xxx values could be declared as integer variables and set
* at runtime from registration routines; the S_xxx definitions would
* still work with that change, with careful initialization.
*/
/* libCom */
#define M_asLib (501 << 16) /* Access Security */
#define M_bucket (502 << 16) /* Bucket Hash */
#define M_devLib (503 << 16) /* Hardware RegisterAccess */
#define M_stdlib (504 << 16) /* EPICS Standard library */
#define M_pool (505 << 16) /* Thread pool */
#define M_time (506 << 16) /* epicsTime */
/* ioc */
#define M_dbAccess (511 << 16) /* Database Access Routines */
#define M_dbLib (512 << 16) /* Static Database Access */
#define M_drvSup (513 << 16) /* Driver Support */
#define M_devSup (514 << 16) /* Device Support */
#define M_recSup (515 << 16) /* Record Support */
/* cas */
#define M_cas (521 << 16) /* CA server */
#define M_gddFuncTbl (522 << 16) /* gdd jump table */
#define M_casApp (523 << 16) /* CA server application */
#endif /*INC_errMdef_H*/
+282
View File
@@ -0,0 +1,282 @@
/*************************************************************************\
* 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 is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* errSymLib.c
* Author: Marty Kraimer
* Date: 6-1-90
*/
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include "cantProceed.h"
#include "epicsAssert.h"
#include "epicsStdio.h"
#include "errMdef.h"
#include "errSymTbl.h"
#include "ellLib.h"
#include "errlog.h"
#define NHASH 256
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;
/****************************************************************
* 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 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;
}
*phashnode = perrNumNode;
perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode);
}
initialized = 1;
return(0);
}
/****************************************************************
* HASH
* returns the hash index of errNum
****************************************************************/
static epicsUInt16 errhash(long errNum)
{
epicsUInt16 modnum;
epicsUInt16 errnum;
modnum = (unsigned short) (errNum >> 16);
errnum = (unsigned short) (errNum & 0xffff);
return (((modnum - 500) * 20) + errnum) % NHASH;
}
/****************************************************************
* ERRSYMBOLADD
* adds symbols to the master errnumlist as compiled from errSymTbl.c
***************************************************************/
int errSymbolAdd(long errNum, const char *name)
{
ERRNUMNODE *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, size_t bufLength)
{
epicsUInt16 modnum = (statusToDecode >>= 16) & 0xffff;
epicsUInt16 errnum = statusToDecode & 0xffff;
assert(bufLength > 20);
if (modnum == 0) {
epicsSnprintf(pBuf, bufLength, "Error #%u", errnum);
}
else {
epicsSnprintf(pBuf, bufLength, "Error (%u,%u)", modnum, errnum);
}
}
static
const char* errSymLookupInternal(long status)
{
unsigned modNum;
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) {
return pStr;
}
}
else {
unsigned hashInd = errhash(status);
phashnode = (ERRNUMNODE**)&hashtable[hashInd];
pNextNode = *phashnode;
while (pNextNode) {
if (pNextNode->errNum==status){
return pNextNode->message;
}
phashnode = &pNextNode->hashnode;
pNextNode = *phashnode;
}
}
return NULL;
}
const char* errSymMsg(long status)
{
const char* msg = errSymLookupInternal(status);
return msg ? msg : "<Unknown code>";
}
/****************************************************************
* errSymLookup
***************************************************************/
void errSymLookup(long status, char * pBuf, size_t bufLength)
{
const char* msg = errSymLookupInternal(status);
if(msg) {
strncpy(pBuf, msg, bufLength);
pBuf[bufLength-1] = '\0';
return;
}
errRawCopy(status, pBuf, bufLength);
}
/****************************************************************
* errSymDump
***************************************************************/
void errSymDump(void)
{
int i;
int msgcount = 0;
if (!initialized) errSymBld();
msgcount = 0;
printf("errSymDump: number of hash slots = %d\n", NHASH);
for (i = 0; i < NHASH; i++) {
ERRNUMNODE **phashnode = &hashtable[i];
ERRNUMNODE *pNextNode = *phashnode;
int count = 0;
while (pNextNode) {
int modnum = pNextNode->errNum >> 16;
int errnum = pNextNode->errNum & 0xffff;
if (!count++) {
printf("HASHNODE = %d\n", i);
}
printf("\tmod %d num %d \"%s\"\n",
modnum , errnum , pNextNode->message);
phashnode = &pNextNode->hashnode;
pNextNode = *phashnode;
}
msgcount += count;
}
printf("\nerrSymDump: total number of error messages = %d\n", msgcount);
}
/****************************************************************
* errSymTestPrint
***************************************************************/
void errSymTestPrint(long errNum)
{
char message[256];
epicsUInt16 modnum;
epicsUInt16 errnum;
if (!initialized) errSymBld();
message[0] = '\0';
modnum = (epicsUInt16) (errNum >> 16);
errnum = (epicsUInt16) (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 errSymTest(epicsUInt16 modnum, epicsUInt16 begErrNum,
epicsUInt16 endErrNum)
{
long errNum;
epicsUInt16 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);
}
}
+50
View File
@@ -0,0 +1,50 @@
/*************************************************************************\
* Copyright (c) 2012 UChicago Argonne LLC, 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 is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef INC_errSymTbl_H
#define INC_errSymTbl_H
#include <stddef.h>
#include "shareLib.h"
#include "epicsTypes.h"
/* ERRSYMBOL - entry in symbol table */
typedef struct {
long errNum; /* errMessage symbol number */
const char *name; /* pointer to symbol name */
} ERRSYMBOL;
/* ERRSYMTAB - symbol table */
typedef struct {
int nsymbols; /* current number of symbols in table */
ERRSYMBOL *symbols; /* ptr to array of symbol entries */
} ERRSYMTAB;
typedef ERRSYMTAB *ERRSYMTAB_ID;
#ifdef __cplusplus
extern "C" {
#endif
epicsShareFunc void errSymLookup(long status, char *pBuf, size_t bufLength);
epicsShareFunc const char* errSymMsg(long status);
epicsShareFunc void errSymTest(epicsUInt16 modnum, epicsUInt16 begErrNum,
epicsUInt16 endErrNum);
epicsShareFunc void errSymTestPrint(long errNum);
epicsShareFunc int errSymBld(void);
epicsShareFunc int errSymbolAdd(long errNum, const char *name);
epicsShareFunc void errSymDump(void);
#ifdef __cplusplus
}
#endif
#endif /* INC_errSymTbl_H */
+695
View File
@@ -0,0 +1,695 @@
/*************************************************************************\
* Copyright (c) 2010 UChicago Argonne LLC, 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 is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Original Author: Marty Kraimer
* Date: 07JAN1998
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#define epicsExportSharedSymbols
#define ERRLOG_INIT
#include "adjustment.h"
#include "dbDefs.h"
#include "epicsThread.h"
#include "cantProceed.h"
#include "epicsMutex.h"
#include "epicsEvent.h"
#include "epicsInterrupt.h"
#include "errMdef.h"
#include "errSymTbl.h"
#include "ellLib.h"
#include "errlog.h"
#include "epicsStdio.h"
#include "epicsExit.h"
#define BUFFER_SIZE 1280
#define MAX_MESSAGE_SIZE 256
/*Declare storage for errVerbose */
epicsShareDef int errVerbose = 0;
static void errlogExitHandler(void *);
static void errlogThread(void);
static char *msgbufGetFree(int noConsoleMessage);
static void msgbufSetSize(int size); /* Send 'size' chars plus trailing '\0' */
static char *msgbufGetSend(int *noConsoleMessage);
static void msgbufFreeSend(void);
typedef struct listenerNode{
ELLNODE node;
errlogListener listener;
void *pPrivate;
} listenerNode;
/*each message consists of a msgNode immediately followed by the message */
typedef struct msgNode {
ELLNODE node;
char *message;
int length;
int noConsoleMessage;
} msgNode;
static struct {
epicsEventId waitForWork; /*errlogThread waits for this*/
epicsMutexId msgQueueLock;
epicsMutexId listenerLock;
epicsEventId waitForFlush; /*errlogFlush waits for this*/
epicsEventId flush; /*errlogFlush sets errlogThread does a Try*/
epicsMutexId flushLock;
epicsEventId waitForExit; /*errlogExitHandler waits for this*/
int atExit; /*TRUE when errlogExitHandler is active*/
ELLLIST listenerList;
ELLLIST msgQueue;
msgNode *pnextSend;
int errlogInitFailed;
int buffersize;
int maxMsgSize;
int msgNeeded;
int sevToLog;
int toConsole;
FILE *console;
int missedMessages;
char *pbuffer;
} pvtData;
/*
* vsnprintf with truncation message
*/
static int tvsnPrint(char *str, size_t size, const char *format, va_list ap)
{
static const char tmsg[] = "<<TRUNCATED>>\n";
int nchar = epicsVsnprintf(str, size, format ? format : "", ap);
if (nchar >= size) {
if (size > sizeof tmsg)
strcpy(str + size - sizeof tmsg, tmsg);
nchar = size - 1;
}
return nchar;
}
int errlogPrintf(const char *pFormat, ...)
{
va_list pvar;
char *pbuffer;
int nchar;
int isOkToBlock;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogPrintf called from interrupt level\n");
return 0;
}
errlogInit(0);
isOkToBlock = epicsThreadIsOkToBlock();
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
va_start(pvar, pFormat);
nchar = vfprintf(console, pFormat, pvar);
va_end (pvar);
fflush(console);
}
if (pvtData.atExit)
return nchar;
pbuffer = msgbufGetFree(isOkToBlock);
if (!pbuffer)
return 0;
va_start(pvar, pFormat);
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
va_end(pvar);
msgbufSetSize(nchar);
return nchar;
}
int errlogVprintf(const char *pFormat,va_list pvar)
{
int nchar;
char *pbuffer;
int isOkToBlock;
FILE *console;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogVprintf called from interrupt level\n");
return 0;
}
errlogInit(0);
if (pvtData.atExit)
return 0;
isOkToBlock = epicsThreadIsOkToBlock();
pbuffer = msgbufGetFree(isOkToBlock);
if (!pbuffer) {
console = pvtData.console ? pvtData.console : stderr;
vfprintf(console, pFormat, pvar);
fflush(console);
return 0;
}
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "%s", pbuffer);
fflush(console);
}
msgbufSetSize(nchar);
return nchar;
}
int errlogMessage(const char *message)
{
errlogPrintf("%s", message);
return 0;
}
int errlogPrintfNoConsole(const char *pFormat, ...)
{
va_list pvar;
int nchar;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogPrintfNoConsole called from interrupt level\n");
return 0;
}
errlogInit(0);
va_start(pvar, pFormat);
nchar = errlogVprintfNoConsole(pFormat, pvar);
va_end(pvar);
return nchar;
}
int errlogVprintfNoConsole(const char *pFormat, va_list pvar)
{
int nchar;
char *pbuffer;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogVprintfNoConsole called from interrupt level\n");
return 0;
}
errlogInit(0);
if (pvtData.atExit)
return 0;
pbuffer = msgbufGetFree(1);
if (!pbuffer)
return 0;
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
msgbufSetSize(nchar);
return nchar;
}
int errlogSevPrintf(errlogSevEnum severity, const char *pFormat, ...)
{
va_list pvar;
int nchar;
int isOkToBlock;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogSevPrintf called from interrupt level\n");
return 0;
}
errlogInit(0);
if (pvtData.sevToLog > severity)
return 0;
isOkToBlock = epicsThreadIsOkToBlock();
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "sevr=%s ", errlogGetSevEnumString(severity));
va_start(pvar, pFormat);
vfprintf(console, pFormat, pvar);
va_end(pvar);
fflush(console);
}
va_start(pvar, pFormat);
nchar = errlogSevVprintf(severity, pFormat, pvar);
va_end(pvar);
return nchar;
}
int errlogSevVprintf(errlogSevEnum severity, const char *pFormat, va_list pvar)
{
char *pnext;
int nchar;
int totalChar = 0;
int isOkToBlock;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogSevVprintf called from interrupt level\n");
return 0;
}
errlogInit(0);
if (pvtData.atExit)
return 0;
isOkToBlock = epicsThreadIsOkToBlock();
pnext = msgbufGetFree(isOkToBlock);
if (!pnext)
return 0;
nchar = sprintf(pnext, "sevr=%s ", errlogGetSevEnumString(severity));
pnext += nchar; totalChar += nchar;
nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pFormat, pvar);
pnext += nchar; totalChar += nchar;
if (pnext[-1] != '\n') {
strcpy(pnext,"\n");
totalChar++;
}
msgbufSetSize(totalChar);
return nchar;
}
const char * errlogGetSevEnumString(errlogSevEnum severity)
{
errlogInit(0);
if (severity > 3)
return "unknown";
return errlogSevEnumString[severity];
}
void errlogSetSevToLog(errlogSevEnum severity)
{
errlogInit(0);
pvtData.sevToLog = severity;
}
errlogSevEnum errlogGetSevToLog(void)
{
errlogInit(0);
return pvtData.sevToLog;
}
void errlogAddListener(errlogListener listener, void *pPrivate)
{
listenerNode *plistenerNode;
errlogInit(0);
if (pvtData.atExit)
return;
plistenerNode = callocMustSucceed(1,sizeof(listenerNode),
"errlogAddListener");
epicsMutexMustLock(pvtData.listenerLock);
plistenerNode->listener = listener;
plistenerNode->pPrivate = pPrivate;
ellAdd(&pvtData.listenerList,&plistenerNode->node);
epicsMutexUnlock(pvtData.listenerLock);
}
int errlogRemoveListeners(errlogListener listener, void *pPrivate)
{
listenerNode *plistenerNode;
int count = 0;
errlogInit(0);
if (!pvtData.atExit)
epicsMutexMustLock(pvtData.listenerLock);
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
while (plistenerNode) {
listenerNode *pnext = (listenerNode *)ellNext(&plistenerNode->node);
if (plistenerNode->listener == listener &&
plistenerNode->pPrivate == pPrivate) {
ellDelete(&pvtData.listenerList, &plistenerNode->node);
free(plistenerNode);
++count;
}
plistenerNode = pnext;
}
if (!pvtData.atExit)
epicsMutexUnlock(pvtData.listenerLock);
if (count == 0) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console,
"errlogRemoveListeners: No listeners found\n");
}
return count;
}
int eltc(int yesno)
{
errlogInit(0);
errlogFlush();
pvtData.toConsole = yesno;
return 0;
}
int errlogSetConsole(FILE *stream)
{
errlogInit(0);
pvtData.console = stream;
return 0;
}
void errPrintf(long status, const char *pFileName, int lineno,
const char *pformat, ...)
{
va_list pvar;
char *pnext;
int nchar;
int totalChar=0;
int isOkToBlock;
char name[256];
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage("errPrintf called from interrupt level\n");
return;
}
errlogInit(0);
isOkToBlock = epicsThreadIsOkToBlock();
if (status == 0)
status = errno;
if (status > 0) {
errSymLookup(status, name, sizeof(name));
}
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
if (pFileName)
fprintf(console, "filename=\"%s\" line number=%d\n",
pFileName, lineno);
if (status > 0)
fprintf(console, "%s ", name);
va_start(pvar, pformat);
vfprintf(console, pformat, pvar);
va_end(pvar);
fputc('\n', console);
fflush(console);
}
if (pvtData.atExit)
return;
pnext = msgbufGetFree(isOkToBlock);
if (!pnext)
return;
if (pFileName) {
nchar = sprintf(pnext,"filename=\"%s\" line number=%d\n",
pFileName, lineno);
pnext += nchar; totalChar += nchar;
}
if (status > 0) {
nchar = sprintf(pnext,"%s ",name);
pnext += nchar; totalChar += nchar;
}
va_start(pvar, pformat);
nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pformat, pvar);
va_end(pvar);
if (nchar>0) {
pnext += nchar;
totalChar += nchar;
}
strcpy(pnext, "\n");
totalChar++ ; /*include the \n */
msgbufSetSize(totalChar);
}
static void errlogExitHandler(void *pvt)
{
pvtData.atExit = 1;
epicsEventSignal(pvtData.waitForWork);
epicsEventMustWait(pvtData.waitForExit);
}
struct initArgs {
int bufsize;
int maxMsgSize;
};
static void errlogInitPvt(void *arg)
{
struct initArgs *pconfig = (struct initArgs *) arg;
epicsThreadId tid;
pvtData.errlogInitFailed = TRUE;
pvtData.buffersize = pconfig->bufsize;
pvtData.maxMsgSize = pconfig->maxMsgSize;
pvtData.msgNeeded = adjustToWorstCaseAlignment(pvtData.maxMsgSize +
sizeof(msgNode));
ellInit(&pvtData.listenerList);
ellInit(&pvtData.msgQueue);
pvtData.toConsole = TRUE;
pvtData.console = NULL;
pvtData.waitForWork = epicsEventMustCreate(epicsEventEmpty);
pvtData.listenerLock = epicsMutexMustCreate();
pvtData.msgQueueLock = epicsMutexMustCreate();
pvtData.waitForFlush = epicsEventMustCreate(epicsEventEmpty);
pvtData.flush = epicsEventMustCreate(epicsEventEmpty);
pvtData.flushLock = epicsMutexMustCreate();
pvtData.waitForExit = epicsEventMustCreate(epicsEventEmpty);
pvtData.pbuffer = callocMustSucceed(1, pvtData.buffersize,
"errlogInitPvt");
errSymBld(); /* Better not to do this lazily... */
tid = epicsThreadCreate("errlog", epicsThreadPriorityLow,
epicsThreadGetStackSize(epicsThreadStackSmall),
(EPICSTHREADFUNC)errlogThread, 0);
if (tid) {
pvtData.errlogInitFailed = FALSE;
}
}
int errlogInit2(int bufsize, int maxMsgSize)
{
static epicsThreadOnceId errlogOnceFlag = EPICS_THREAD_ONCE_INIT;
struct initArgs config;
if (pvtData.atExit)
return 0;
if (bufsize < BUFFER_SIZE)
bufsize = BUFFER_SIZE;
config.bufsize = bufsize;
if (maxMsgSize < MAX_MESSAGE_SIZE)
maxMsgSize = MAX_MESSAGE_SIZE;
config.maxMsgSize = maxMsgSize;
epicsThreadOnce(&errlogOnceFlag, errlogInitPvt, &config);
if (pvtData.errlogInitFailed) {
fprintf(stderr,"errlogInit failed\n");
exit(1);
}
return 0;
}
int errlogInit(int bufsize)
{
return errlogInit2(bufsize, MAX_MESSAGE_SIZE);
}
void errlogFlush(void)
{
int count;
errlogInit(0);
if (pvtData.atExit)
return;
/*If nothing in queue dont wake up errlogThread*/
epicsMutexMustLock(pvtData.msgQueueLock);
count = ellCount(&pvtData.msgQueue);
epicsMutexUnlock(pvtData.msgQueueLock);
if (count <= 0)
return;
/*must let errlogThread empty queue*/
epicsMutexMustLock(pvtData.flushLock);
epicsEventSignal(pvtData.flush);
epicsEventSignal(pvtData.waitForWork);
epicsEventMustWait(pvtData.waitForFlush);
epicsMutexUnlock(pvtData.flushLock);
}
static void errlogThread(void)
{
listenerNode *plistenerNode;
int noConsoleMessage;
char *pmessage;
epicsAtExit(errlogExitHandler,0);
while (TRUE) {
epicsEventMustWait(pvtData.waitForWork);
while ((pmessage = msgbufGetSend(&noConsoleMessage))) {
epicsMutexMustLock(pvtData.listenerLock);
if (pvtData.toConsole && !noConsoleMessage) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "%s", pmessage);
fflush(console);
}
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
while (plistenerNode) {
(*plistenerNode->listener)(plistenerNode->pPrivate, pmessage);
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
}
epicsMutexUnlock(pvtData.listenerLock);
msgbufFreeSend();
}
if (pvtData.atExit)
break;
if (epicsEventTryWait(pvtData.flush) != epicsEventWaitOK)
continue;
epicsThreadSleep(.2); /*just wait an extra .2 seconds*/
epicsEventSignal(pvtData.waitForFlush);
}
epicsEventSignal(pvtData.waitForExit);
}
static msgNode * msgbufGetNode(void)
{
char *pbuffer = pvtData.pbuffer;
char *pnextFree;
msgNode *pnextSend;
if (ellCount(&pvtData.msgQueue) == 0 ) {
pnextFree = pbuffer; /* Reset if empty */
}
else {
msgNode *pfirst = (msgNode *)ellFirst(&pvtData.msgQueue);
msgNode *plast = (msgNode *)ellLast(&pvtData.msgQueue);
char *plimit = pbuffer + pvtData.buffersize;
pnextFree = plast->message + adjustToWorstCaseAlignment(plast->length);
if (pfirst > plast) {
plimit = (char *)pfirst;
}
else if (pnextFree + pvtData.msgNeeded > plimit) {
pnextFree = pbuffer; /* Hit end, wrap to start */
plimit = (char *)pfirst;
}
if (pnextFree + pvtData.msgNeeded > plimit) {
return 0; /* No room */
}
}
pnextSend = (msgNode *)pnextFree;
pnextSend->message = pnextFree + sizeof(msgNode);
pnextSend->length = 0;
return pnextSend;
}
static char * msgbufGetFree(int noConsoleMessage)
{
msgNode *pnextSend;
if (epicsMutexLock(pvtData.msgQueueLock) != epicsMutexLockOK)
return 0;
if ((ellCount(&pvtData.msgQueue) == 0) && pvtData.missedMessages) {
int nchar;
pnextSend = msgbufGetNode();
nchar = sprintf(pnextSend->message,
"errlog: %d messages were discarded\n", pvtData.missedMessages);
pnextSend->length = nchar + 1;
pvtData.missedMessages = 0;
ellAdd(&pvtData.msgQueue, &pnextSend->node);
}
pvtData.pnextSend = pnextSend = msgbufGetNode();
if (pnextSend) {
pnextSend->noConsoleMessage = noConsoleMessage;
pnextSend->length = 0;
return pnextSend->message; /* NB: msgQueueLock is still locked */
}
++pvtData.missedMessages;
epicsMutexUnlock(pvtData.msgQueueLock);
return 0;
}
static void msgbufSetSize(int size)
{
msgNode *pnextSend = pvtData.pnextSend;
pnextSend->length = size+1;
ellAdd(&pvtData.msgQueue, &pnextSend->node);
epicsMutexUnlock(pvtData.msgQueueLock);
epicsEventSignal(pvtData.waitForWork);
}
static char * msgbufGetSend(int *noConsoleMessage)
{
msgNode *pnextSend;
epicsMutexMustLock(pvtData.msgQueueLock);
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
epicsMutexUnlock(pvtData.msgQueueLock);
if (!pnextSend)
return 0;
*noConsoleMessage = pnextSend->noConsoleMessage;
return pnextSend->message;
}
static void msgbufFreeSend(void)
{
msgNode *pnextSend;
epicsMutexMustLock(pvtData.msgQueueLock);
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
if (!pnextSend) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "errlog: msgbufFreeSend logic error\n");
epicsThreadSuspendSelf();
}
ellDelete(&pvtData.msgQueue, &pnextSend->node);
epicsMutexUnlock(pvtData.msgQueueLock);
}
+91
View File
@@ -0,0 +1,91 @@
/*************************************************************************\
* Copyright (c) 2014 UChicago Argonne LLC, 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 is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef INC_errlog_H
#define INC_errlog_H
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include "shareLib.h"
#include "compilerDependencies.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*errlogListener)(void *pPrivate, const char *message);
typedef enum {
errlogInfo,
errlogMinor,
errlogMajor,
errlogFatal
} errlogSevEnum;
epicsShareExtern int errVerbose;
#ifdef ERRLOG_INIT
epicsShareDef const char *errlogSevEnumString[] = {
"info",
"minor",
"major",
"fatal"
};
#else
epicsShareExtern const char * errlogSevEnumString[];
#endif
/* errMessage is a macro so it can get the file and line number */
#define errMessage(S, PM) \
errPrintf(S, __FILE__, __LINE__, "%s", PM)
/* epicsPrintf and epicsVprintf are old names for errlog routines*/
#define epicsPrintf errlogPrintf
#define epicsVprintf errlogVprintf
epicsShareFunc int errlogPrintf(const char *pformat, ...)
EPICS_PRINTF_STYLE(1,2);
epicsShareFunc int errlogVprintf(const char *pformat, va_list pvar);
epicsShareFunc int errlogSevPrintf(const errlogSevEnum severity,
const char *pformat, ...) EPICS_PRINTF_STYLE(2,3);
epicsShareFunc int errlogSevVprintf(const errlogSevEnum severity,
const char *pformat, va_list pvar);
epicsShareFunc int errlogMessage(const char *message);
epicsShareFunc const char * errlogGetSevEnumString(errlogSevEnum severity);
epicsShareFunc void errlogSetSevToLog(errlogSevEnum severity);
epicsShareFunc errlogSevEnum errlogGetSevToLog(void);
epicsShareFunc void errlogAddListener(errlogListener listener, void *pPrivate);
epicsShareFunc int errlogRemoveListeners(errlogListener listener,
void *pPrivate);
epicsShareFunc int eltc(int yesno);
epicsShareFunc int errlogSetConsole(FILE *stream);
epicsShareFunc int errlogInit(int bufsize);
epicsShareFunc int errlogInit2(int bufsize, int maxMsgSize);
epicsShareFunc void errlogFlush(void);
epicsShareFunc void errPrintf(long status, const char *pFileName, int lineno,
const char *pformat, ...) EPICS_PRINTF_STYLE(4,5);
epicsShareFunc int errlogPrintfNoConsole(const char *pformat, ...)
EPICS_PRINTF_STYLE(1,2);
epicsShareFunc int errlogVprintfNoConsole(const char *pformat,va_list pvar);
epicsShareFunc void errSymLookup(long status, char *pBuf, size_t bufLength);
#ifdef __cplusplus
}
#endif
#endif /*INC_errlog_H*/
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env perl
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2014 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
# makeStatTbl.pl - Create Error Symbol Table
#
# Original Author: Kay-Uwe Kasemir, 1-31-97
#
# SYNOPSIS
# perl makeStatTbl.pl files.h...
#
# DESCRIPTION
# This tool creates a symbol table (ERRSYMTAB) structure which contains the
# names and values of all the status codes defined in the .h files named in
# its input arguments. The status codes must be prefixed with "S_"
# in order to be included in this table.
# Module numbers definitions prefixed with "M_" are also read from the input
# files and included in the output.
#
# This tool's primary use is for creating an error status table used
# by errPrint, and errSymLookup.
#
# FILES
# errMdef.h Module number file for each h directory
# errSymTbl.c Source file generated by tool in the cwd
#
# SEE ALSO: errnoLib(1), symLib(1)
use strict;
use Getopt::Std;
my $tool = 'makeStatTbl.pl';
our ($opt_h);
our $opt_o = 'errSymTbl.c';
$Getopt::Std::OUTPUT_HELP_VERSION = 1;
&HELP_MESSAGE unless getopts('ho:') && @ARGV;
&HELP_MESSAGE if $opt_h;
my (@syms, %vals, %msgs);
# Extract names, values and comments from all S_ and M_ symbol definitions
while (<>) {
chomp;
next unless m/^ \s* \# \s* define \s+ ([SM]_[A-Za-z0-9_]+)
\s+ (.*?) \s* \/ \* \s* (.*?) \s* \* \/ \s* $/x;
push @syms, $1;
$vals{$1} = $2;
$msgs{$1} = $3;
}
open my $out, '>', $opt_o or
die "Can't create $opt_o: $!\n";
print $out <<"END";
/* Generated file $opt_o */
#include "errMdef.h"
#include "errSymTbl.h"
#include "dbDefs.h"
END
my @mods = grep {/^M_/} @syms;
my @errs = grep {/^S_/} @syms;
foreach my $mod (@mods) {
my $val = $vals{$mod};
my $msg = $msgs{$mod};
print $out
"#ifndef $mod\n",
"#define $mod $val /* $msg */\n",
"#endif\n";
}
print $out
"\n",
"static ERRSYMBOL symbols[] = {\n";
foreach my $err (@errs) {
my $msg = escape($msgs{$err});
my $val = $vals{$err};
print $out
" { $val, \"$msg\"},\n";
}
print $out <<"END";
};
static ERRSYMTAB symTbl = {
NELEMENTS(symbols), symbols
};
ERRSYMTAB_ID errSymTbl = &symTbl;
END
sub HELP_MESSAGE {
print STDERR "Usage: $tool [-o file.c] files.h ...\n";
exit 2;
}
sub escape {
$_ = shift;
s/"/\\"/g;
return $_;
}