Merge branch '7.0' into PSI-7.0

This commit is contained in:
2024-08-07 17:30:04 +02:00
72 changed files with 1441 additions and 1032 deletions
+1 -1
View File
@@ -23,4 +23,4 @@ dbCore_SRCS += asIocRegister.c
PROD_HOST += ascheck
ascheck_SRCS = ascheck.c
ascheck_LIBS = dbCore ca Com
ascheck_LIBS = dbCore ca
+5
View File
@@ -225,6 +225,11 @@ static void asCaTask(void)
if(asCaDebug) printf("asCaTask has cleared all channels\n");
epicsEventSignal(asCaTaskWait);
}
/* ATM never reached, just a placeholder */
cantProceed("Unreachable. Perpetual thread.");
taskwdRemove(0);
}
void asCaStart(void)
+1 -1
View File
@@ -112,7 +112,7 @@ void dbSpcAsRegisterCallback(SPC_ASCALLBACK func)
long dbPutSpecial(DBADDR *paddr,int pass)
{
long int (*pspecial)()=NULL;
long int (*pspecial)(struct dbAddr *, int)=NULL;
rset *prset;
dbCommon *precord = paddr->precord;
long status=0;
+6 -3
View File
@@ -225,6 +225,7 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
assert(plink->type==CA_LINK);
pca = (caLink *)plink->value.pv_link.pvt;
caLinkInc(pca);
epicsMutexMustLock(pca->lock);
assert(!pca->monitor && !pca->connect && !pca->userPvt);
@@ -239,6 +240,8 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
dbScanUnlock(plink->precord);
epicsEventMustWait(evt);
/* ensure worker has finished executing */
dbCaSync();
dbScanLock(plink->precord);
epicsMutexMustLock(pca->lock);
@@ -250,6 +253,7 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
epicsEventDestroy(evt);
epicsMutexUnlock(pca->lock);
caLinkDec(pca);
dbScanUnlock(plink->precord);
}
@@ -287,16 +291,15 @@ void dbCaSync(void)
epicsEventMustWait(wake);
/* Worker holds workListLock when calling epicsEventMustTrigger()
* we cycle through workListLock to ensure worker call to
* we hold workListLock to ensure worker call to
* epicsEventMustTrigger() returns before we destroy the event.
*/
epicsMutexMustLock(workListLock);
epicsMutexUnlock(workListLock);
assert(templink.refcount==1);
epicsMutexDestroy(templink.lock);
epicsEventDestroy(wake);
epicsMutexUnlock(workListLock);
}
void dbCaCallbackProcess(void *userPvt)
+21 -3
View File
@@ -7,20 +7,38 @@
* EPICS Base is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbConvertFast.h */
/** @file dbConvertFast.h
* @brief Data conversion for scalar values
*
* The typedef FASTCONVERTFUNC is defined in link.h as:
* @code
* long convert(const void *from, void *to, const struct dbAddr *paddr);
* @endcode
*
* The arrays declared here provide pointers to the fast conversion
* routine where the first array index is the data type for the first
* "from" pointer arg, and the second array index is the data type for
* the second "to" pointer arg. The array index values are a subset of
* the DBF_ enum values defined in dbFldTypes.h
*/
#ifndef INCdbConvertFasth
#define INCdbConvertFasth
#include "dbFldTypes.h"
#include "dbCoreAPI.h"
#include "link.h"
#ifdef __cplusplus
extern "C" {
#endif
DBCORE_API extern long (*dbFastGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1])();
DBCORE_API extern long (*dbFastPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1])();
/** Function pointers for get conversions */
DBCORE_API extern const FASTCONVERTFUNC
dbFastGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1];
/** Function pointers for put conversions */
DBCORE_API extern const FASTCONVERTFUNC
dbFastPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1];
#ifdef __cplusplus
}
+2 -4
View File
@@ -19,8 +19,6 @@
#include "dbConvertFast.h"
#include "dbConvertJSON.h"
typedef long (*FASTCONVERT)();
typedef struct parseContext {
int depth;
short dbrType;
@@ -42,7 +40,7 @@ static int dbcj_boolean(void *ctx, int val) {
static int dbcj_integer(void *ctx, long long num) {
parseContext *parser = (parseContext *) ctx;
epicsInt64 val64 = num;
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_INT64][parser->dbrType];
FASTCONVERTFUNC conv = dbFastPutConvertRoutine[DBF_INT64][parser->dbrType];
if (parser->elems > 0) {
conv(&val64, parser->pdest, NULL);
@@ -54,7 +52,7 @@ static int dbcj_integer(void *ctx, long long num) {
static int dbcj_double(void *ctx, double num) {
parseContext *parser = (parseContext *) ctx;
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
FASTCONVERTFUNC conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
if (parser->elems > 0) {
conv(&num, parser->pdest, NULL);
+2 -2
View File
@@ -98,8 +98,8 @@ struct event_user {
unsigned char extra_labor; /* if set call extra labor func */
unsigned char flowCtrlMode; /* replace existing monitor */
unsigned char extraLaborBusy;
void (*init_func)();
epicsThreadId init_func_arg;
void (*init_func)(void *);
void *init_func_arg;
};
typedef struct {
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -133,7 +133,7 @@ void dbInitLink(struct link *plink, short dbfType)
plink->value.pv_link.pvlMask |= pvlOptFWD;
}
else {
errlogPrintf("Forward-link uses Channel Access "
errlogPrintf(ERL_WARNING ": Forward-link uses Channel Access "
"without pointing to PROC field\n"
" %s.%s => %s\n",
precord->name, dbLinkFieldName(plink),
+2 -2
View File
@@ -307,7 +307,7 @@ typedef struct lset {
*
* @param plink the link
* @param dbrType data type code
* @param pbuffer where to put the value
* @param pbuffer where the data is
* @param nRequest number of elements to send
* @returns status value
*/
@@ -324,7 +324,7 @@ typedef struct lset {
*
* @param plink the link
* @param dbrType data type code
* @param pbuffer where to put the value
* @param pbuffer where the data is
* @param nRequest number of elements to send
* @returns status value
*/
+1 -1
View File
@@ -918,7 +918,7 @@ long dblsr(char *recordname,int level)
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[link]];
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
if(plink->type != DB_LINK) continue;
pdbAddr = (DBADDR *)(plink->value.pv_link.pvt);
pdbAddr = &((dbChannel *)(plink->value.pv_link.pvt))->addr;
printf("\t%s",pdbFldDes->name);
if(pdbFldDes->field_type==DBF_INLINK) {
printf("\t INLINK");
+3 -3
View File
@@ -155,7 +155,7 @@ void scanStop(void)
{
int i;
if (scanCtl == ctlExit) return;
if (scanCtl == ctlInit || scanCtl == ctlExit) return;
scanCtl = ctlExit;
interruptAccept = FALSE;
@@ -264,7 +264,7 @@ void scanAdd(struct dbCommon *precord)
} else if (scan == menuScanI_O_Intr) {
ioscan_head *piosh = NULL;
int prio;
DEVSUPFUN get_ioint_info;
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
if (precord->dset == NULL){
recGblRecordError(-1, (void *)precord,
@@ -332,7 +332,7 @@ void scanDelete(struct dbCommon *precord)
} else if (scan == menuScanI_O_Intr) {
ioscan_head *piosh = NULL;
int prio;
DEVSUPFUN get_ioint_info;
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
if (precord->dset==NULL) {
recGblRecordError(-1, (void *)precord,
+1 -1
View File
@@ -680,7 +680,7 @@ long dbtpf(const char *pname, const char *pvalue)
long dbior(const char *pdrvName,int interest_level)
{
drvSup *pdrvSup;
struct drvet *pdrvet;
drvet *pdrvet;
dbRecordType *pdbRecordType;
if (!pdbbase) {
+1 -1
View File
@@ -62,7 +62,7 @@ void recGblRecordError(long status, void *pdbc,
dbCommon *precord = pdbc;
char errMsg[256] = "";
if (status)
if ( status>0 )
errSymLookup(status, errMsg, sizeof(errMsg));
errlogPrintf("recGblRecordError: %s %s PV: %s\n",
@@ -11,6 +11,8 @@
SRC_DIRS += $(IOCDIR)/dbStatic
USR_CFLAGS += -DUSE_TYPED_DRVET
INC += dbBase.h
INC += dbFldTypes.h
INC += dbStaticLib.h
+4 -3
View File
@@ -21,6 +21,7 @@
#include "dbDefs.h"
#include "recSup.h"
#include "devSup.h"
#include "drvSup.h"
typedef struct dbMenu {
ELLNODE node;
@@ -33,7 +34,7 @@ typedef struct dbMenu {
typedef struct drvSup {
ELLNODE node;
char *name;
struct drvet *pdrvet;
drvet *pdrvet;
}drvSup;
typedef struct devSup {
@@ -119,7 +120,7 @@ typedef struct dbRecordNode {
ELLLIST infoList; /*LIST head of info nodes*/
int flags;
/** Parse order of this record()
* @since UNRELEASED
* @since 7.0.8.1
*/
unsigned order;
struct dbRecordNode *aliasedRecnode; /* NULL unless flags|DBRN_FLAGS_ISALIAS */
@@ -189,7 +190,7 @@ typedef struct dbBase {
short ignoreMissingMenus;
short loadCdefs;
/** Total number of records.
* @since UNRELEASED
* @since 7.0.8.1
*/
unsigned no_records;
}dbBase;
@@ -225,7 +225,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
char **macPairs;
if (ellCount(&tempList)) {
epicsPrintf("dbReadCOM: Parser stack dirty %d\n", ellCount(&tempList));
fprintf(stderr, ERL_WARNING ": dbReadCOM: Parser stack dirty %d\n", ellCount(&tempList));
}
if (getIocState() != iocVoid) {
@@ -250,7 +250,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
if (substitutions == NULL)
substitutions = "";
if(macCreateHandle(&macHandle,NULL)) {
epicsPrintf("macCreateHandle error\n");
fprintf(stderr, ERL_ERROR ": macCreateHandle failed\n");
status = -1;
goto cleanup;
}
@@ -294,7 +294,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
status = pvt_yy_parse();
if (ellCount(&tempList) && !yyAbort)
epicsPrintf("dbReadCOM: Parser stack dirty w/o error. %d\n", ellCount(&tempList));
fprintf(stderr, ERL_WARNING ": dbReadCOM: Parser stack dirty w/o error. %d\n", ellCount(&tempList));
while (ellCount(&tempList))
popFirstTemp(); /* Memory leak on parser failure */
@@ -401,15 +401,15 @@ static void dbIncludePrint(void)
inputFile *pinputFile = pinputFileNow;
while (pinputFile) {
epicsPrintf(" in");
fprintf(stderr, " in");
if (pinputFile->path)
epicsPrintf(" path \"%s\" ",pinputFile->path);
fprintf(stderr, " path \"%s\" ",pinputFile->path);
if (pinputFile->filename) {
epicsPrintf(" file \"%s\"",pinputFile->filename);
fprintf(stderr, " file \"%s\"",pinputFile->filename);
} else {
epicsPrintf(" standard input");
fprintf(stderr, " standard input");
}
epicsPrintf(" line %d\n",pinputFile->line_num);
fprintf(stderr, " line %d\n",pinputFile->line_num);
pinputFile = (inputFile *)ellPrevious(&pinputFile->node);
}
return;
@@ -434,7 +434,7 @@ static void dbIncludeNew(char *filename)
pinputFile->filename = macEnvExpand(filename);
pinputFile->path = dbOpenFile(savedPdbbase, pinputFile->filename, &fp);
if (!fp) {
epicsPrintf("Can't open include file \"%s\"\n", filename);
fprintf(stderr, "Can't open include file \"%s\"\n", filename);
yyerror(NULL);
free((void *)pinputFile->filename);
free((void *)pinputFile);
@@ -696,7 +696,7 @@ static void dbRecordtypeEmpty(void)
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbRecordType = ptempListNode->item;
epicsPrintf("Declaration of recordtype(%s) preceeded full definition.\n",
fprintf(stderr, "Declaration of recordtype(%s) preceeded full definition.\n",
pdbRecordType->name);
yyerrorAbort(NULL);
}
@@ -801,7 +801,7 @@ static void dbDevice(char *recordtype,char *linktype,
int i,link_type;
pgphentry = gphFind(savedPdbbase->pgpHash,recordtype,&savedPdbbase->recordTypeList);
if(!pgphentry) {
epicsPrintf("Record type \"%s\" not found for device \"%s\"\n",
fprintf(stderr, "Record type \"%s\" not found for device \"%s\"\n",
recordtype, choicestring);
yyerror(NULL);
return;
@@ -814,7 +814,7 @@ static void dbDevice(char *recordtype,char *linktype,
}
}
if(link_type==-1) {
epicsPrintf("Bad link type \"%s\" for device \"%s\"\n",
fprintf(stderr, "Bad link type \"%s\" for device \"%s\"\n",
linktype, choicestring);
yyerror(NULL);
return;
@@ -1077,16 +1077,16 @@ int dbRecordNameValidate(const char *name)
if(i==0) {
/* first character restrictions */
if(c=='-' || c=='+' || c=='[' || c=='{') {
errlogPrintf("Warning: Record/Alias name '%s' should not begin with '%c'\n", name, c);
fprintf(stderr, "Warning: Record/Alias name '%s' should not begin with '%c'\n", name, c);
}
}
/* any character restrictions */
if(c < ' ') {
errlogPrintf("Warning: Record/Alias name '%s' should not contain non-printable 0x%02x\n",
fprintf(stderr, "Warning: Record/Alias name '%s' should not contain non-printable 0x%02x\n",
name, c);
} else if(c==' ' || c=='\t' || c=='"' || c=='\'' || c=='.' || c=='$') {
epicsPrintf(ERL_ERROR ": Bad character '%c' in Record/Alias name \"%s\"\n",
fprintf(stderr, ERL_ERROR ": Bad character '%c' in Record/Alias name \"%s\"\n",
c, name);
yyerrorAbort(NULL);
return 1;
@@ -1113,7 +1113,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
status = dbFindRecord(pdbentry, name);
if (status == 0)
return; /* done */
epicsPrintf(ERL_ERROR ": Record \"%s\" not found\n", name);
fprintf(stderr, ERL_ERROR ": Record \"%s\" not found\n", name);
yyerror(NULL);
duplicate = TRUE;
return;
@@ -1121,7 +1121,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
status = dbFindRecordType(pdbentry, recordType);
if (status) {
epicsPrintf("Record \"%s\" is of unknown type \"%s\"\n",
fprintf(stderr, "Record \"%s\" is of unknown type \"%s\"\n",
name, recordType);
yyerrorAbort(NULL);
return;
@@ -1132,14 +1132,14 @@ static void dbRecordHead(char *recordType, char *name, int visible)
status = dbCreateRecord(pdbentry,name);
if (status == S_dbLib_recExists) {
if (strcmp(recordType, dbGetRecordTypeName(pdbentry)) != 0) {
epicsPrintf(ERL_ERROR ": Record \"%s\" of type \"%s\" redefined with new type "
fprintf(stderr, ERL_ERROR ": Record \"%s\" of type \"%s\" redefined with new type "
"\"%s\"\n", name, dbGetRecordTypeName(pdbentry), recordType);
yyerror(NULL);
duplicate = TRUE;
return;
}
else if (dbRecordsOnceOnly) {
epicsPrintf(ERL_ERROR ": Record \"%s\" already defined and dbRecordsOnceOnly set.\n"
fprintf(stderr, ERL_ERROR ": Record \"%s\" already defined and dbRecordsOnceOnly set.\n"
"Used record type \"*\" to append.\n",
name);
yyerror(NULL);
@@ -1147,7 +1147,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
}
}
else if (status) {
epicsPrintf("Can't create record \"%s\" of type \"%s\"\n",
fprintf(stderr, "Can't create record \"%s\" of type \"%s\"\n",
name, recordType);
yyerrorAbort(NULL);
}
@@ -1167,7 +1167,7 @@ static void dbRecordField(char *name,char *value)
pdbentry = ptempListNode->item;
status = dbFindField(pdbentry,name);
if (status) {
epicsPrintf("%s Record \"%s\" does not have a field \"%s\"\n",
fprintf(stderr, "%s Record \"%s\" does not have a field \"%s\"\n",
dbGetRecordTypeName(pdbentry), dbGetRecordName(pdbentry), name);
if(dbGetRecordName(pdbentry)) {
DBENTRY temp;
@@ -1183,17 +1183,17 @@ static void dbRecordField(char *name,char *value)
}
dbFinishEntry(&temp);
if(bestSim>0.0) {
epicsPrintf(" Did you mean \"%s\"?", bestFld->name);
fprintf(stderr, " Did you mean \"%s\"?", bestFld->name);
if(bestFld->prompt)
epicsPrintf(" (%s)", bestFld->prompt);
epicsPrintf("\n");
fprintf(stderr, " (%s)", bestFld->prompt);
fprintf(stderr, "\n");
}
}
yyerror(NULL);
return;
}
if (pdbentry->indfield == 0) {
epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
fprintf(stderr, "Can't set \"NAME\" field of record \"%s\"\n",
dbGetRecordName(pdbentry));
yyerror(NULL);
return;
@@ -1211,7 +1211,7 @@ static void dbRecordField(char *name,char *value)
char msg[128];
errSymLookup(status, msg, sizeof(msg));
epicsPrintf("Can't set \"%s.%s\" to \"%s\" %s : %s\n",
fprintf(stderr, "Can't set \"%s.%s\" to \"%s\" %s : %s\n",
dbGetRecordName(pdbentry), name, value, pdbentry->message ? pdbentry->message : "", msg);
dbPutStringSuggest(pdbentry, value);
yyerror(NULL);
@@ -1242,7 +1242,7 @@ static void dbRecordInfo(char *name, char *value)
status = dbPutInfo(pdbentry,name,value);
if (status) {
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
fprintf(stderr, "Can't set \"%s\" info \"%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
yyerror(NULL);
return;
@@ -1263,7 +1263,7 @@ static void dbRecordAlias(char *name)
pdbentry = ptempListNode->item;
status = dbCreateAlias(pdbentry, name);
if (status) {
epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
fprintf(stderr, "Can't create alias \"%s\" for \"%s\"\n",
name, dbGetRecordName(pdbentry));
yyerror(NULL);
return;
@@ -1280,12 +1280,12 @@ static void dbAlias(char *name, char *alias)
dbInitEntry(savedPdbbase, pdbEntry);
if (dbFindRecord(pdbEntry, name)) {
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
fprintf(stderr, "Alias \"%s\" refers to unknown record \"%s\"\n",
alias, name);
yyerror(NULL);
}
else if (dbCreateAlias(pdbEntry, alias)) {
epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
fprintf(stderr, "Can't create alias \"%s\" referring to \"%s\"\n",
alias, name);
yyerror(NULL);
}
+4 -4
View File
@@ -8,7 +8,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
%{
static int yyerror();
static int yyerror(char *str);
static int yy_start;
static long pvt_yy_parse(void);
static int yyFailed = 0;
@@ -370,11 +370,11 @@ json_value: jsonNULL { $$ = dbmfStrdup("null"); }
static int yyerror(char *str)
{
if (str)
epicsPrintf(ERL_ERROR ": %s\n", str);
fprintf(stderr, ERL_ERROR ": %s\n", str);
else
epicsPrintf(ERL_ERROR "");
fprintf(stderr, ERL_ERROR ": ");
if (!yyFailed) { /* Only print this stuff once */
epicsPrintf(" at or before '%s'", yytext);
fprintf(stderr, " at or before '%s'", yytext);
dbIncludePrint();
yyFailed = TRUE;
}
+4 -4
View File
@@ -77,14 +77,14 @@ struct macro_link {
char *macroStr;
};
struct dbCommon;
typedef long (*LINKCVT)();
struct dbAddr;
typedef long (*FASTCONVERTFUNC)(const void *from, void *to, const struct dbAddr *paddr);
struct pv_link {
ELLNODE backlinknode;
char *pvname; /* pvname link points to */
void *pvt; /* CA or DB private */
LINKCVT getCvt; /* input conversion function */
FASTCONVERTFUNC getCvt; /* input conversion function */
short pvlMask; /* Options mask */
short lastGetdbrType; /* last dbrType for DB or CA get */
};
@@ -188,8 +188,8 @@ union value {
struct vxiio vxiio; /* vxi io */
};
struct dbCommon;
struct lset;
struct link {
struct dbCommon *precord; /* Pointer to record owning link */
short type;
@@ -14,7 +14,6 @@ SRC_DIRS += $(IOCDIR)/dbtemplate
PROD_CMD += msi
msi_SRCS = msi.cpp
msi_LIBS += Com
HTMLS += msi.html
INC += dbLoadTemplate.h
+17 -17
View File
@@ -114,7 +114,7 @@ int iocInit(void)
static int iocBuild_1(void)
{
if (iocState != iocVoid) {
errlogPrintf("iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
errlogPrintf("iocBuild: " ERL_ERROR " IOC can only be initialized from uninitialized or stopped state\n");
return -1;
}
errlogInit(0);
@@ -126,7 +126,7 @@ static int iocBuild_1(void)
errlogPrintf("Starting iocInit\n");
if (checkDatabase(pdbbase)) {
errlogPrintf("iocBuild: Aborting, bad database definition (DBD)!\n");
errlogPrintf("iocBuild: " ERL_ERROR " Aborting, bad database definition (DBD)!\n");
return -1;
}
epicsSignalInstallSigHupIgnore();
@@ -237,7 +237,7 @@ int iocBuildIsolated(void)
int iocRun(void)
{
if (iocState != iocPaused && iocState != iocBuilt) {
errlogPrintf("iocRun: IOC not paused\n");
errlogPrintf("iocRun: " ERL_WARNING " IOC not paused\n");
return -1;
}
initHookAnnounce(initHookAtIocRun);
@@ -268,7 +268,7 @@ int iocRun(void)
int iocPause(void)
{
if (iocState != iocRunning) {
errlogPrintf("iocPause: IOC not running\n");
errlogPrintf("iocPause: " ERL_WARNING " IOC not running\n");
return -1;
}
initHookAnnounce(initHookAtIocPause);
@@ -306,59 +306,59 @@ static int checkDatabase(dbBase *pdbbase)
const dbMenu *pMenu;
if (!pdbbase) {
errlogPrintf("checkDatabase: No database definitions loaded.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " No database definitions loaded.\n");
return -1;
}
pMenu = dbFindMenu(pdbbase, "menuConvert");
if (!pMenu) {
errlogPrintf("checkDatabase: menuConvert not defined.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvert not defined.\n");
return -1;
}
if (pMenu->nChoice <= menuConvertLINEAR) {
errlogPrintf("checkDatabase: menuConvert has too few choices.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvert has too few choices.\n");
return -1;
}
if (strcmp(pMenu->papChoiceName[menuConvertNO_CONVERSION],
"menuConvertNO_CONVERSION")) {
errlogPrintf("checkDatabase: menuConvertNO_CONVERSION doesn't match.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvertNO_CONVERSION doesn't match.\n");
return -1;
}
if (strcmp(pMenu->papChoiceName[menuConvertSLOPE], "menuConvertSLOPE")) {
errlogPrintf("checkDatabase: menuConvertSLOPE doesn't match.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvertSLOPE doesn't match.\n");
return -1;
}
if (strcmp(pMenu->papChoiceName[menuConvertLINEAR], "menuConvertLINEAR")) {
errlogPrintf("checkDatabase: menuConvertLINEAR doesn't match.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvertLINEAR doesn't match.\n");
return -1;
}
pMenu = dbFindMenu(pdbbase, "menuScan");
if (!pMenu) {
errlogPrintf("checkDatabase: menuScan not defined.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuScan not defined.\n");
return -1;
}
if (pMenu->nChoice <= menuScanI_O_Intr) {
errlogPrintf("checkDatabase: menuScan has too few choices.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuScan has too few choices.\n");
return -1;
}
if (strcmp(pMenu->papChoiceName[menuScanPassive],
"menuScanPassive")) {
errlogPrintf("checkDatabase: menuScanPassive doesn't match.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuScanPassive doesn't match.\n");
return -1;
}
if (strcmp(pMenu->papChoiceName[menuScanEvent],
"menuScanEvent")) {
errlogPrintf("checkDatabase: menuScanEvent doesn't match.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuScanEvent doesn't match.\n");
return -1;
}
if (strcmp(pMenu->papChoiceName[menuScanI_O_Intr],
"menuScanI_O_Intr")) {
errlogPrintf("checkDatabase: menuScanI_O_Intr doesn't match.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuScanI_O_Intr doesn't match.\n");
return -1;
}
if (pMenu->nChoice <= SCAN_1ST_PERIODIC) {
errlogPrintf("checkDatabase: menuScan has no periodic choices.\n");
errlogPrintf("checkDatabase: " ERL_ERROR " menuScan has no periodic choices.\n");
return -1;
}
@@ -388,7 +388,7 @@ static void initDrvSup(void) /* Locate all driver support entry tables */
for (pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList); pdrvSup;
pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) {
struct drvet *pdrvet = registryDriverSupportFind(pdrvSup->name);
drvet *pdrvet = registryDriverSupportFind(pdrvSup->name);
if (!pdrvet) {
errlogPrintf("iocInit: driver %s not found\n", pdrvSup->name);
@@ -32,11 +32,12 @@ namespace {
struct compareLoc {
bool operator()(const recordTypeLocation& lhs, const recordTypeLocation& rhs) const
{
if(lhs.prset<rhs.prset)
if (lhs.prset < rhs.prset)
return true;
else if(lhs.prset>rhs.prset)
if (lhs.prset > rhs.prset)
return false;
return lhs.sizeOffset<rhs.sizeOffset;
return reinterpret_cast<char *>(lhs.sizeOffset)
< reinterpret_cast<char *>(rhs.sizeOffset);
}
};
@@ -65,7 +65,7 @@ void registerDevices(DBBASE *pbase, int nDevices,
}
void registerDrivers(DBBASE *pbase, int nDrivers,
const char * const * driverSupportNames, struct drvet * const *drvsl)
const char * const * driverSupportNames, drvet * const *drvsl)
{
int i;
for (i = 0; i < nDrivers; i++) {
@@ -29,7 +29,7 @@ DBCORE_API void registerDevices(
const char * const *deviceSupportNames, const dset * const *devsl);
DBCORE_API void registerDrivers(
DBBASE *pbase, int nDrivers,
const char * const *driverSupportNames, struct drvet * const *drvsl);
const char * const *driverSupportNames, drvet * const *drvsl);
DBCORE_API void registerJLinks(
DBBASE *pbase, int nDrivers, jlif * const *jlifsl);
@@ -18,12 +18,12 @@ static void *registryID = "driver support";
DBCORE_API int registryDriverSupportAdd(
const char *name, struct drvet *pdrvet)
const char *name, drvet *pdrvet)
{
return registryAdd(registryID, name, pdrvet);
}
DBCORE_API struct drvet * registryDriverSupportFind(
DBCORE_API drvet * registryDriverSupportFind(
const char *name)
{
return registryFind(registryID, name);
@@ -19,8 +19,8 @@ extern "C" {
#endif
DBCORE_API int registryDriverSupportAdd(
const char *name, struct drvet *pdrvet);
DBCORE_API struct drvet * registryDriverSupportFind(
const char *name, drvet *pdrvet);
DBCORE_API drvet * registryDriverSupportFind(
const char *name);
#ifdef __cplusplus
+7 -2
View File
@@ -120,6 +120,11 @@ static void req_server (void *pParm)
}
}
}
/* ATM never reached, just a placeholder */
cantProceed("Unreachable. Perpetual thread.");
taskwdRemove(0);
}
static
@@ -585,8 +590,7 @@ void rsrv_init (void)
errlogPrintf ( "cas " ERL_WARNING ": reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" );
}
epicsSnprintf(buf, sizeof(buf)-1u, "%u", ca_server_port);
buf[sizeof(buf)-1u] = '\0';
epicsSnprintf(buf, sizeof(buf), "%u", ca_server_port);
epicsEnvSet("RSRV_SERVER_PORT", buf);
}
@@ -748,6 +752,7 @@ void rsrv_init (void)
if(!havesometcp)
cantProceed("CAS: No TCP server started\n");
}
free(socks);
/* servers list is considered read-only from this point */
+1 -4
View File
@@ -98,13 +98,10 @@ static void clean_addrq(struct client *client)
}
epicsMutexUnlock ( client->chanListLock );
# ifdef DEBUG
if(ndelete){
if (CASDEBUG>1 && ndelete){
epicsPrintf ("CAS: %d CA channels have expired after %f sec\n",
ndelete, maxdelay);
}
# endif
}
/*
@@ -129,7 +129,11 @@ void rsrv_online_notify_task(void *pParm)
}
}
/* ATM never reached, just a placeholder */
cantProceed("Unreachable. Perpetual thread.");
free(lastError);
taskwdRemove(0);
}
+2 -4
View File
@@ -36,8 +36,6 @@
#include "epicsExport.h"
typedef long (*FASTCONVERT)();
typedef struct calc_link {
jlink jlink; /* embedded object */
int nArgs;
@@ -558,7 +556,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
dbCommon *prec = plink->precord;
int i;
long status;
FASTCONVERT conv;
FASTCONVERTFUNC conv;
if(INVALID_DB_REQ(dbrType))
return S_db_badDbrtype;
@@ -638,7 +636,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
dbCommon *prec = plink->precord;
int i;
long status;
FASTCONVERT conv;
FASTCONVERTFUNC conv;
if(INVALID_DB_REQ(dbrType))
return S_db_badDbrtype;
+6 -6
View File
@@ -23,8 +23,6 @@
#include "epicsExport.h"
typedef long (*FASTCONVERT)();
typedef struct const_link {
jlink jlink; /* embedded object */
int nElems;
@@ -458,7 +456,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
short dbrSize;
char *pdest = pbuffer;
int nElems = clink->nElems;
FASTCONVERT conv;
FASTCONVERTFUNC conv;
long status;
if(INVALID_DB_REQ(dbrType))
@@ -495,9 +493,11 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
}
else {
/* Long string conversion */
strncpy(pbuffer, clink->value.scalar_string, *pnReq);
((char *)pbuffer)[*pnReq] = 0;
nElems = strlen(pbuffer) + 1;
if (*pnReq > 0) {
strncpy(pbuffer, clink->value.scalar_string, *pnReq);
((char *)pbuffer)[*pnReq - 1] = 0;
nElems = strlen(pbuffer) + 1;
}
status = 0;
}
break;
+1 -3
View File
@@ -34,8 +34,6 @@
#include "epicsExport.h"
typedef long (*FASTCONVERT)();
typedef struct state_link {
jlink jlink; /* embedded object */
char *name;
@@ -143,7 +141,7 @@ static long lnkState_getValue(struct link *plink, short dbrType, void *pbuffer,
{
state_link *slink = CONTAINER(plink->value.json.jlink,
struct state_link, jlink);
FASTCONVERT conv;
FASTCONVERTFUNC conv;
if(INVALID_DB_REQ(dbrType))
return S_db_badDbrtype;
@@ -16,7 +16,7 @@ has a number of additional features:
=item *
It provides 20 different input and output fields which can hold array or
It provides 21 different input and output fields which can hold array or
scalar values.
The types and array capacities of these are user configurable, and they all
have an associated input or output link.
@@ -1160,7 +1160,7 @@ See next section.
=head2 C<special>
This is called id CALC or OCAL is changed. C<special> calls postfix.
This is called if CALC or OCAL is changed. C<special> calls postfix.
=head2 C<get_units>
+38 -42
View File
@@ -149,13 +149,16 @@ static int compare(const void *arg1, const void *arg2)
else return 1;
}
#define min(a, b) ((a) < (b) ? (a) : (b))
static int compress_array(compressRecord *prec,
double *psource, int no_elements)
{
epicsInt32 i,j;
epicsInt32 j;
epicsInt32 n, nnew;
epicsInt32 nsam = prec->nsam;
double value;
epicsUInt32 samples_written = 0;
double value = 0.0;
/* skip out of limit data */
if (prec->ilil < prec->ihil) {
@@ -167,61 +170,54 @@ static int compress_array(compressRecord *prec,
}
if (prec->n <= 0)
prec->n = 1;
if (no_elements < prec->n && prec->pbuf != menuYesNoYES)
return 1; /*dont do anything*/
n = no_elements;
n = prec->n;
/* determine number of samples to take */
if (no_elements < nsam * n)
nnew = (no_elements / n);
else nnew = nsam;
nnew = min(no_elements, nsam * n);
/* compress according to specified algorithm */
switch (prec->alg){
case compressALG_N_to_1_Low_Value:
/* compress N to 1 keeping the lowest value */
for (i = 0; i < nnew; i++) {
while (nnew > 0)
{
if (nnew < n && prec->pbuf != menuYesNoYES)
break;
n = min(n, nnew);
switch (prec->alg)
{
case compressALG_N_to_1_Low_Value:
value = *psource++;
for (j = 1; j < n; j++, psource++) {
for (j = 1; j < n; j++, psource++)
{
if (value > *psource)
value = *psource;
}
put_value(prec, &value, 1);
}
break;
case compressALG_N_to_1_High_Value:
/* compress N to 1 keeping the highest value */
for (i = 0; i < nnew; i++){
break;
case compressALG_N_to_1_High_Value:
value = *psource++;
for (j = 1; j < n; j++, psource++) {
for (j = 1; j < n; j++, psource++)
{
if (value < *psource)
value = *psource;
}
put_value(prec, &value, 1);
}
break;
case compressALG_N_to_1_Average:
/* compress N to 1 keeping the average value */
for (i = 0; i < nnew; i++) {
value = 0;
for (j = 0; j < n; j++, psource++)
break;
case compressALG_N_to_1_Average:
value = *psource++;
for (j = 1; j < n; j++, psource++)
{
value += *psource;
value /= n;
put_value(prec, &value, 1);
}
break;
case compressALG_N_to_1_Median:
/* compress N to 1 keeping the median value */
/* note: sorts source array (OK; it's a work pointer) */
for (i = 0; i < nnew; i++, psource += nnew) {
}
value = value / n;
break;
case compressALG_N_to_1_Median:
/* note: sorts source array (OK; it's a work pointer) */
qsort(psource, n, sizeof(double), compare);
value = psource[n / 2];
put_value(prec, &value, 1);
psource += n;
break;
}
break;
nnew -= n;
put_value(prec, &value, 1);
samples_written++;
}
return 0;
return (samples_written == 0);
}
static int array_average(compressRecord *prec,
@@ -91,10 +91,10 @@ The BPTR field contains a pointer to the unsigned long array of frequency
values. The VAL field references this array as well. However, the BPTR field is
not accessible at run-time.
The MCNT field keeps counts the number of signal counts since the last monitor
The MCNT field keeps the number of signal counts since the last monitor
was invoked.
The collections controls field (CMD) is a menu field with five choices:
The collections controls field (CMD) is a menu field with four choices:
=menu histogramCMD
@@ -110,8 +110,6 @@ array. Unlike C<Read>, it doesn't clear the array first.
The C<Stop> command disables the reading of signal values into the array.
The C<Setup> command waits until the C<start> or C<read> command has been issued
to start counting.
The CSTA or collections status field implements the CMD field choices by
enabling or disabling the reading of values into the histogram array. While
+3
View File
@@ -49,6 +49,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
if (sizv < 16) {
sizv = 16; /* Enforce a minimum size for the VAL field */
prec->sizv = sizv;
} else if (sizv > 0x7fff) {
sizv = 0x7fff; /* SIZV is unsigned, but dbAddr::field_size is signed */
prec->sizv = sizv;
}
prec->val = callocMustSucceed(1, sizv, "lsi::init_record");
@@ -9,7 +9,7 @@
=title Long String Input Record (lsi)
The long string input record is used to retrieve an arbitrary ASCII string with
a maximum length of 65535 characters.
a maximum length of 32767 characters.
This record type was included in base.dbd beginning with epics-base 3.15.0.2 .
@@ -36,7 +36,7 @@ from. It can be a database or channel access link, or a constant. If constant,
the VAL field is initialized with the constant and can be changed via dbPuts.
Otherwise, the string is read from the specified location each time the record
is processed and placed in the VAL field. The maximum number of characters in
VAL is given by SIZV, and cannot be larger than 65535. In addition, the
VAL is given by SIZV, and cannot be larger than 32767. In addition, the
appropriate device support module must be entered into the DTYP field.
=fields VAL, OVAL, SIZV, INP, DTYP
+3
View File
@@ -53,6 +53,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
if (sizv < 16) {
sizv = 16; /* Enforce a minimum size for the VAL field */
prec->sizv = sizv;
} else if (sizv > 0x7fff) {
sizv = 0x7fff; /* SIZV is unsigned, but dbAddr::field_size is signed */
prec->sizv = sizv;
}
prec->val = callocMustSucceed(1, sizv, "lso::init_record");
@@ -9,7 +9,7 @@
=title Long String Output Record (lso)
The long string output record is used to write an arbitrary ASCII string with a
maximum length of 65535 characters.
maximum length of 32767 characters.
This record type was included in base.dbd beginning with epics-base 3.15.0.2 .
@@ -41,7 +41,7 @@ C<supervisory> is specified, DOL is ignored, the current value of VAL is
written, and VAL can be changed externally via dbPuts at run-time.
The maximum number of characters in VAL is given by SIZV, and cannot be larger
than 65535.
than 32767.
DOL can also be a constant instead of a link, in which case VAL is initialized
to the constant value. Most simple string constants are likely to be interpreted
@@ -337,6 +337,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
if (sizv < 16) {
sizv = 16; /* Enforce a minimum size for the VAL field */
prec->sizv = sizv;
} else if (sizv > 0x7fff) {
sizv = 0x7fff; /* SIZV is unsigned, but dbAddr::field_size is signed */
prec->sizv = sizv;
}
prec->val = callocMustSucceed(1, sizv, "printf::init_record");
@@ -152,7 +152,7 @@ Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Dat
for information on specifying links.
The formatted string is written to the VAL field. The maximum number of
characters in VAL is given by SIZV, and cannot be larger than 65535. The LEN
characters in VAL is given by SIZV, and cannot be larger than 32767. The LEN
field contains the length of the formatted string in the VAL field.
=fields FMT, INP0, INP1, INP2, INP3, INP4, INP5, INP6, INP7, INP8, INP9, VAL, SIZV, LEN
@@ -17,10 +17,12 @@
#include <epicsGetopt.h>
#include "registryFunction.h"
#include "errlog.h"
#include "epicsThread.h"
#include "epicsExit.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "errlog.h"
#include "dbStaticLib.h"
#include "subRecord.h"
#include "dbAccess.h"
@@ -92,7 +94,7 @@ void usage(const char *arg0, const std::string& base_dbd) {
"interactive IOC shell.\n"
"\n"
"Compiled-in path to softIoc.dbd is:\n"
"\t"<<base_dbd.c_str()<<"\n";
"\t"<<base_dbd.c_str()<<std::endl;
}
void errIf(int ret, const std::string& msg)
@@ -239,7 +241,9 @@ int main(int argc, char *argv[])
if (loadedDb) {
if (verbose)
std::cout<<"iocInit()\n";
iocInit();
if(iocInit()) {
std::cerr<<ERL_ERROR " during iocInit()"<<std::endl;
}
epicsThreadSleep(0.2);
}
@@ -270,7 +274,8 @@ int main(int argc, char *argv[])
return 0;
}catch(std::exception& e){
std::cerr<<"Error: "<<e.what()<<"\n";
errlogFlush();
std::cerr<<ERL_ERROR ": "<<e.what()<<"\n";
epicsExit(2);
return 2;
}