In some cases the license-identification header was missing, so I added that as well. Replaced the remaining headers that specifically identified "Versions 3.13.7 and higher". Makefiles and the build system were deliberately excluded.
1047 lines
30 KiB
C
1047 lines
30 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
/* lnkDebug.c */
|
|
|
|
/* Usage
|
|
* {debug:{...:...}}
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "alarm.h"
|
|
#include "dbDefs.h"
|
|
#include "dbAccessDefs.h"
|
|
#include "dbLink.h"
|
|
#include "dbJLink.h"
|
|
#include "dbStaticLib.h"
|
|
#include "errlog.h"
|
|
#include "epicsTime.h"
|
|
|
|
#include "epicsExport.h"
|
|
|
|
/* This is for debugging the debug link-type */
|
|
int lnkDebug_debug;
|
|
epicsExportAddress(int, lnkDebug_debug);
|
|
|
|
#define IFDEBUG(n) if (lnkDebug_debug >= (n))
|
|
|
|
typedef struct debug_link {
|
|
jlink jlink; /* embedded object */
|
|
short dbfType;
|
|
unsigned trace:1;
|
|
const jlif *child_jlif;
|
|
const lset *child_lset;
|
|
jlif jlif;
|
|
lset lset;
|
|
struct link child_link;
|
|
} debug_link;
|
|
|
|
|
|
/********************* Delegating jlif Routines *********************/
|
|
|
|
static void delegate_free(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
struct link *plink = &dlink->child_link;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::free_jlink(%p)\n",
|
|
pif->name, pjlink);
|
|
|
|
pif->free_jlink(pjlink);
|
|
plink->type = 0;
|
|
plink->value.json.jlink = NULL;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::free_jlink(%p) returned\n",
|
|
pif->name, pjlink);
|
|
}
|
|
|
|
static jlif_result delegate_null(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_null(%p)\n",
|
|
pif->name, pjlink);
|
|
|
|
res = pif->parse_null(pjlink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_null(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_boolean(jlink *pjlink, int val)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_boolean(%p, %d)\n",
|
|
pif->name, pjlink, val);
|
|
|
|
res = pif->parse_boolean(pjlink, val);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_boolean(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_integer(jlink *pjlink, long long num)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_integer(%p, %lld)\n",
|
|
pif->name, pjlink, num);
|
|
|
|
res = pif->parse_integer(pjlink, num);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_integer(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_double(jlink *pjlink, double num)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_double(%p, %g)\n",
|
|
pif->name, pjlink, num);
|
|
|
|
res = pif->parse_double(pjlink, num);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_double(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_string(jlink *pjlink, const char *val, size_t len)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_string(%p, \"%.*s\")\n",
|
|
pif->name, pjlink, (int) len, val);
|
|
|
|
res = pif->parse_string(pjlink, val, len);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_string(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_key_result delegate_start_map(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_key_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_start_map(%p)\n",
|
|
pif->name, pjlink);
|
|
|
|
res = pif->parse_start_map(pjlink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_start_map(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_key_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_map_key(jlink *pjlink, const char *key, size_t len)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_map_key(%p, \"%.*s\")\n",
|
|
pif->name, pjlink, (int) len, key);
|
|
|
|
res = pif->parse_map_key(pjlink, key, len);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_map_key(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_end_map(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_end_map(%p)\n",
|
|
pif->name, pjlink);
|
|
|
|
res = pif->parse_end_map(pjlink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_end_map(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_start_array(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_(%p)\n",
|
|
pif->name, pjlink);
|
|
|
|
res = pif->parse_start_array(pjlink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_start_array(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static jlif_result delegate_end_array(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
jlif_result res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::parse_end_array(%p)\n",
|
|
pif->name, pjlink);
|
|
|
|
res = pif->parse_end_array(pjlink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::parse_end_array(%p) returned %s\n",
|
|
pif->name, pjlink, jlif_result_name[res]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static void delegate_start_child(jlink *pjlink, jlink *child)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::start_child(%p, %p)\n",
|
|
pif->name, pjlink, child);
|
|
|
|
pif->start_child(pjlink, child);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::start_child(%p) returned\n",
|
|
pif->name, pjlink);
|
|
}
|
|
|
|
static void delegate_end_child(jlink *pjlink, jlink *child)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::end_child(%p, %p)\n",
|
|
pif->name, pjlink, child);
|
|
|
|
pif->end_child(pjlink, child);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::end_child(%p) returned\n",
|
|
pif->name, pjlink);
|
|
}
|
|
|
|
static struct lset* delegate_get_lset(const jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: NOT calling %s::get_lset(%p)\n",
|
|
dlink->child_jlif->name, pjlink);
|
|
|
|
return &dlink->lset;
|
|
}
|
|
|
|
static void delegate_report(const jlink *pjlink, int level, int indent)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::report(%p, %d, %d)\n",
|
|
pif->name, pjlink, level, indent);
|
|
|
|
pif->report(pjlink, level, indent);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::report(%p) returned\n",
|
|
pif->name, pjlink);
|
|
}
|
|
|
|
static long delegate_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
|
|
const jlif *pif = dlink->child_jlif;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::map_children(%p, %p, %p)\n",
|
|
pif->name, pjlink, rtn, ctx);
|
|
|
|
res = pif->map_children(pjlink, rtn, ctx);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::map_children(%p) returned %ld\n",
|
|
pif->name, pjlink, res);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/********************* Delegating lset Routines *********************/
|
|
|
|
static void delegate_openLink(struct link *plink)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::openLink(%p = jlink %p)\n",
|
|
dlink->child_jlif->name, clink, clink->value.json.jlink);
|
|
|
|
clink->precord = plink->precord;
|
|
clset->openLink(clink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::openLink(%p) returned\n",
|
|
dlink->child_jlif->name, clink);
|
|
}
|
|
|
|
static void delegate_removeLink(struct dbLocker *locker, struct link *plink)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::removeLink(%p, %p)\n",
|
|
dlink->child_jlif->name, locker, clink);
|
|
|
|
clset->removeLink(locker, clink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::removeLink(%p) returned\n",
|
|
dlink->child_jlif->name, clink);
|
|
}
|
|
|
|
static long delegate_loadScalar(struct link *plink, short dbrType, void *pbuffer)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::loadScalar(%p, %s, %p)\n",
|
|
dlink->child_jlif->name, clink,
|
|
dbGetFieldTypeString(dbrType), pbuffer);
|
|
|
|
res = clset->loadScalar(clink, dbrType, pbuffer);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::loadScalar(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_loadLS(struct link *plink, char *pbuffer, epicsUInt32 size,
|
|
epicsUInt32 *plen)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::loadLS(%p, %p, %u)\n",
|
|
dlink->child_jlif->name, clink, pbuffer, size);
|
|
|
|
res = clset->loadLS(clink, pbuffer, size, plen);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::loadLS(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Loaded: %u byte(s) \"%s\"\n", *plen, pbuffer);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
|
long *pnRequest)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::loadArray(%p, %s, %p, %ld)\n",
|
|
dlink->child_jlif->name, clink,
|
|
dbGetFieldTypeString(dbrType), pbuffer, pnRequest ? *pnRequest : 0l);
|
|
|
|
res = clset->loadArray(clink, dbrType, pbuffer, pnRequest);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::loadArray(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Loaded: %ld element(s)\n", pnRequest ? *pnRequest : 1l);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int delegate_isConnected(const struct link *plink)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
int res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::isConnected(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->isConnected(clink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::isConnected(%p) returned %d (%s)\n",
|
|
dlink->child_jlif->name, clink, res,
|
|
res == 0 ? "No" : res == 1 ? "Yes" : "Bad value");
|
|
|
|
return res;
|
|
}
|
|
|
|
static int delegate_getDBFtype(const struct link *plink)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
int res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getDBFtype(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getDBFtype(clink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::getDBFtype(%p) returned %d (%s)\n",
|
|
dlink->child_jlif->name, clink, res,
|
|
res == -1 ? "Link disconnected" : dbGetFieldTypeString(res));
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getElements(const struct link *plink, long *pnElements)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getElements(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getElements(clink, pnElements);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getElements(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Result: %ld element(s)\n", *pnElements);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getValue(struct link *plink, short dbrType, void *pbuffer,
|
|
long *pnRequest)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getValue(%p, %s, %p, %ld)\n",
|
|
dlink->child_jlif->name, clink,
|
|
dbGetFieldTypeString(dbrType), pbuffer, pnRequest ? *pnRequest : 0l);
|
|
|
|
res = clset->getValue(clink, dbrType, pbuffer, pnRequest);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getValue(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got: %ld element(s)\n", pnRequest ? *pnRequest : 1l);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getControlLimits(const struct link *plink,
|
|
double *lo, double *hi)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getControlLimits(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getControlLimits(clink, lo, hi);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getControlLimits(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got: Lo = %g, Hi = %g\n", *lo, *hi);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getGraphicLimits(const struct link *plink,
|
|
double *lo, double *hi)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getGraphicLimits(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getGraphicLimits(clink, lo, hi);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getGraphicLimits(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got: Lo = %g, Hi = %g\n", *lo, *hi);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getAlarmLimits(const struct link *plink,
|
|
double *lolo, double *lo, double *hi, double *hihi)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getAlarmLimits(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getAlarmLimits(clink, lolo, lo, hi, hihi);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getAlarmLimits(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got: Lolo = %g, Lo = %g, Hi = %g, Hihi = %g\n",
|
|
*lolo, *lo, *hi, *hihi);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getPrecision(const struct link *plink, short *precision)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getPrecision(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getPrecision(clink, precision);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getPrecision(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got: prec = %d\n", *precision);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getUnits(const struct link *plink, char *units, int unitsSize)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getUnits(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getUnits(clink, units, unitsSize);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getUnits(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got: Units = '%s'\n", units);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getAlarm(const struct link *plink, epicsEnum16 *stat,
|
|
epicsEnum16 *sevr)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getAlarm(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getAlarm(clink, stat, sevr);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getAlarm(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0)
|
|
printf(" Got:%s%s%s%s\n",
|
|
stat ? " Status = " : "",
|
|
stat && (*stat < ALARM_NSTATUS) ?
|
|
epicsAlarmConditionStrings[*stat] : "Bad-status",
|
|
sevr ? " Severity = " : "",
|
|
sevr && (*sevr < ALARM_NSEV) ?
|
|
epicsAlarmSeverityStrings[*sevr] : "Bad-severity"
|
|
);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_getTimeStamp(const struct link *plink, epicsTimeStamp *pstamp)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::getTimeStamp(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
res = clset->getTimeStamp(clink, pstamp);
|
|
|
|
if (dlink->trace) {
|
|
printf("Link trace: %s::getTimeStamp(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
if (res == 0) {
|
|
char timeStr[32];
|
|
|
|
epicsTimeToStrftime(timeStr, sizeof(timeStr),
|
|
"%Y-%m-%d %H:%M:%S.%09f", pstamp);
|
|
printf(" Got: Timestamp = '%s'\n", timeStr);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_putValue(struct link *plink, short dbrType,
|
|
const void *pbuffer, long nRequest)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::putValue(%p, %s, %p, %ld)\n",
|
|
dlink->child_jlif->name, clink,
|
|
dbGetFieldTypeString(dbrType), pbuffer, nRequest);
|
|
|
|
res = clset->putValue(clink, dbrType, pbuffer, nRequest);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::putValue(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
|
|
return res;
|
|
}
|
|
|
|
static long delegate_putAsync(struct link *plink, short dbrType,
|
|
const void *pbuffer, long nRequest)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::putAsync(%p, %s, %p, %ld)\n",
|
|
dlink->child_jlif->name, clink,
|
|
dbGetFieldTypeString(dbrType), pbuffer, nRequest);
|
|
|
|
res = clset->putAsync(clink, dbrType, pbuffer, nRequest);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::putAsync(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
|
|
return res;
|
|
}
|
|
|
|
static void delegate_scanForward(struct link *plink)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::scanForward(%p)\n",
|
|
dlink->child_jlif->name, clink);
|
|
|
|
clset->scanForward(clink);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::scanForward(%p) returned\n",
|
|
dlink->child_jlif->name, clink);
|
|
}
|
|
|
|
static long delegate_doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
|
{
|
|
debug_link *dlink = CONTAINER(plink->value.json.jlink,
|
|
struct debug_link, jlink);
|
|
struct link *clink = &dlink->child_link;
|
|
const lset *clset = dlink->child_lset;
|
|
long res;
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: Calling %s::doLocked(%p, %p, %p)\n",
|
|
dlink->child_jlif->name, clink, rtn, priv);
|
|
|
|
res = clset->doLocked(clink, rtn, priv);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::doLocked(%p) returned %ld (0x%lx)\n",
|
|
dlink->child_jlif->name, clink, res, res);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/************************ Debug jlif Routines ***********************/
|
|
|
|
static jlink* lnkDebug_alloc(short dbfType)
|
|
{
|
|
debug_link *dlink;
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_alloc(%s)\n", dbGetFieldTypeString(dbfType));
|
|
|
|
dlink = calloc(1, sizeof(struct debug_link));
|
|
if (!dlink) {
|
|
errlogPrintf("lnkDebug: calloc() failed.\n");
|
|
return NULL;
|
|
}
|
|
|
|
dlink->dbfType = dbfType;
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_alloc -> debug@%p\n", dlink);
|
|
|
|
return &dlink->jlink;
|
|
}
|
|
|
|
static jlink* lnkTrace_alloc(short dbfType)
|
|
{
|
|
debug_link *dlink;
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkTrace_alloc(%s)\n", dbGetFieldTypeString(dbfType));
|
|
|
|
dlink = calloc(1, sizeof(struct debug_link));
|
|
if (!dlink) {
|
|
errlogPrintf("lnkTrace: calloc() failed.\n");
|
|
return NULL;
|
|
}
|
|
|
|
dlink->dbfType = dbfType;
|
|
dlink->trace = 1;
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkTrace_alloc -> debug@%p\n", dlink);
|
|
|
|
return &dlink->jlink;
|
|
}
|
|
|
|
static void lnkDebug_free(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_free(debug@%p)\n", dlink);
|
|
|
|
dbJLinkFree(dlink->child_link.value.json.jlink);
|
|
|
|
free(dlink);
|
|
}
|
|
|
|
static jlif_key_result lnkDebug_start_map(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_start_map(debug@%p)\n", dlink);
|
|
|
|
switch (dlink->dbfType) {
|
|
case DBF_INLINK:
|
|
return jlif_key_child_inlink;
|
|
case DBF_OUTLINK:
|
|
return jlif_key_child_outlink;
|
|
case DBF_FWDLINK:
|
|
return jlif_key_child_outlink;
|
|
}
|
|
return jlif_key_stop;
|
|
}
|
|
|
|
static jlif_result lnkDebug_end_map(jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_end_map(debug@%p)\n", dlink);
|
|
|
|
return jlif_continue;
|
|
}
|
|
|
|
static void lnkDebug_start_child(jlink *parent, jlink *child)
|
|
{
|
|
debug_link *dlink = CONTAINER(parent, struct debug_link, jlink);
|
|
const jlif *pif = child->pif;
|
|
const jlif delegate_jlif = {
|
|
pif->name,
|
|
pif->alloc_jlink, /* Never used */
|
|
delegate_free,
|
|
pif->parse_null ? delegate_null : NULL,
|
|
pif->parse_boolean ? delegate_boolean : NULL,
|
|
pif->parse_integer ? delegate_integer : NULL,
|
|
pif->parse_double ? delegate_double : NULL,
|
|
pif->parse_string ? delegate_string : NULL,
|
|
pif->parse_start_map ? delegate_start_map : NULL,
|
|
pif->parse_map_key ? delegate_map_key : NULL,
|
|
pif->parse_end_map ? delegate_end_map : NULL,
|
|
pif->parse_start_array ? delegate_start_array : NULL,
|
|
pif->parse_end_array ? delegate_end_array : NULL,
|
|
pif->end_child ? delegate_end_child : NULL,
|
|
delegate_get_lset,
|
|
pif->report ? delegate_report : NULL,
|
|
pif->map_children ? delegate_map_children : NULL,
|
|
pif->start_child ? delegate_start_child : NULL
|
|
};
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_start_child(debug@%p, %s@%p)\n", dlink,
|
|
child->pif->name, child);
|
|
|
|
dlink->child_jlif = pif;
|
|
memcpy(&dlink->jlif, &delegate_jlif, sizeof(jlif));
|
|
|
|
child->debug = 1;
|
|
child->pif = &dlink->jlif; /* Replace Child's interface table */
|
|
|
|
IFDEBUG(15)
|
|
printf("lnkDebug_start_child: pif %p => %p\n", pif, child->pif);
|
|
|
|
if (dlink->trace)
|
|
printf("Link trace: %s::alloc_jlink(%s) returned %p\n",
|
|
pif->name, dbGetFieldTypeString(dlink->dbfType), child);
|
|
}
|
|
|
|
static void lnkDebug_end_child(jlink *parent, jlink *child)
|
|
{
|
|
debug_link *dlink = CONTAINER(parent, struct debug_link, jlink);
|
|
struct link *plink = &dlink->child_link;
|
|
const lset *plset = dlink->child_jlif->get_lset(child);
|
|
lset delegate_lset = {
|
|
plset->isConstant,
|
|
plset->isVolatile,
|
|
plset->openLink ? delegate_openLink : NULL,
|
|
plset->removeLink ? delegate_removeLink : NULL,
|
|
plset->loadScalar ? delegate_loadScalar : NULL,
|
|
plset->loadLS ? delegate_loadLS : NULL,
|
|
plset->loadArray ? delegate_loadArray : NULL,
|
|
plset->isConnected ? delegate_isConnected : NULL,
|
|
plset->getDBFtype ? delegate_getDBFtype : NULL,
|
|
plset->getElements ? delegate_getElements : NULL,
|
|
plset->getValue ? delegate_getValue : NULL,
|
|
plset->getControlLimits ? delegate_getControlLimits : NULL,
|
|
plset->getGraphicLimits ? delegate_getGraphicLimits : NULL,
|
|
plset->getAlarmLimits ? delegate_getAlarmLimits : NULL,
|
|
plset->getPrecision ? delegate_getPrecision : NULL,
|
|
plset->getUnits ? delegate_getUnits : NULL,
|
|
plset->getAlarm ? delegate_getAlarm : NULL,
|
|
plset->getTimeStamp ? delegate_getTimeStamp : NULL,
|
|
plset->putValue ? delegate_putValue : NULL,
|
|
plset->putAsync ? delegate_putAsync : NULL,
|
|
plset->scanForward ? delegate_scanForward : NULL,
|
|
plset->doLocked ? delegate_doLocked : NULL
|
|
};
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_end_child(debug@%p, %s@%p)\n", dlink,
|
|
child->pif->name, child);
|
|
|
|
plink->type = JSON_LINK;
|
|
plink->value.json.string = NULL;
|
|
plink->value.json.jlink = child;
|
|
|
|
dlink->child_lset = plset;
|
|
memcpy(&dlink->lset, &delegate_lset, sizeof(lset));
|
|
|
|
IFDEBUG(15)
|
|
printf("lnkDebug_end_child: lset %p => %p\n", plset, &dlink->lset);
|
|
}
|
|
|
|
static struct lset* lnkDebug_get_lset(const jlink *pjlink)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_get_lset(debug@%p)\n", pjlink);
|
|
|
|
return &dlink->lset;
|
|
}
|
|
|
|
static void lnkDebug_report(const jlink *pjlink, int level, int indent)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_report(debug@%p)\n", dlink);
|
|
|
|
if (dlink->trace)
|
|
printf("%*s'trace':\n", indent, "");
|
|
else
|
|
printf("%*s'debug':\n", indent, "");
|
|
|
|
if (dlink->child_link.type == JSON_LINK) {
|
|
dbJLinkReport(dlink->child_link.value.json.jlink, level, indent + 2);
|
|
}
|
|
}
|
|
|
|
long lnkDebug_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
|
|
{
|
|
debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
|
|
|
|
IFDEBUG(10)
|
|
printf("lnkDebug_map_children(debug@%p)\n", dlink);
|
|
|
|
if (dlink->child_link.type == JSON_LINK) {
|
|
return dbJLinkMapChildren(&dlink->child_link, rtn, ctx);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/************************* Interface Tables *************************/
|
|
|
|
static jlif lnkDebugIf = {
|
|
"debug", lnkDebug_alloc, lnkDebug_free,
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
lnkDebug_start_map, NULL, lnkDebug_end_map,
|
|
NULL, NULL, lnkDebug_end_child, lnkDebug_get_lset,
|
|
lnkDebug_report, lnkDebug_map_children, lnkDebug_start_child
|
|
};
|
|
epicsExportAddress(jlif, lnkDebugIf);
|
|
|
|
static jlif lnkTraceIf = {
|
|
"trace", lnkTrace_alloc, lnkDebug_free,
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
lnkDebug_start_map, NULL, lnkDebug_end_map,
|
|
NULL, NULL, lnkDebug_end_child, lnkDebug_get_lset,
|
|
lnkDebug_report, lnkDebug_map_children, lnkDebug_start_child
|
|
};
|
|
epicsExportAddress(jlif, lnkTraceIf);
|