diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 39a1a79cf..c60ab9575 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -97,6 +97,14 @@ be happy to try and answer them!

+

Finding info fields

+ +

A new iocsh command dbli lists the info fields defined in the +database, and can take a glob pattern to limit output to specific info names. +The newly added dbStaticLib function dbNextMatchingInfo() iterates +through the info fields defined in the current record, and is used to implement +the new command.

+

Output from dbpr command enhanced

The "DataBase Print Record" command dbpr now generates slightly diff --git a/modules/database/src/ioc/db/dbIocRegister.c b/modules/database/src/ioc/db/dbIocRegister.c index 07c9836c2..4d0b88cd9 100644 --- a/modules/database/src/ioc/db/dbIocRegister.c +++ b/modules/database/src/ioc/db/dbIocRegister.c @@ -152,6 +152,12 @@ static const iocshArg * const dbnrArgs[1] = {&dbnrArg0}; static const iocshFuncDef dbnrFuncDef = {"dbnr",1,dbnrArgs}; static void dbnrCallFunc(const iocshArgBuf *args) { dbnr(args[0].ival);} +/* dbli */ +static const iocshArg dbliArg0 = { "pattern",iocshArgString}; +static const iocshArg * const dbliArgs[1] = {&dbliArg0}; +static const iocshFuncDef dbliFuncDef = {"dbli",1,dbliArgs}; +static void dbliCallFunc(const iocshArgBuf *args) { dbli(args[0].sval);} + /* dbla */ static const iocshArg dblaArg0 = { "pattern",iocshArgString}; static const iocshArg * const dblaArgs[1] = {&dblaArg0}; @@ -415,6 +421,7 @@ void dbIocRegister(void) iocshRegister(&dblFuncDef,dblCallFunc); iocshRegister(&dbnrFuncDef,dbnrCallFunc); iocshRegister(&dblaFuncDef,dblaCallFunc); + iocshRegister(&dbliFuncDef,dbliCallFunc); iocshRegister(&dbgrepFuncDef,dbgrepCallFunc); iocshRegister(&dbgfFuncDef,dbgfCallFunc); iocshRegister(&dbpfFuncDef,dbpfCallFunc); diff --git a/modules/database/src/ioc/db/dbLink.c b/modules/database/src/ioc/db/dbLink.c index 9ca587f71..bcdbec473 100644 --- a/modules/database/src/ioc/db/dbLink.c +++ b/modules/database/src/ioc/db/dbLink.c @@ -49,7 +49,7 @@ #include "special.h" /* How to identify links in error messages */ -static const char * link_field_name(const struct link *plink) +const char * dbLinkFieldName(const struct link *plink) { const struct dbCommon *precord = plink->precord; const dbRecordType *pdbRecordType = precord->rdes; @@ -136,7 +136,7 @@ void dbInitLink(struct link *plink, short dbfType) errlogPrintf("Forward-link uses Channel Access " "without pointing to PROC field\n" " %s.%s => %s\n", - precord->name, link_field_name(plink), + precord->name, dbLinkFieldName(plink), plink->value.pv_link.pvname); } } diff --git a/modules/database/src/ioc/db/dbLink.h b/modules/database/src/ioc/db/dbLink.h index fcfadb24f..16066e0d5 100644 --- a/modules/database/src/ioc/db/dbLink.h +++ b/modules/database/src/ioc/db/dbLink.h @@ -81,6 +81,8 @@ typedef struct lset { #define dbGetSevr(link, sevr) \ dbGetAlarm(link, NULL, sevr) +epicsShareFunc const char * dbLinkFieldName(const struct link *plink); + epicsShareFunc void dbInitLink(struct link *plink, short dbfType); epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget); diff --git a/modules/database/src/ioc/db/dbTest.c b/modules/database/src/ioc/db/dbTest.c index cb9963ef3..0daafc436 100644 --- a/modules/database/src/ioc/db/dbTest.c +++ b/modules/database/src/ioc/db/dbTest.c @@ -258,7 +258,30 @@ long dbla(const char *pmask) dbFinishEntry(pdbentry); return 0; } + +long dbli(const char *pattern) +{ + DBENTRY dbentry; + void* ptr; + if (!pdbbase) { + printf("No database loaded\n"); + return 0; + } + + dbInitEntry(pdbbase, &dbentry); + while (dbNextMatchingInfo(&dbentry, pattern) == 0) + { + printf("%s info(%s, \"%s\"", dbGetRecordName(&dbentry), + dbGetInfoName(&dbentry), dbGetInfoString(&dbentry)); + if ((ptr = dbGetInfoPointer(&dbentry)) != NULL) + printf(", %p", ptr); + printf(")\n"); + } + dbFinishEntry(&dbentry); + return 0; +} + long dbgrep(const char *pmask) { DBENTRY dbentry; diff --git a/modules/database/src/ioc/db/dbTest.h b/modules/database/src/ioc/db/dbTest.h index 6d457b59e..a4d90e2ad 100644 --- a/modules/database/src/ioc/db/dbTest.h +++ b/modules/database/src/ioc/db/dbTest.h @@ -25,6 +25,8 @@ epicsShareFunc long dbl( epicsShareFunc long dbnr(int verbose); /* list aliases */ epicsShareFunc long dbla(const char *pmask); +/* list infos */ +epicsShareFunc long dbli(const char *patern); /*list records with mask*/ epicsShareFunc long dbgrep(const char *pmask); /*get field value*/ diff --git a/modules/database/src/ioc/dbStatic/dbStaticLib.c b/modules/database/src/ioc/dbStatic/dbStaticLib.c index 4e0755db7..1a3d9883f 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticLib.c +++ b/modules/database/src/ioc/dbStatic/dbStaticLib.c @@ -2894,6 +2894,32 @@ long dbNextInfo(DBENTRY *pdbentry) return (pinfo ? 0 : S_dbLib_infoNotFound); } +long dbNextMatchingInfo(DBENTRY *pdbentry, const char *pattern) +{ + long status; + + if (!pdbentry->precordType) + { + status = dbFirstRecordType(pdbentry); + goto first; + } + while(1) { + status = dbNextInfo(pdbentry); + while (status) { + status = dbNextRecord(pdbentry); + while (status) { + status = dbNextRecordType(pdbentry); +first: + if (status) return status; + status = dbFirstRecord(pdbentry); + } + status = dbFirstInfo(pdbentry); + } + if (!pattern || !*pattern) return 0; + if (epicsStrGlobMatch(dbGetInfoName(pdbentry), pattern)) return 0; + } +} + long dbFindInfo(DBENTRY *pdbentry,const char *name) { dbRecordNode *precnode = pdbentry->precnode; diff --git a/modules/database/src/ioc/dbStatic/dbStaticLib.h b/modules/database/src/ioc/dbStatic/dbStaticLib.h index 1ee999104..4082600be 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticLib.h +++ b/modules/database/src/ioc/dbStatic/dbStaticLib.h @@ -190,6 +190,8 @@ epicsShareFunc long dbFirstInfo(DBENTRY *pdbentry); epicsShareFunc long dbNextInfo(DBENTRY *pdbentry); epicsShareFunc long dbFindInfo(DBENTRY *pdbentry, const char *name); +epicsShareFunc long dbNextMatchingInfo(DBENTRY *pdbentry, + const char *pattern); epicsShareFunc long dbDeleteInfo(DBENTRY *pdbentry); epicsShareFunc const char * dbGetInfoName(DBENTRY *pdbentry); epicsShareFunc const char * dbGetInfoString(DBENTRY *pdbentry); diff --git a/modules/database/src/std/rec/compressRecord.c b/modules/database/src/std/rec/compressRecord.c index 4b4de5f15..b123dcf09 100644 --- a/modules/database/src/std/rec/compressRecord.c +++ b/modules/database/src/std/rec/compressRecord.c @@ -120,13 +120,13 @@ static void put_value(compressRecord *prec, double *psource, int n) nuse = nsam; while (n--) { - /* for LIFO, decrement before */ + /* for LIFO, pre-decrement modulo nsam */ if (!fifo) - offset = (offset - 1) % nsam; + offset = (offset + nsam - 1) % nsam; prec->bptr[offset] = *psource++; - /* for FIFO, increment after */ + /* for FIFO, post-increment modulo nsam */ if (fifo) offset = (offset + 1) % nsam; } @@ -424,15 +424,15 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset) compressRecord *prec = (compressRecord *) paddr->precord; epicsUInt32 off = prec->off; epicsUInt32 nuse = prec->nuse; - epicsUInt32 nsam = prec->nsam; - *no_elements = nuse; if (prec->balg == bufferingALG_FIFO) { - *offset = (off - nuse) % nsam; - } else { - *offset = off; + epicsUInt32 nsam = prec->nsam; + + off = (off + nsam - nuse) % nsam; } + *no_elements = nuse; + *offset = off; return 0; } diff --git a/modules/database/test/ioc/db/dbStaticTest.db b/modules/database/test/ioc/db/dbStaticTest.db index c35ff9a91..63036727f 100644 --- a/modules/database/test/ioc/db/dbStaticTest.db +++ b/modules/database/test/ioc/db/dbStaticTest.db @@ -1,7 +1,7 @@ record(x, "testrec") { - info("A", "B") alias("testalias") + info("A", "B") } alias("testrec", "testalias2")