diff --git a/src/ioc/db/dbCa.c b/src/ioc/db/dbCa.c index 88d4468f4..d680dc4a7 100644 --- a/src/ioc/db/dbCa.c +++ b/src/ioc/db/dbCa.c @@ -714,7 +714,7 @@ static void scanLinkOnce(dbCommon *prec, caLink *pca) { static lset dbCa_lset = { 0, 1, /* not Constant, Volatile */ - dbCaRemoveLink, + NULL, dbCaRemoveLink, NULL, NULL, NULL, isConnected, getDBFtype, getElements, diff --git a/src/ioc/db/dbConstLink.c b/src/ioc/db/dbConstLink.c index 5f3aa1ac0..32e0c88c1 100644 --- a/src/ioc/db/dbConstLink.c +++ b/src/ioc/db/dbConstLink.c @@ -124,7 +124,7 @@ static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer, static lset dbConst_lset = { 1, 0, /* Constant, not Volatile */ - NULL, + NULL, NULL, dbConstLoadScalar, dbConstLoadLS, dbConstLoadArray, diff --git a/src/ioc/db/dbDbLink.c b/src/ioc/db/dbDbLink.c index 2fc21c5bc..294a13fe0 100644 --- a/src/ioc/db/dbDbLink.c +++ b/src/ioc/db/dbDbLink.c @@ -337,7 +337,7 @@ static void dbDbScanFwdLink(struct link *plink) static lset dbDb_lset = { 0, 0, /* not Constant, not Volatile */ - dbDbRemoveLink, + NULL, dbDbRemoveLink, NULL, NULL, NULL, dbDbIsConnected, dbDbGetDBFtype, dbDbGetElements, diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c index f94a90e17..11f364e5e 100644 --- a/src/ioc/db/dbJLink.c +++ b/src/ioc/db/dbJLink.c @@ -43,17 +43,13 @@ typedef struct parseContext { unsigned key_is_link:1; } parseContext; -#define CALLIF(routine) !routine ? jlif_stop : routine +#define CALL_OR_STOP(routine) !(routine) ? jlif_stop : (routine) - -static int dbjl_value(parseContext *parser, jlif_result result) { +static int dbjl_return(parseContext *parser, jlif_result result) { jlink *pjlink = parser->pjlink; - IFDEBUG(10) { - printf("dbjl_value(%s@%p, %d)\n", pjlink->pif->name, pjlink, result); - printf(" jsonDepth=%d, linkDepth=%d, key_is_link=%d\n", - parser->jsonDepth, parser->linkDepth, parser->key_is_link); - } + IFDEBUG(10) + printf("dbjl_return(%s@%p, %d)\n", pjlink->pif->name, pjlink, result); if (result == jlif_stop && pjlink) { jlink *parent; @@ -65,19 +61,35 @@ static int dbjl_value(parseContext *parser, jlif_result result) { pjlink->pif->free_jlink(pjlink); } - if (result == jlif_stop || parser->linkDepth > 0) - return result; + return result; +} + +static int dbjl_value(parseContext *parser, jlif_result result) { + jlink *pjlink = parser->pjlink; + jlink *parent; + + IFDEBUG(10) { + printf("dbjl_value(%s@%p, %d)\n", pjlink->pif->name, pjlink, result); + printf(" jsonDepth=%d, linkDepth=%d, key_is_link=%d\n", + parser->jsonDepth, parser->linkDepth, parser->key_is_link); + } + + if (result == jlif_stop || parser->linkDepth > 0) + return dbjl_return(parser, result); + + parent = pjlink->parent; + if (!parent) + parser->product = pjlink; + else if (parent->pif->end_child) + parent->pif->end_child(parent, pjlink); - parser->product = pjlink; parser->key_is_link = 0; - if (pjlink) - parser->pjlink = pjlink->parent; + parser->pjlink = parent; IFDEBUG(8) printf("dbjl_value: product = %p\n", pjlink); - return pjlink->pif->end_parse ? pjlink->pif->end_parse(pjlink) - : jlif_continue; + return jlif_continue; } static int dbjl_null(void *ctx) { @@ -88,7 +100,8 @@ static int dbjl_null(void *ctx) { printf("dbjl_null(%s@%p)\n", pjlink->pif->name, pjlink); assert(pjlink); - return dbjl_value(parser, CALLIF(pjlink->pif->parse_null)(pjlink)); + return dbjl_value(parser, + CALL_OR_STOP(pjlink->pif->parse_null)(pjlink)); } static int dbjl_boolean(void *ctx, int val) { @@ -96,7 +109,8 @@ static int dbjl_boolean(void *ctx, int val) { jlink *pjlink = parser->pjlink; assert(pjlink); - return dbjl_value(parser, CALLIF(pjlink->pif->parse_boolean)(pjlink, val)); + return dbjl_value(parser, + CALL_OR_STOP(pjlink->pif->parse_boolean)(pjlink, val)); } static int dbjl_integer(void *ctx, long num) { @@ -104,10 +118,12 @@ static int dbjl_integer(void *ctx, long num) { jlink *pjlink = parser->pjlink; IFDEBUG(10) - printf("dbjl_integer(%s@%p, %ld)\n", pjlink->pif->name, pjlink, num); + printf("dbjl_integer(%s@%p, %ld)\n", + pjlink->pif->name, pjlink, num); assert(pjlink); - return dbjl_value(parser, CALLIF(pjlink->pif->parse_integer)(pjlink, num)); + return dbjl_value(parser, + CALL_OR_STOP(pjlink->pif->parse_integer)(pjlink, num)); } static int dbjl_double(void *ctx, double num) { @@ -115,10 +131,12 @@ static int dbjl_double(void *ctx, double num) { jlink *pjlink = parser->pjlink; IFDEBUG(10) - printf("dbjl_double(%s@%p, %g)\n", pjlink->pif->name, pjlink, num); + printf("dbjl_double(%s@%p, %g)\n", + pjlink->pif->name, pjlink, num); assert(pjlink); - return dbjl_value(parser, CALLIF(pjlink->pif->parse_double)(pjlink, num)); + return dbjl_value(parser, + CALL_OR_STOP(pjlink->pif->parse_double)(pjlink, num)); } static int dbjl_string(void *ctx, const unsigned char *val, unsigned len) { @@ -126,11 +144,12 @@ static int dbjl_string(void *ctx, const unsigned char *val, unsigned len) { jlink *pjlink = parser->pjlink; IFDEBUG(10) - printf("dbjl_string(%s@%p, \"%.*s\")\n", pjlink->pif->name, pjlink, len, val); + printf("dbjl_string(%s@%p, \"%.*s\")\n", + pjlink->pif->name, pjlink, len, val); assert(pjlink); return dbjl_value(parser, - CALLIF(pjlink->pif->parse_string)(pjlink, (const char *) val, len)); + CALL_OR_STOP(pjlink->pif->parse_string)(pjlink, (const char *) val, len)); } static int dbjl_start_map(void *ctx) { @@ -159,8 +178,9 @@ static int dbjl_start_map(void *ctx) { parser->linkDepth++; parser->jsonDepth++; - result = CALLIF(pjlink->pif->parse_start_map)(pjlink); - if (result == jlif_key_embed_link) { + + result = CALL_OR_STOP(pjlink->pif->parse_start_map)(pjlink); + if (result == jlif_key_child_link) { parser->key_is_link = 1; result = jlif_continue; } @@ -168,7 +188,7 @@ static int dbjl_start_map(void *ctx) { IFDEBUG(10) printf("dbjl_start_map -> %d\n", result); - return result; + return dbjl_return(parser, result); } static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { @@ -178,13 +198,12 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { size_t lnlen = len; linkSup *linkSup; jlif *pjlif; - jlif_result result; if (!parser->key_is_link) { if (!pjlink) { errlogPrintf("dbJLinkInit: Illegal second link key '%.*s'\n", len, key); - return jlif_stop; + return dbjl_return(parser, jlif_stop); } IFDEBUG(10) { @@ -195,7 +214,9 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { } assert(parser->linkDepth > 0); - return CALLIF(pjlink->pif->parse_map_key)(pjlink, (const char *) key, len); + return dbjl_return(parser, + CALL_OR_STOP(pjlink->pif->parse_map_key)(pjlink, + (const char *) key, len)); } IFDEBUG(10) { @@ -213,44 +234,35 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) { if (!linkSup) { errlogPrintf("dbJLinkInit: Link type '%s' not found\n", link_name); - return jlif_stop; + return dbjl_return(parser, jlif_stop); } pjlif = linkSup->pjlif; if (!pjlif) { errlogPrintf("dbJLinkInit: Support for Link type '%s' not loaded\n", link_name); - return jlif_stop; + return dbjl_return(parser, jlif_stop); } pjlink = pjlif->alloc_jlink(parser->dbfType); if (!pjlink) { errlogPrintf("dbJLinkInit: Out of memory\n"); - return jlif_stop; + return dbjl_return(parser, jlif_stop); } pjlink->pif = pjlif; if (parser->pjlink) { - /* This is an embedded link */ + /* We're starting a child link, save its parent */ pjlink->parent = parser->pjlink; } + parser->pjlink = pjlink; - result = pjlif->start_parse ? pjlif->start_parse(pjlink) : jlif_continue; - if (result == jlif_continue) { - parser->pjlink = pjlink; + IFDEBUG(8) + printf("dbjl_map_key: New %s@%p\n", pjlink->pif->name, pjlink); - IFDEBUG(8) - printf("dbjl_map_key: New %s@%p\n", pjlink->pif->name, pjlink); - } - else { - pjlif->free_jlink(pjlink); - } - // FIXME Ensure link map has only one link key... + // FIXME How to ensure a link map has only one key/value pair? - IFDEBUG(10) - printf("dbjl_map_key -> %d\n", result); - - return result; + return jlif_continue; } static int dbjl_end_map(void *ctx) { @@ -269,7 +281,8 @@ static int dbjl_end_map(void *ctx) { if (parser->linkDepth > 0) { parser->linkDepth--; - result = dbjl_value(parser, CALLIF(pjlink->pif->parse_end_map)(pjlink)); + result = dbjl_value(parser, + CALL_OR_STOP(pjlink->pif->parse_end_map)(pjlink)); } else { result = jlif_continue; @@ -290,7 +303,9 @@ static int dbjl_start_array(void *ctx) { assert(pjlink); parser->linkDepth++; parser->jsonDepth++; - return CALLIF(pjlink->pif->parse_start_array)(pjlink); + + return dbjl_return(parser, + CALL_OR_STOP(pjlink->pif->parse_start_array)(pjlink)); } static int dbjl_end_array(void *ctx) { @@ -306,9 +321,12 @@ static int dbjl_end_array(void *ctx) { assert(pjlink); parser->linkDepth--; parser->jsonDepth--; - return dbjl_value(parser, CALLIF(pjlink->pif->parse_end_array)(pjlink)); + + return dbjl_value(parser, + CALL_OR_STOP(pjlink->pif->parse_end_array)(pjlink)); } + static yajl_callbacks dbjl_callbacks = { dbjl_null, dbjl_boolean, dbjl_integer, dbjl_double, NULL, dbjl_string, dbjl_start_map, dbjl_map_key, dbjl_end_map, dbjl_start_array, dbjl_end_array @@ -380,7 +398,8 @@ long dbJLinkInit(struct link *plink) pjlink = plink->value.json.jlink; if (pjlink) - plink->lset = pjlink->pif->get_lset(pjlink, plink); + plink->lset = pjlink->pif->get_lset(pjlink); + dbLinkOpen(plink); return 0; } diff --git a/src/ioc/db/dbJLink.h b/src/ioc/db/dbJLink.h index fc3d86005..7b32fb130 100644 --- a/src/ioc/db/dbJLink.h +++ b/src/ioc/db/dbJLink.h @@ -27,7 +27,7 @@ typedef enum { typedef enum { jlif_key_stop = jlif_stop, jlif_key_continue = jlif_continue, - jlif_key_embed_link + jlif_key_child_link } jlif_key_result; struct link; @@ -44,7 +44,6 @@ typedef struct jlif { const char *name; jlink* (*alloc_jlink)(short dbfType); void (*free_jlink)(jlink *); - jlif_result (*start_parse)(jlink *); jlif_result (*parse_null)(jlink *); jlif_result (*parse_boolean)(jlink *, int val); jlif_result (*parse_integer)(jlink *, long num); @@ -55,8 +54,8 @@ typedef struct jlif { jlif_result (*parse_end_map)(jlink *); jlif_result (*parse_start_array)(jlink *); jlif_result (*parse_end_array)(jlink *); - jlif_result (*end_parse)(jlink *); - struct lset* (*get_lset)(const jlink *, struct link *); + void (*end_child)(jlink *parent, jlink *child); + struct lset* (*get_lset)(const jlink *); void (*report)(const jlink *); } jlif; diff --git a/src/ioc/db/dbLink.c b/src/ioc/db/dbLink.c index 2f2bd461a..f58944222 100644 --- a/src/ioc/db/dbLink.c +++ b/src/ioc/db/dbLink.c @@ -160,6 +160,14 @@ void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, } } +void dbLinkOpen(struct link *plink) +{ + lset *plset = plink->lset; + + if (plset && plset->openLink) + plset->openLink(plink); +} + void dbRemoveLink(struct dbLocker *locker, struct link *plink) { lset *plset = plink->lset; diff --git a/src/ioc/db/dbLink.h b/src/ioc/db/dbLink.h index ebdf24307..3cf676af9 100644 --- a/src/ioc/db/dbLink.h +++ b/src/ioc/db/dbLink.h @@ -32,6 +32,9 @@ typedef struct lset { const unsigned isConstant:1; const unsigned isVolatile:1; + /* Activation */ + void (*openLink)(struct link *plink); + /* Destructor */ void (*removeLink)(struct dbLocker *locker, struct link *plink); @@ -76,6 +79,8 @@ typedef struct lset { epicsShareFunc void dbInitLink(struct link *plink, short dbfType); epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget); + +epicsShareFunc void dbLinkOpen(struct link *plink); epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink); epicsShareFunc int dbLinkIsDefined(const struct link *plink); /* 0 or 1 */ diff --git a/src/std/link/lnkConst.c b/src/std/link/lnkConst.c index 14d8a5b59..1059521d3 100644 --- a/src/std/link/lnkConst.c +++ b/src/std/link/lnkConst.c @@ -275,9 +275,9 @@ static jlif_result lnkConst_end_array(jlink *pjlink) { return jlif_continue; } -static struct lset* lnkConst_get_lset(const jlink *pjlink, struct link *plink) { +static struct lset* lnkConst_get_lset(const jlink *pjlink) { IFDEBUG(10) - printf("lnkConst_get_lset(const@%p, %p)\n", pjlink, plink); + printf("lnkConst_get_lset(const@%p)\n", pjlink); return &lnkConst_lset; } @@ -466,7 +466,8 @@ static long lnkConst_getValue(struct link *plink, short dbrType, void *pbuffer, static lset lnkConst_lset = { 1, 0, /* Constant, not Volatile */ - NULL, lnkConst_loadScalar, lnkConst_loadLS, lnkConst_loadArray, NULL, + NULL, NULL, + lnkConst_loadScalar, lnkConst_loadLS, lnkConst_loadArray, NULL, NULL, lnkConst_getNelements, lnkConst_getValue, NULL, NULL, NULL, NULL, NULL, @@ -476,7 +477,7 @@ static lset lnkConst_lset = { }; static jlif lnkConstIf = { - "const", lnkConst_alloc, lnkConst_free, NULL, + "const", lnkConst_alloc, lnkConst_free, NULL, lnkConst_boolean, lnkConst_integer, lnkConst_double, lnkConst_string, NULL, NULL, NULL, lnkConst_start_array, lnkConst_end_array, NULL, lnkConst_get_lset, lnkConst_report