Add fields argument to dbgrep() (#613)

This allows optionally printing out the value of one or more fields
for each record found.
This commit is contained in:
Freddie Akeroyd
2025-04-04 15:17:16 +01:00
committed by GitHub
parent 26e9e407f6
commit 7372b4e5bb
4 changed files with 80 additions and 49 deletions

View File

@@ -235,14 +235,16 @@ static void dblaCallFunc(const iocshArgBuf *args) { iocshSetError(dbla(args[0].s
/* dbgrep */
static const iocshArg dbgrepArg0 = { "pattern",iocshArgStringRecord};
static const iocshArg * const dbgrepArgs[1] = {&dbgrepArg0};
static const iocshFuncDef dbgrepFuncDef = {"dbgrep",1,dbgrepArgs,
"List record names matching pattern.\n"
static const iocshArg dbgrepArg1 = { "fields",iocshArgString};
static const iocshArg * const dbgrepArgs[2] = {&dbgrepArg0,&dbgrepArg1};
static const iocshFuncDef dbgrepFuncDef = {"dbgrep",2,dbgrepArgs,
"List record names matching pattern and optionally print field values. \n"
"The pattern can contain any characters that are legal in record names as well as:\n"
" - \"?\", which matches 0 or one characters.\n"
" - \"*\", which matches 0 or more characters.\n\n"
"Example: dbgrep(\"*gpibAi*\")\n"};
static void dbgrepCallFunc(const iocshArgBuf *args) { iocshSetError(dbgrep(args[0].sval));}
"Example: dbgrep(\"*gpibAi*\")\n"
" dbgrep(\"*gpibAi*\",\"VAL DESC\")\n"};
static void dbgrepCallFunc(const iocshArgBuf *args) { iocshSetError(dbgrep(args[0].sval,args[1].sval));}
/* dbgf */
static const iocshArg dbgfArg0 = { "record name",iocshArgStringRecord};

View File

@@ -100,13 +100,59 @@ long dba(const char*pname)
return 0;
}
/* split a space separated list of field names and return the number of
fields with each field an element of papfields. These elements
point to within the fieldnames variable which is modified
by the function. memory is allocated for *ppapfields and needs
to be freed later by the calling routine */
static int splitFieldsList(char *fieldnames, char ***ppapfields)
{
char *pnext = fieldnames;
int nfields = 0, maxfields = 1;
char* saveptr = NULL;
/* this may overcount real fields e.g. " VAL " hence maxfields */
while (*pnext && (pnext = strchr(pnext, ' '))) {
maxfields++;
while (*pnext == ' ') pnext++;
}
*ppapfields = dbCalloc(maxfields, sizeof(char *));
pnext = epicsStrtok_r(fieldnames, " ", &saveptr);
while(pnext != NULL) {
(*ppapfields)[nfields++] = pnext;
pnext = epicsStrtok_r(NULL, " ", &saveptr);
}
return nfields;
}
static void printFieldsList(DBENTRY *pdbentry, char** papfields, int nfields)
{
int ifield;
for (ifield = 0; ifield < nfields; ifield++) {
char *pvalue;
long status = dbFindField(pdbentry, papfields[ifield]);
if (status) {
if (!strcmp(papfields[ifield], "recordType")) {
pvalue = dbGetRecordTypeName(pdbentry);
}
else {
printf(", ");
continue;
}
}
else {
pvalue = dbGetString(pdbentry);
}
printf(", \"%s\"", (pvalue ? pvalue : ""));
}
printf("\n");
}
long dbl(const char *precordTypename, const char *fields)
{
DBENTRY dbentry;
DBENTRY *pdbentry=&dbentry;
long status;
int nfields = 0;
int ifield;
char *fieldnames = 0;
char **papfields = 0;
@@ -121,25 +167,8 @@ long dbl(const char *precordTypename, const char *fields)
if (fields && (*fields == '\0'))
fields = NULL;
if (fields) {
char *pnext;
fieldnames = epicsStrDup(fields);
nfields = 1;
pnext = fieldnames;
while (*pnext && (pnext = strchr(pnext,' '))) {
nfields++;
while (*pnext == ' ') pnext++;
}
papfields = dbCalloc(nfields,sizeof(char *));
pnext = fieldnames;
for (ifield = 0; ifield < nfields; ifield++) {
papfields[ifield] = pnext;
if (ifield < nfields - 1) {
pnext = strchr(pnext, ' ');
*pnext++ = 0;
while (*pnext == ' ') pnext++;
}
}
nfields = splitFieldsList(fieldnames, &papfields);
}
dbInitEntry(pdbbase, pdbentry);
if (!precordTypename)
@@ -154,24 +183,7 @@ long dbl(const char *precordTypename, const char *fields)
status = dbFirstRecord(pdbentry);
while (!status) {
printf("%s", dbGetRecordName(pdbentry));
for (ifield = 0; ifield < nfields; ifield++) {
char *pvalue;
status = dbFindField(pdbentry, papfields[ifield]);
if (status) {
if (!strcmp(papfields[ifield], "recordType")) {
pvalue = dbGetRecordTypeName(pdbentry);
}
else {
printf(", ");
continue;
}
}
else {
pvalue = dbGetString(pdbentry);
}
printf(", \"%s\"", pvalue ? pvalue : "");
}
printf("\n");
printFieldsList(pdbentry, papfields, nfields);
status = dbNextRecord(pdbentry);
}
if (precordTypename)
@@ -283,14 +295,17 @@ long dbli(const char *pattern)
return 0;
}
long dbgrep(const char *pmask)
long dbgrep(const char *pmask,const char *fields)
{
DBENTRY dbentry;
DBENTRY *pdbentry = &dbentry;
long status;
int nfields = 0;
char *fieldnames = 0;
char **papfields = 0;
if (!pmask || !*pmask) {
printf("Usage: dbgrep \"pattern\"\n");
printf("Usage: dbgrep \"pattern\" \"fields\"\n");
return 1;
}
@@ -298,20 +313,30 @@ long dbgrep(const char *pmask)
printf("No database loaded\n");
return 0;
}
if (fields && (*fields == '\0'))
fields = NULL;
if (fields) {
fieldnames = epicsStrDup(fields);
nfields = splitFieldsList(fieldnames, &papfields);
}
dbInitEntry(pdbbase, pdbentry);
status = dbFirstRecordType(pdbentry);
while (!status) {
status = dbFirstRecord(pdbentry);
while (!status) {
char *pname = dbGetRecordName(pdbentry);
if (epicsStrGlobMatch(pname, pmask))
puts(pname);
if (epicsStrGlobMatch(pname, pmask)) {
printf("%s", pname);
printFieldsList(pdbentry, papfields, nfields);
}
status = dbNextRecord(pdbentry);
}
status = dbNextRecordType(pdbentry);
}
if (nfields > 0) {
free((void *)papfields);
free((void *)fieldnames);
}
dbFinishEntry(pdbentry);
return 0;
}

View File

@@ -29,7 +29,7 @@ DBCORE_API long dbla(const char *pmask);
/* list infos */
DBCORE_API long dbli(const char *patern);
/*list records with mask*/
DBCORE_API long dbgrep(const char *pmask);
DBCORE_API long dbgrep(const char *pmask,const char *fields);
/*get field value*/
DBCORE_API long dbgf(const char *pname);
/*put field value*/