From 579a0791ea271b77d36f088537fcc49d9c94b609 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 27 Apr 2017 19:46:33 -0400 Subject: [PATCH] jlink conditional debug print Enable magic info("linkDebug","YES") to enable debug prints during parsing. --- src/ioc/db/dbAccess.c | 2 +- src/ioc/db/dbJLink.c | 60 +++++++++++++++------------------ src/ioc/db/dbJLink.h | 3 +- src/ioc/db/test/dbPutLinkTest.c | 4 +-- src/ioc/dbStatic/dbStaticLib.c | 19 ++++++++--- src/ioc/dbStatic/dbStaticPvt.h | 4 ++- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index 46b47fb04..5331b30ac 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -1006,7 +1006,7 @@ static long dbPutFieldLink(DBADDR *paddr, return S_db_badDbrtype; } - status = dbParseLink(pstring, pfldDes->field_type, &link_info); + status = dbParseLink(pstring, pfldDes->field_type, &link_info, 0); if (status) return status; diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c index 5638e73ee..f634e6d3c 100644 --- a/src/ioc/db/dbJLink.c +++ b/src/ioc/db/dbJLink.c @@ -18,24 +18,15 @@ #define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbCommon.h" +#include "dbStaticLib.h" +#include "dbStaticPvt.h" #include "dbLink.h" #include "dbJLink.h" #include "dbLock.h" #include "dbStaticLib.h" #include "link.h" -/* Change 'undef' to 'define' to turn on debug statements: */ -#undef DEBUG_JLINK - -#ifdef DEBUG_JLINK - int jlinkDebug = 10; -# define IFDEBUG(n) \ - if (jlinkDebug >= n) /* block or statement */ -#else -# define IFDEBUG(n) \ - if(0) /* Compiler will elide the block or statement */ -#endif - +#define IFDEBUG(n) if(parser->debug) typedef struct parseContext { jlink *pjlink; @@ -43,6 +34,7 @@ typedef struct parseContext { short dbfType; short jsonDepth; unsigned key_is_link:1; + unsigned debug:1; } parseContext; #define CALL_OR_STOP(routine) !(routine) ? jlif_stop : (routine) @@ -51,9 +43,9 @@ static int dbjl_return(parseContext *parser, jlif_result result) { jlink *pjlink = parser->pjlink; IFDEBUG(10) { - printf("dbjl_return(%s@%p, %d)\t", pjlink->pif->name, pjlink, result); + printf("dbjl_return(%s@%p, %d)\t", pjlink ? pjlink->pif->name : "", pjlink, result); printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n", - parser->jsonDepth, pjlink->parseDepth, parser->key_is_link); + parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link); } if (result == jlif_stop && pjlink) { @@ -74,19 +66,21 @@ static int dbjl_value(parseContext *parser, jlif_result result) { jlink *parent; IFDEBUG(10) { - printf("dbjl_value(%s@%p, %d)\t", pjlink->pif->name, pjlink, result); + printf("dbjl_value(%s@%p, %d)\t", pjlink ? pjlink->pif->name : "", pjlink, result); printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n", - parser->jsonDepth, pjlink->parseDepth, parser->key_is_link); + parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link); } if (result == jlif_stop || pjlink->parseDepth > 0) return dbjl_return(parser, result); parent = pjlink->parent; - if (!parent) + if (!parent) { parser->product = pjlink; - else if (parent->pif->end_child) + } else if (parent->pif->end_child) { parent->pif->end_child(parent, pjlink); + } + pjlink->debug = 0; parser->pjlink = parent; @@ -101,7 +95,7 @@ static int dbjl_null(void *ctx) { jlink *pjlink = parser->pjlink; IFDEBUG(10) - printf("dbjl_null(%s@%p)\n", pjlink->pif->name, pjlink); + printf("dbjl_null(%s@%p)\n", pjlink ? pjlink->pif->name : "", pjlink); assert(pjlink); return dbjl_value(parser, @@ -175,9 +169,9 @@ static int dbjl_start_map(void *ctx) { } IFDEBUG(10) { - printf("dbjl_start_map(%s@%p)\t", pjlink->pif->name, pjlink); + printf("dbjl_start_map(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink); printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n", - parser->jsonDepth, pjlink->parseDepth, parser->key_is_link); + parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link); } pjlink->parseDepth++; @@ -213,7 +207,7 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { printf("dbjl_map_key(%s@%p, \"%.*s\")\t", pjlink->pif->name, pjlink, len, key); printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n", - parser->jsonDepth, pjlink->parseDepth, parser->key_is_link); + parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link); } assert(pjlink->parseDepth > 0); @@ -256,6 +250,7 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { pjlink->pif = pjlif; pjlink->parent = NULL; pjlink->parseDepth = 0; + pjlink->debug = !!parser->debug; if (parser->pjlink) { /* We're starting a child link, save its parent */ @@ -265,7 +260,7 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { parser->key_is_link = 0; IFDEBUG(8) - printf("dbjl_map_key: New %s@%p\n", pjlink->pif->name, pjlink); + printf("dbjl_map_key: New %s@%p\n", pjlink ? pjlink->pif->name : "", pjlink); return jlif_continue; } @@ -301,9 +296,9 @@ static int dbjl_start_array(void *ctx) { jlink *pjlink = parser->pjlink; IFDEBUG(10) { - printf("dbjl_start_array(%s@%p)\t", pjlink->pif->name, pjlink); + printf("dbjl_start_array(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink); printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n", - parser->jsonDepth, pjlink->parseDepth, parser->key_is_link); + parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link); } assert(pjlink); @@ -319,9 +314,9 @@ static int dbjl_end_array(void *ctx) { jlink *pjlink = parser->pjlink; IFDEBUG(10) { - printf("dbjl_end_array(%s@%p)\t", pjlink->pif->name, pjlink); + printf("dbjl_end_array(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink); printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n", - parser->jsonDepth, pjlink->parseDepth, parser->key_is_link); + parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link); } assert(pjlink); @@ -342,7 +337,7 @@ static const yajl_parser_config dbjl_config = { 0, 0 }; /* allowComments = NO, checkUTF8 = NO */ long dbJLinkParse(const char *json, size_t jlen, short dbfType, - jlink **ppjlink) + jlink **ppjlink, unsigned opts) { parseContext context, *parser = &context; yajl_alloc_funcs dbjl_allocs; @@ -350,15 +345,16 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType, yajl_status ys; long status; - IFDEBUG(10) - printf("dbJLinkInit(\"%.*s\", %d, %p)\n", - (int) jlen, json, dbfType, ppjlink); - parser->pjlink = NULL; parser->product = NULL; parser->dbfType = dbfType; parser->jsonDepth = 0; parser->key_is_link = 0; + parser->debug = !!(opts&LINK_DEBUG); + + IFDEBUG(10) + printf("dbJLinkInit(\"%.*s\", %d, %p)\n", + (int) jlen, json, dbfType, ppjlink); IFDEBUG(10) printf("dbJLinkInit: jsonDepth=%d, key_is_link=%d\n", diff --git a/src/ioc/db/dbJLink.h b/src/ioc/db/dbJLink.h index 38476b1fd..8924c5d4a 100644 --- a/src/ioc/db/dbJLink.h +++ b/src/ioc/db/dbJLink.h @@ -35,6 +35,7 @@ typedef struct jlink { struct jlif *pif; /* Link methods */ struct jlink *parent; /* NULL for top-level links */ int parseDepth; /* Used by parser, unused afterwards */ + unsigned debug:1; /* set by caller of jlif operations to request debug output to console */ /* Link types extend or embed this structure for private storage */ } jlink; @@ -112,7 +113,7 @@ typedef struct jlif { } jlif; epicsShareFunc long dbJLinkParse(const char *json, size_t len, short dbfType, - jlink **ppjlink); + jlink **ppjlink, unsigned opts); epicsShareFunc long dbJLinkInit(struct link *plink); epicsShareFunc void dbJLinkFree(jlink *); diff --git a/src/ioc/db/test/dbPutLinkTest.c b/src/ioc/db/test/dbPutLinkTest.c index d8024c82a..b39b98db2 100644 --- a/src/ioc/db/test/dbPutLinkTest.c +++ b/src/ioc/db/test/dbPutLinkTest.c @@ -86,7 +86,7 @@ static void testLinkParse(void) for (;td->str; td++) { int i, N; testDiag("Parsing \"%s\"", td->str); - testOk(dbParseLink(td->str, DBF_INLINK, &info) == 0, "Parser returned OK"); + testOk(dbParseLink(td->str, DBF_INLINK, &info, 0) == 0, "Parser returned OK"); if (!testOk(info.ltype == td->info.ltype, "Link type value")) testDiag("Expected %d, got %d", td->info.ltype, info.ltype); if (td->info.target) @@ -146,7 +146,7 @@ static void testLinkFailParse(void) eltc(1); for(;*td; td++) { - testOk(dbParseLink(*td, DBF_INLINK, &info) == S_dbLib_badField, + testOk(dbParseLink(*td, DBF_INLINK, &info, 0) == S_dbLib_badField, "dbParseLink correctly rejected \"%s\"", *td); } diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index a9de8ea3c..82f300c64 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -2175,7 +2175,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec) if(!plink->text) continue; - if(dbParseLink(plink->text, pflddes->field_type, &link_info)!=0) { + if(dbParseLink(plink->text, pflddes->field_type, &link_info, 0)!=0) { /* This was already parsed once when ->text was set. * Any syntax error messages were printed at that time. */ @@ -2204,7 +2204,7 @@ void dbFreeLinkInfo(dbLinkInfo *pinfo) pinfo->target = NULL; } -long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo) +long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, unsigned opts) { char *pstr; size_t len; @@ -2240,7 +2240,7 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo) /* Check for braces => JSON */ if (*str == '{' && str[len-1] == '}') { - if (dbJLinkParse(str, len, ftype, &pinfo->jlink)) + if (dbJLinkParse(str, len, ftype, &pinfo->jlink, opts)) goto fail; pinfo->ltype = JSON_LINK; @@ -2573,8 +2573,19 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring) case DBF_FWDLINK: { dbLinkInfo link_info; DBLINK *plink = (DBLINK *)pfield; + DBENTRY infoentry; + unsigned opts = 0; - status = dbParseLink(pstring, pflddes->field_type, &link_info); + if(pdbentry->precnode && ellCount(&pdbentry->precnode->infoList)) { + dbCopyEntryContents(pdbentry, &infoentry); + + if(dbFindInfo(&infoentry, "linkDebug")==0 && epicsStrCaseCmp(dbGetInfoString(&infoentry), "YES")==0) + opts |= LINK_DEBUG; + + dbFinishEntry(&infoentry); + } + + status = dbParseLink(pstring, pflddes->field_type, &link_info, opts); if (status) break; if (plink->type==CONSTANT && plink->value.constantStr==NULL) { diff --git a/src/ioc/dbStatic/dbStaticPvt.h b/src/ioc/dbStatic/dbStaticPvt.h index 4e7d2d6f1..3af74459b 100644 --- a/src/ioc/dbStatic/dbStaticPvt.h +++ b/src/ioc/dbStatic/dbStaticPvt.h @@ -59,10 +59,12 @@ typedef struct dbLinkInfo { long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec); +#define LINK_DEBUG 1 + /* Parse link string. no record locks needed. * on success caller must free pinfo->target */ -epicsShareFunc long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo); +epicsShareFunc long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, unsigned opts); /* Check if link type allow the parsed link value pinfo * to be assigned to the given link. * Record containing plink must be locked.