Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15: rename iocshFind -> iocshFindCommand Added patch Changed function outputs to remove pointer to next function. more whitespace whitespace Added functions to allow access to what functions and variables the ioc shell has registered. missing include ioc/dbStatic: dbFreeBase() don't double free alias'd records ioc/dbStatic: plug leak in dbFreeBase() ioc/dbStatic: whitespace Fix indentation warning from GCC libCom/test: errlog test more verbose libCom: STATIC_ASSERT use c++11 static_assert when possible Check for empty PV names in Perl catools Conflicts: src/std/rec/subRecord.c
This commit is contained in:
@@ -20,13 +20,16 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
HELP_MESSAGE() unless getopts('0:ac:d:e:f:F:g:hnsStw:');
|
||||
HELP_MESSAGE() if $opt_h;
|
||||
|
||||
die "caget: -c option takes a positive number\n"
|
||||
die "caget.pl: -c option takes a positive number\n"
|
||||
unless looks_like_number($opt_c) && $opt_c >= 0;
|
||||
|
||||
die "No pv name specified. ('caget -h' gives help.)\n"
|
||||
die "No pv name specified. ('caget.pl -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
|
||||
my @chans = map { CA->new($_); } @ARGV;
|
||||
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
|
||||
|
||||
die "caget.pl: Please provide at least one non-empty pv name\n"
|
||||
unless @chans;
|
||||
|
||||
eval { CA->pend_io($opt_w); };
|
||||
if ($@) {
|
||||
|
||||
@@ -16,10 +16,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
HELP_MESSAGE() unless getopts('hw:');
|
||||
HELP_MESSAGE() if $opt_h;
|
||||
|
||||
die "No pv name specified. ('cainfo -h' gives help.)\n"
|
||||
die "No pv name specified. ('cainfo.pl -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
|
||||
my @chans = map { CA->new($_); } @ARGV;
|
||||
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
|
||||
|
||||
die "cainfo.pl: Please provide at least one non-empty pv name\n"
|
||||
unless @chans;
|
||||
|
||||
eval {
|
||||
CA->pend_io($opt_w);
|
||||
|
||||
@@ -20,14 +20,17 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
HELP_MESSAGE() unless getopts('0:c:e:f:F:g:hm:nsSw:');
|
||||
HELP_MESSAGE() if $opt_h;
|
||||
|
||||
die "caget: -c option takes a positive number\n"
|
||||
die "camonitor.pl: -c option takes a positive number\n"
|
||||
unless looks_like_number($opt_c) && $opt_c >= 0;
|
||||
|
||||
die "No pv name specified. ('camonitor -h' gives help.)\n"
|
||||
die "No pv name specified. ('camonitor.pl -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
|
||||
my %monitors;
|
||||
my @chans = map { CA->new($_, \&conn_callback); } @ARGV;
|
||||
my @chans = map { CA->new($_, \&conn_callback); } grep { $_ ne '' } @ARGV;
|
||||
|
||||
die "camonitor.pl: Please provide at least one non-empty pv name\n"
|
||||
unless @chans;
|
||||
|
||||
my $fmt = ($opt_F eq ' ') ? "%-30s %s\n" : "%s$opt_F%s\n";
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
HELP_MESSAGE() unless getopts('achlnsStw:');
|
||||
HELP_MESSAGE() if $opt_h;
|
||||
|
||||
die "No pv name specified. ('caput -h' gives help.)\n"
|
||||
die "No pv name specified. ('caput.pl -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
my $pv = shift;
|
||||
die "caput.pl: Empty pv name given.\n"
|
||||
unless $pv ne '';
|
||||
|
||||
die "No value specified. ('caput -h' gives help.)\n"
|
||||
die "No value specified. ('caput.pl -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
|
||||
my $chan = CA->new($pv);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "cantProceed.h"
|
||||
#include "cvtFast.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbmf.h"
|
||||
#include "ellLib.h"
|
||||
@@ -442,8 +443,6 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
dbRecordType *pdbRecordType;
|
||||
dbRecordType *pdbRecordTypeNext;
|
||||
dbFldDes * pdbFldDes;
|
||||
dbRecordNode *pdbRecordNode;
|
||||
dbRecordNode *pdbRecordNodeNext;
|
||||
dbRecordAttribute *pAttribute;
|
||||
dbRecordAttribute *pAttributeNext;
|
||||
devSup *pdevSup;
|
||||
@@ -462,134 +461,136 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
dbGuiGroup *pguiGroupNext;
|
||||
int i;
|
||||
DBENTRY dbentry;
|
||||
|
||||
long status;
|
||||
|
||||
dbInitEntry(pdbbase,&dbentry);
|
||||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
while(pdbRecordType) {
|
||||
pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
|
||||
while(pdbRecordNode) {
|
||||
pdbRecordNodeNext = (dbRecordNode *)ellNext(&pdbRecordNode->node);
|
||||
if(!dbFindRecord(&dbentry,pdbRecordNode->recordname))
|
||||
dbDeleteRecord(&dbentry);
|
||||
pdbRecordNode = pdbRecordNodeNext;
|
||||
}
|
||||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||||
status = dbFirstRecordType(&dbentry);
|
||||
while(!status) {
|
||||
/* dbDeleteRecord() will remove alias or real record node.
|
||||
* For real record nodes, also removes the nodes of all aliases.
|
||||
* This complicates safe traversal, so we re-start iteration
|
||||
* from the first record after each call.
|
||||
*/
|
||||
while((status = dbFirstRecord(&dbentry))==0) {
|
||||
dbDeleteRecord(&dbentry);
|
||||
}
|
||||
assert(status==S_dbLib_recNotFound);
|
||||
status = dbNextRecordType(&dbentry);
|
||||
}
|
||||
dbFinishEntry(&dbentry);
|
||||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
while(pdbRecordType) {
|
||||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||||
free((void *)pdbFldDes->prompt);
|
||||
free((void *)pdbFldDes->name);
|
||||
free((void *)pdbFldDes->extra);
|
||||
free((void *)pdbFldDes->initial);
|
||||
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
|
||||
dbDeviceMenu *pdbDeviceMenu;
|
||||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||||
free((void *)pdbFldDes->prompt);
|
||||
free((void *)pdbFldDes->name);
|
||||
free((void *)pdbFldDes->extra);
|
||||
free((void *)pdbFldDes->initial);
|
||||
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
|
||||
dbDeviceMenu *pdbDeviceMenu;
|
||||
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
pdbFldDes->ftPvt=0;
|
||||
}
|
||||
free((void *)pdbFldDes);
|
||||
}
|
||||
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
while(pdevSup) {
|
||||
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
|
||||
ellDelete(&pdbRecordType->devList,&pdevSup->node);
|
||||
free((void *)pdevSup->name);
|
||||
free((void *)pdevSup->choice);
|
||||
free((void *)pdevSup);
|
||||
pdevSup = pdevSupNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbRecordType->cdefList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pAttribute =
|
||||
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
|
||||
while(pAttribute) {
|
||||
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
|
||||
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
|
||||
free((void *)pAttribute->name);
|
||||
free((void *)pAttribute->pdbFldDes);
|
||||
free(pAttribute);
|
||||
pAttribute = pAttributeNext;
|
||||
}
|
||||
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||||
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
|
||||
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
|
||||
free((void *)pdbRecordType->name);
|
||||
free((void *)pdbRecordType->link_ind);
|
||||
free((void *)pdbRecordType->papsortFldName);
|
||||
free((void *)pdbRecordType->sortFldInd);
|
||||
free((void *)pdbRecordType->papFldDes);
|
||||
free((void *)pdbRecordType);
|
||||
pdbRecordType = pdbRecordTypeNext;
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
pdbFldDes->ftPvt=0;
|
||||
}
|
||||
free((void *)pdbFldDes);
|
||||
}
|
||||
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
while(pdevSup) {
|
||||
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
|
||||
ellDelete(&pdbRecordType->devList,&pdevSup->node);
|
||||
free((void *)pdevSup->name);
|
||||
free((void *)pdevSup->choice);
|
||||
free((void *)pdevSup);
|
||||
pdevSup = pdevSupNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbRecordType->cdefList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pAttribute =
|
||||
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
|
||||
while(pAttribute) {
|
||||
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
|
||||
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
|
||||
free((void *)pAttribute->name);
|
||||
free((void *)pAttribute->pdbFldDes);
|
||||
free(pAttribute);
|
||||
pAttribute = pAttributeNext;
|
||||
}
|
||||
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||||
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
|
||||
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
|
||||
free((void *)pdbRecordType->name);
|
||||
free((void *)pdbRecordType->link_ind);
|
||||
free((void *)pdbRecordType->papsortFldName);
|
||||
free((void *)pdbRecordType->sortFldInd);
|
||||
free((void *)pdbRecordType->papFldDes);
|
||||
free((void *)pdbRecordType);
|
||||
pdbRecordType = pdbRecordTypeNext;
|
||||
}
|
||||
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
|
||||
while(pdbMenu) {
|
||||
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
|
||||
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
|
||||
ellDelete(&pdbbase->menuList,&pdbMenu->node);
|
||||
for(i=0; i< pdbMenu->nChoice; i++) {
|
||||
free((void *)pdbMenu->papChoiceName[i]);
|
||||
free((void *)pdbMenu->papChoiceValue[i]);
|
||||
}
|
||||
free((void *)pdbMenu->papChoiceName);
|
||||
free((void *)pdbMenu->papChoiceValue);
|
||||
free((void *)pdbMenu ->name);
|
||||
free((void *)pdbMenu);
|
||||
pdbMenu = pdbMenuNext;
|
||||
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
|
||||
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
|
||||
ellDelete(&pdbbase->menuList,&pdbMenu->node);
|
||||
for(i=0; i< pdbMenu->nChoice; i++) {
|
||||
free((void *)pdbMenu->papChoiceName[i]);
|
||||
free((void *)pdbMenu->papChoiceValue[i]);
|
||||
}
|
||||
free((void *)pdbMenu->papChoiceName);
|
||||
free((void *)pdbMenu->papChoiceValue);
|
||||
free((void *)pdbMenu ->name);
|
||||
free((void *)pdbMenu);
|
||||
pdbMenu = pdbMenuNext;
|
||||
}
|
||||
pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
|
||||
while(pdrvSup) {
|
||||
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
|
||||
ellDelete(&pdbbase->drvList,&pdrvSup->node);
|
||||
free((void *)pdrvSup->name);
|
||||
free((void *)pdrvSup);
|
||||
pdrvSup = pdrvSupNext;
|
||||
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
|
||||
ellDelete(&pdbbase->drvList,&pdrvSup->node);
|
||||
free((void *)pdrvSup->name);
|
||||
free((void *)pdrvSup);
|
||||
pdrvSup = pdrvSupNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbbase->registrarList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->registrarList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
ptext = ptextNext;
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->registrarList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbbase->functionList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->functionList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
ptext = ptextNext;
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->functionList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pvar = (dbVariableDef *)ellFirst(&pdbbase->variableList);
|
||||
while(pvar) {
|
||||
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
|
||||
ellDelete(&pdbbase->variableList,&pvar->node);
|
||||
free((void *)pvar->name);
|
||||
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
|
||||
ellDelete(&pdbbase->variableList,&pvar->node);
|
||||
free((void *)pvar->name);
|
||||
free((void *)pvar->type);
|
||||
free((void *)pvar);
|
||||
pvar = pvarNext;
|
||||
free((void *)pvar);
|
||||
pvar = pvarNext;
|
||||
}
|
||||
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
|
||||
while(pbrkTable) {
|
||||
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
|
||||
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
|
||||
ellDelete(&pdbbase->bptList,&pbrkTable->node);
|
||||
free(pbrkTable->name);
|
||||
free((void *)pbrkTable->paBrkInt);
|
||||
free((void *)pbrkTable);
|
||||
pbrkTable = pbrkTableNext;
|
||||
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
|
||||
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
|
||||
ellDelete(&pdbbase->bptList,&pbrkTable->node);
|
||||
free(pbrkTable->name);
|
||||
free((void *)pbrkTable->paBrkInt);
|
||||
free((void *)pbrkTable);
|
||||
pbrkTable = pbrkTableNext;
|
||||
}
|
||||
pfilt = (chFilterPlugin *)ellFirst(&pdbbase->filterList);
|
||||
while(pfilt) {
|
||||
|
||||
@@ -42,8 +42,7 @@ epicsShareDef struct dbBase **iocshPpdbbase;
|
||||
* File-local information
|
||||
*/
|
||||
struct iocshCommand {
|
||||
iocshFuncDef const *pFuncDef;
|
||||
iocshCallFunc func;
|
||||
iocshCmdDef def;
|
||||
struct iocshCommand *next;
|
||||
};
|
||||
static struct iocshCommand *iocshCommandHead;
|
||||
@@ -115,10 +114,10 @@ void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef,
|
||||
|
||||
iocshTableLock ();
|
||||
for (l = NULL, p = iocshCommandHead ; p != NULL ; l = p, p = p->next) {
|
||||
i = strcmp (piocshFuncDef->name, p->pFuncDef->name);
|
||||
i = strcmp (piocshFuncDef->name, p->def.pFuncDef->name);
|
||||
if (i == 0) {
|
||||
p->pFuncDef = piocshFuncDef;
|
||||
p->func = func;
|
||||
p->def.pFuncDef = piocshFuncDef;
|
||||
p->def.func = func;
|
||||
iocshTableUnlock ();
|
||||
return;
|
||||
}
|
||||
@@ -141,11 +140,20 @@ void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef,
|
||||
n->next = l->next;
|
||||
l->next = n;
|
||||
}
|
||||
n->pFuncDef = piocshFuncDef;
|
||||
n->func = func;
|
||||
n->def.pFuncDef = piocshFuncDef;
|
||||
n->def.func = func;
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Retrieves a previously registered function with the given name.
|
||||
*/
|
||||
const iocshCmdDef * epicsShareAPI iocshFindCommand(const char *name)
|
||||
{
|
||||
return (iocshCmdDef *) registryFind(iocshCmdID, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the "var" command and any variable(s)
|
||||
*/
|
||||
@@ -204,6 +212,15 @@ void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef)
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves a previously registered variable with the given name.
|
||||
*/
|
||||
const iocshVarDef * epicsShareAPI iocshFindVariable(const char *name)
|
||||
{
|
||||
struct iocshVariable *temp = (iocshVariable *) registryFind(iocshVarID, name);
|
||||
return temp->pVarDef;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free storage created by iocshRegister/iocshRegisterVariable
|
||||
*/
|
||||
@@ -431,7 +448,7 @@ static void helpCallFunc(const iocshArgBuf *args)
|
||||
"Type 'help <command>' to see the arguments of <command>.\n");
|
||||
iocshTableLock ();
|
||||
for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) {
|
||||
piocshFuncDef = pcmd->pFuncDef;
|
||||
piocshFuncDef = pcmd->def.pFuncDef;
|
||||
l = strlen (piocshFuncDef->name);
|
||||
if ((l + col) >= 79) {
|
||||
fputc('\n', epicsGetStdout());
|
||||
@@ -457,7 +474,7 @@ static void helpCallFunc(const iocshArgBuf *args)
|
||||
else {
|
||||
for (int iarg = 1 ; iarg < argc ; iarg++) {
|
||||
for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) {
|
||||
piocshFuncDef = pcmd->pFuncDef;
|
||||
piocshFuncDef = pcmd->def.pFuncDef;
|
||||
if (epicsStrGlobMatch(piocshFuncDef->name, argv[iarg]) != 0) {
|
||||
fputs(piocshFuncDef->name, epicsGetStdout());
|
||||
for (int a = 0 ; a < piocshFuncDef->nargs ; a++) {
|
||||
@@ -811,11 +828,11 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
|
||||
/*
|
||||
* Process arguments and call function
|
||||
*/
|
||||
struct iocshFuncDef const *piocshFuncDef = found->pFuncDef;
|
||||
struct iocshFuncDef const *piocshFuncDef = found->def.pFuncDef;
|
||||
for (int iarg = 0 ; ; ) {
|
||||
if (iarg == piocshFuncDef->nargs) {
|
||||
startRedirect(filename, lineno, redirects);
|
||||
(*found->func)(argBuf);
|
||||
(*found->def.func)(argBuf);
|
||||
break;
|
||||
}
|
||||
if (iarg >= argBufCapacity) {
|
||||
|
||||
@@ -59,10 +59,19 @@ typedef struct iocshFuncDef {
|
||||
|
||||
typedef void (*iocshCallFunc)(const iocshArgBuf *argBuf);
|
||||
|
||||
typedef struct iocshCmdDef {
|
||||
iocshFuncDef const *pFuncDef;
|
||||
iocshCallFunc func;
|
||||
}iocshCmdDef;
|
||||
|
||||
epicsShareFunc void epicsShareAPI iocshRegister(
|
||||
const iocshFuncDef *piocshFuncDef, iocshCallFunc func);
|
||||
epicsShareFunc void epicsShareAPI iocshRegisterVariable (
|
||||
const iocshVarDef *piocshVarDef);
|
||||
epicsShareFunc const iocshCmdDef * epicsShareAPI iocshFindCommand(
|
||||
const char* name);
|
||||
epicsShareFunc const iocshVarDef * epicsShareAPI iocshFindVariable(
|
||||
const char* name);
|
||||
|
||||
/* iocshFree frees storage used by iocshRegister*/
|
||||
/* This should only be called when iocsh is no longer needed*/
|
||||
|
||||
@@ -44,12 +44,15 @@ epicsShareFunc void epicsAssert (const char *pFile, const unsigned line,
|
||||
|
||||
|
||||
/* Compile-time checks */
|
||||
#if __cplusplus>=201103L
|
||||
#define STATIC_ASSERT(expr) static_assert(expr, #expr)
|
||||
#else
|
||||
#define STATIC_JOIN(x, y) STATIC_JOIN2(x, y)
|
||||
#define STATIC_JOIN2(x, y) x ## y
|
||||
#define STATIC_ASSERT(expr) \
|
||||
typedef int STATIC_JOIN(static_assert_failed_at_line_, __LINE__) \
|
||||
[ (expr) ? 1 : -1 ] EPICS_UNUSED
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -102,6 +102,12 @@ static const char prefixexpectedmsg[] = "A message without prefix"
|
||||
static char prefixmsgbuffer[1024];
|
||||
|
||||
|
||||
static
|
||||
void testEqInt_(int lhs, int rhs, const char *LHS, const char *RHS)
|
||||
{
|
||||
testOk(lhs==rhs, "%s (%d) == %s (%d)", LHS, lhs, RHS, rhs);
|
||||
}
|
||||
#define testEqInt(L, R) testEqInt_(L, R, #L, #R);
|
||||
static
|
||||
void logClient(void* raw, const char* msg)
|
||||
{
|
||||
@@ -194,7 +200,7 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", pvt.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 1);
|
||||
testEqInt(pvt.count, 1);
|
||||
|
||||
errlogAddListener(&logClient, &pvt2);
|
||||
|
||||
@@ -204,8 +210,8 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", pvt.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
testOk1(pvt2.count == 1);
|
||||
testEqInt(pvt.count, 2);
|
||||
testEqInt(pvt2.count, 1);
|
||||
|
||||
/* Removes the first listener */
|
||||
testOk(1 == errlogRemoveListeners(&logClient, &pvt),
|
||||
@@ -217,8 +223,8 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", pvt2.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
testOk1(pvt2.count == 2);
|
||||
testEqInt(pvt.count, 2);
|
||||
testEqInt(pvt2.count, 2);
|
||||
|
||||
/* Add the second listener again, then remove both instances */
|
||||
errlogAddListener(&logClient, &pvt2);
|
||||
@@ -228,8 +234,8 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("Something different");
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
testOk1(pvt2.count == 2);
|
||||
testEqInt(pvt.count, 2);
|
||||
testEqInt(pvt2.count, 2);
|
||||
|
||||
/* Re-add one listener */
|
||||
errlogAddListener(&logClient, &pvt);
|
||||
@@ -242,7 +248,7 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", longmsg);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 3);
|
||||
testEqInt(pvt.count, 3);
|
||||
|
||||
pvt.expect = NULL;
|
||||
|
||||
@@ -255,12 +261,12 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", longmsg);
|
||||
epicsThreadSleep(0.1);
|
||||
|
||||
testOk1(pvt.count == 3);
|
||||
testEqInt(pvt.count, 3);
|
||||
|
||||
epicsEventSignal(pvt.jammer);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 4);
|
||||
testEqInt(pvt.count, 4);
|
||||
|
||||
testDiag("Find buffer capacity (%u theoretical)",LOGBUFSIZE);
|
||||
|
||||
@@ -313,7 +319,7 @@ MAIN(epicsErrlogTest)
|
||||
}
|
||||
epicsThreadSleep(0.1); /* should really be a second Event */
|
||||
|
||||
testOk1(pvt.count == 0);
|
||||
testEqInt(pvt.count, 0);
|
||||
|
||||
/* Extract the first 2 messages, 2*(sizeof(msgNode) + 128) bytes */
|
||||
pvt.jam = -2;
|
||||
@@ -321,7 +327,7 @@ MAIN(epicsErrlogTest)
|
||||
epicsThreadSleep(0.1);
|
||||
|
||||
testDiag("Drained %u messages", pvt.count);
|
||||
testOk1(pvt.count == 2);
|
||||
testEqInt(pvt.count, 2);
|
||||
|
||||
/* The buffer has space for 1 more message: sizeof(msgNode) + 256 bytes */
|
||||
errlogPrintfNoConsole("%s", msg); /* Use up that space */
|
||||
@@ -329,13 +335,13 @@ MAIN(epicsErrlogTest)
|
||||
testDiag("Overflow the buffer");
|
||||
errlogPrintfNoConsole("%s", msg);
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
testEqInt(pvt.count, 2);
|
||||
|
||||
epicsEventSignal(pvt.jammer); /* Empty */
|
||||
errlogFlush();
|
||||
|
||||
testDiag("Logged %u messages", pvt.count);
|
||||
testOk1(pvt.count == N+1);
|
||||
testEqInt(pvt.count, N+1);
|
||||
|
||||
/* Clean up */
|
||||
testOk(1 == errlogRemoveListeners(&logClient, &pvt),
|
||||
|
||||
@@ -171,9 +171,10 @@ static long special(DBADDR *paddr, int after)
|
||||
subRecord *prec = (subRecord *)paddr->precord;
|
||||
|
||||
if (!after) {
|
||||
if (prec->snam[0] == 0 && prec->pact)
|
||||
if (prec->snam[0] == 0 && prec->pact) {
|
||||
prec->pact = FALSE;
|
||||
prec->rpro = FALSE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user