Integrated dbChannel more and extended its functionality:
* Register filters in pdbbase, using a list and gphash * Do record and field search first * Test loads a DBD/DB file to provide a record to find
This commit is contained in:
+242
-48
@@ -13,8 +13,12 @@
|
||||
#include "dbBase.h"
|
||||
#include "link.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "errlog.h"
|
||||
#include "gpHash.h"
|
||||
#include "recSup.h"
|
||||
#include "special.h"
|
||||
#include "yajl_parse.h"
|
||||
|
||||
|
||||
@@ -24,10 +28,16 @@ typedef struct parseContext {
|
||||
int depth;
|
||||
} parseContext;
|
||||
|
||||
typedef struct filterPlugin {
|
||||
ELLNODE node;
|
||||
const char *name;
|
||||
const chFilterIf *fif;
|
||||
} filterPlugin;
|
||||
|
||||
|
||||
#define CALLIF(rtn) rtn && rtn
|
||||
|
||||
static void chp_value(parseContext *parser, int result)
|
||||
static void chf_value(parseContext *parser, int result)
|
||||
{
|
||||
chFilter *filter = parser->filter;
|
||||
|
||||
@@ -40,7 +50,7 @@ static void chp_value(parseContext *parser, int result)
|
||||
}
|
||||
|
||||
|
||||
static int chp_null(void * ctx)
|
||||
static int chf_null(void * ctx)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -48,11 +58,11 @@ static int chp_null(void * ctx)
|
||||
|
||||
assert(filter);
|
||||
result = CALLIF(filter->fif->parse_null) (filter );
|
||||
chp_value(parser, result);
|
||||
chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int chp_boolean(void * ctx, int boolVal)
|
||||
static int chf_boolean(void * ctx, int boolVal)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -60,11 +70,11 @@ static int chp_boolean(void * ctx, int boolVal)
|
||||
|
||||
assert(filter);
|
||||
result = CALLIF(filter->fif->parse_boolean) (filter , boolVal);
|
||||
chp_value(parser, result);
|
||||
chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int chp_integer(void * ctx, long integerVal)
|
||||
static int chf_integer(void * ctx, long integerVal)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -72,11 +82,11 @@ static int chp_integer(void * ctx, long integerVal)
|
||||
|
||||
assert(filter);
|
||||
result = CALLIF(filter->fif->parse_integer) (filter , integerVal);
|
||||
chp_value(parser, result);
|
||||
chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int chp_double(void * ctx, double doubleVal)
|
||||
static int chf_double(void * ctx, double doubleVal)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -84,11 +94,11 @@ static int chp_double(void * ctx, double doubleVal)
|
||||
|
||||
assert(filter);
|
||||
result = CALLIF(filter->fif->parse_double) (filter , doubleVal);
|
||||
chp_value(parser, result);
|
||||
chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int chp_string(void * ctx, const unsigned char * stringVal,
|
||||
static int chf_string(void * ctx, const unsigned char * stringVal,
|
||||
unsigned int stringLen)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
@@ -97,11 +107,11 @@ static int chp_string(void * ctx, const unsigned char * stringVal,
|
||||
|
||||
assert(filter);
|
||||
result = CALLIF(filter->fif->parse_string) (filter , (const char *) stringVal, stringLen);
|
||||
chp_value(parser, result);
|
||||
chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int chp_start_map(void * ctx)
|
||||
static int chf_start_map(void * ctx)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -115,7 +125,7 @@ static int chp_start_map(void * ctx)
|
||||
return CALLIF(filter->fif->parse_start_map) (filter );
|
||||
}
|
||||
|
||||
static int chp_map_key(void * ctx, const unsigned char * key,
|
||||
static int chf_map_key(void * ctx, const unsigned char * key,
|
||||
unsigned int stringLen)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
@@ -148,7 +158,7 @@ static int chp_map_key(void * ctx, const unsigned char * key,
|
||||
return result;
|
||||
}
|
||||
|
||||
static int chp_end_map(void * ctx)
|
||||
static int chf_end_map(void * ctx)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -156,14 +166,14 @@ static int chp_end_map(void * ctx)
|
||||
if (filter) {
|
||||
int result = CALLIF(filter->fif->parse_end_map) (filter );
|
||||
|
||||
if (--parser->depth == 0) chp_value(parser, result);
|
||||
if (--parser->depth == 0) chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
assert(parser->depth == 0);
|
||||
return parse_continue; /* Final closing '}' */
|
||||
}
|
||||
|
||||
static int chp_start_array(void * ctx)
|
||||
static int chf_start_array(void * ctx)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -173,7 +183,7 @@ static int chp_start_array(void * ctx)
|
||||
return CALLIF(filter->fif->parse_start_array) (filter );
|
||||
}
|
||||
|
||||
static int chp_end_array(void * ctx)
|
||||
static int chf_end_array(void * ctx)
|
||||
{
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
chFilter *filter = parser->filter;
|
||||
@@ -181,66 +191,250 @@ static int chp_end_array(void * ctx)
|
||||
|
||||
assert(filter);
|
||||
result = CALLIF(filter->fif->parse_end_array) (filter );
|
||||
if (--parser->depth == 0) chp_value(parser, result);
|
||||
if (--parser->depth == 0) chf_value(parser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const yajl_callbacks chp_callbacks =
|
||||
{ chp_null, chp_boolean, chp_integer, chp_double, NULL, chp_string,
|
||||
chp_start_map, chp_map_key, chp_end_map, chp_start_array, chp_end_array };
|
||||
static const yajl_callbacks chf_callbacks =
|
||||
{ chf_null, chf_boolean, chf_integer, chf_double, NULL, chf_string,
|
||||
chf_start_map, chf_map_key, chf_end_map, chf_start_array, chf_end_array };
|
||||
|
||||
static const yajl_parser_config chp_config =
|
||||
static const yajl_parser_config chf_config =
|
||||
{ 0, 1 }; /* allowComments = NO , checkUTF8 = YES */
|
||||
|
||||
|
||||
void dbChannelInit(dbChannel *chan)
|
||||
{
|
||||
ellInit(&chan->filters);
|
||||
}
|
||||
// Move ellInit into ChannelFind, rename it again?
|
||||
long dbChannelFind(dbChannel *chan, const char *name)
|
||||
static long chf_parse(dbChannel *chan, const char *json)
|
||||
{
|
||||
parseContext parser =
|
||||
{ chan, NULL, 0};
|
||||
yajl_handle yh = yajl_alloc(&chp_callbacks, &chp_config, NULL, &parser);
|
||||
size_t len = strlen(name);
|
||||
yajl_status status;
|
||||
yajl_handle yh = yajl_alloc(&chf_callbacks, &chf_config, NULL, &parser);
|
||||
size_t jlen = strlen(json);
|
||||
yajl_status ys;
|
||||
long status;
|
||||
|
||||
status = yajl_parse(yh, (const unsigned char *) name, len);
|
||||
if (status != yajl_status_ok && parser.filter) {
|
||||
if (!yh) return S_db_noMemory;
|
||||
|
||||
ys = yajl_parse(yh, (const unsigned char *) json, jlen);
|
||||
if (ys == yajl_status_insufficient_data)
|
||||
ys = yajl_parse_complete(yh);
|
||||
|
||||
switch(ys) {
|
||||
case yajl_status_ok:
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case yajl_status_error: {
|
||||
unsigned char *err;
|
||||
|
||||
err = yajl_get_error(yh, 1, (const unsigned char *) json, jlen);
|
||||
printf("dbChannelFind: %s\n", err);
|
||||
yajl_free_error(yh, err);
|
||||
} /* fall through */
|
||||
default:
|
||||
status = S_db_notFound;
|
||||
}
|
||||
|
||||
if (parser.filter) {
|
||||
assert(status);
|
||||
parser.filter->fif->parse_abort(parser.filter);
|
||||
free(parser.filter);
|
||||
}
|
||||
yajl_free(yh);
|
||||
return status == yajl_status_ok;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Stolen from dbAccess.c: */
|
||||
static short mapDBFToDBR[DBF_NTYPES] = {
|
||||
/* DBF_STRING => */ DBR_STRING,
|
||||
/* DBF_CHAR => */ DBR_CHAR,
|
||||
/* DBF_UCHAR => */ DBR_UCHAR,
|
||||
/* DBF_SHORT => */ DBR_SHORT,
|
||||
/* DBF_USHORT => */ DBR_USHORT,
|
||||
/* DBF_LONG => */ DBR_LONG,
|
||||
/* DBF_ULONG => */ DBR_ULONG,
|
||||
/* DBF_FLOAT => */ DBR_FLOAT,
|
||||
/* DBF_DOUBLE => */ DBR_DOUBLE,
|
||||
/* DBF_ENUM, => */ DBR_ENUM,
|
||||
/* DBF_MENU, => */ DBR_ENUM,
|
||||
/* DBF_DEVICE => */ DBR_ENUM,
|
||||
/* DBF_INLINK => */ DBR_STRING,
|
||||
/* DBF_OUTLINK => */ DBR_STRING,
|
||||
/* DBF_FWDLINK => */ DBR_STRING,
|
||||
/* DBF_NOACCESS => */ DBR_NOACCESS
|
||||
};
|
||||
|
||||
long dbChannelFind(dbChannel *chan, const char *pname)
|
||||
{
|
||||
DBADDR *paddr;
|
||||
DBENTRY dbEntry;
|
||||
dbFldDes *pflddes;
|
||||
long status;
|
||||
short dbfType;
|
||||
|
||||
if (!chan || !pname || !*pname || !pdbbase)
|
||||
return S_db_notFound;
|
||||
|
||||
if (chan->magic == DBCHANNEL_MAGIC) {
|
||||
chFilter *filter;
|
||||
|
||||
while ((filter = (chFilter *) ellGet(&chan->filters))) {
|
||||
filter->fif->channel_close(filter);
|
||||
free(filter);
|
||||
}
|
||||
} else {
|
||||
ellInit(&chan->filters);
|
||||
chan->magic = DBCHANNEL_MAGIC;
|
||||
}
|
||||
|
||||
dbInitEntry(pdbbase, &dbEntry);
|
||||
status = dbFindRecordPart(&dbEntry, &pname);
|
||||
if (status) goto finish;
|
||||
|
||||
if (*pname == '.') ++pname;
|
||||
status = dbFindFieldPart(&dbEntry, &pname);
|
||||
if (status == S_dbLib_fieldNotFound)
|
||||
status = dbGetAttributePart(&dbEntry, &pname);
|
||||
if (status) goto finish;
|
||||
|
||||
paddr = &chan->addr;
|
||||
pflddes = dbEntry.pflddes;
|
||||
dbfType = pflddes->field_type;
|
||||
|
||||
paddr->precord = dbEntry.precnode->precord;
|
||||
paddr->pfield = dbEntry.pfield;
|
||||
paddr->pfldDes = pflddes;
|
||||
paddr->no_elements = 1;
|
||||
paddr->field_type = dbfType;
|
||||
paddr->field_size = pflddes->size;
|
||||
paddr->special = pflddes->special;
|
||||
paddr->dbr_field_type = mapDBFToDBR[dbfType];
|
||||
|
||||
/* Handle field modifiers */
|
||||
while (*pname) {
|
||||
switch (*pname) {
|
||||
case '$':
|
||||
/* Some field types can be accessed as char arrays */
|
||||
if (dbfType == DBF_STRING) {
|
||||
paddr->no_elements = pflddes->size;
|
||||
paddr->field_type = DBF_CHAR;
|
||||
paddr->field_size = 1;
|
||||
paddr->dbr_field_type = DBR_CHAR;
|
||||
} else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
|
||||
/* Clients see a char array, but keep original dbfType */
|
||||
paddr->no_elements = PVNAME_STRINGSZ + 12;
|
||||
paddr->field_size = 1;
|
||||
paddr->dbr_field_type = DBR_CHAR;
|
||||
} else {
|
||||
status = S_dbLib_fieldNotFound;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case '{':
|
||||
status = chf_parse(chan, pname);
|
||||
goto finish;
|
||||
default:
|
||||
status = S_dbLib_fieldNotFound;
|
||||
goto finish;
|
||||
}
|
||||
pname++;
|
||||
}
|
||||
|
||||
finish:
|
||||
dbFinishEntry(&dbEntry);
|
||||
return status;
|
||||
}
|
||||
|
||||
long dbChannelOpen(dbChannel *chan)
|
||||
{
|
||||
return S_db_notFound;
|
||||
DBADDR *paddr;
|
||||
chFilter *filter;
|
||||
long status = 0;
|
||||
|
||||
if (chan->magic != DBCHANNEL_MAGIC) return S_db_notInit;
|
||||
|
||||
paddr = &chan->addr;
|
||||
if (paddr->special == SPC_DBADDR) {
|
||||
struct rset *prset = dbGetRset(paddr);
|
||||
|
||||
/* Let record type modify the dbAddr */
|
||||
if (prset && prset->cvt_dbaddr) {
|
||||
status = prset->cvt_dbaddr(paddr);
|
||||
if (status) return status;
|
||||
}
|
||||
}
|
||||
|
||||
filter = (chFilter *) ellFirst(&chan->filters);
|
||||
while (filter) {
|
||||
status = filter->fif->channel_open(filter);
|
||||
if (status) break;
|
||||
filter = (chFilter *) ellNext(&filter->node);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void dbChannelReport(dbChannel *chan, int level)
|
||||
{
|
||||
chFilter *filter;
|
||||
|
||||
if (chan->magic != DBCHANNEL_MAGIC) return;
|
||||
|
||||
filter = (chFilter *) ellFirst(&chan->filters);
|
||||
while (filter) {
|
||||
filter->fif->channel_report(filter, level);
|
||||
filter = (chFilter *) ellNext(&filter->node);
|
||||
}
|
||||
}
|
||||
|
||||
long dbChannelClose(dbChannel *chan)
|
||||
{
|
||||
chFilter *filter;
|
||||
|
||||
if (chan->magic != DBCHANNEL_MAGIC) return S_db_notInit;
|
||||
|
||||
while ((filter = (chFilter *) ellGet(&chan->filters))) {
|
||||
filter->fif->channel_close(filter);
|
||||
free(filter);
|
||||
}
|
||||
chan->magic = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Do these belong in a different file? */
|
||||
|
||||
const chFilterIf * filt = NULL;
|
||||
const char *fname = NULL;
|
||||
|
||||
void dbRegisterFilter(const char *key, const chFilterIf *fif)
|
||||
void dbRegisterFilter(const char *name, const chFilterIf *fif)
|
||||
{
|
||||
/* FIXME: Add filter to a list and hash in pdbbase */
|
||||
filt = fif;
|
||||
fname = key;
|
||||
fif->plugin_init();
|
||||
GPHENTRY *pgph;
|
||||
filterPlugin *pfilt;
|
||||
|
||||
if (!pdbbase) {
|
||||
printf("dbRegisterFilter: pdbbase not set!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pgph = gphFind(pdbbase->pgpHash, name, &pdbbase->filterList);
|
||||
if (pgph) return;
|
||||
|
||||
pfilt = dbCalloc(1, sizeof(filterPlugin));
|
||||
pfilt->name = strdup(name);
|
||||
pfilt->fif = fif;
|
||||
|
||||
ellAdd(&pdbbase->filterList, &pfilt->node);
|
||||
pgph = gphAdd(pdbbase->pgpHash, pfilt->name, &pdbbase->filterList);
|
||||
if (!pgph) {
|
||||
free((void *)pfilt->name);
|
||||
free(pfilt);
|
||||
printf("dbRegisterFilter: gphAdd failed\n");
|
||||
return;
|
||||
}
|
||||
pgph->userPvt = pfilt;
|
||||
}
|
||||
|
||||
const chFilterIf * dbFindFilter(const char *key, size_t len)
|
||||
const chFilterIf * dbFindFilter(const char *name, size_t len)
|
||||
{
|
||||
/* FIXME: gpHash lookup */
|
||||
if (strncmp(fname, key, len) == 0)
|
||||
return filt;
|
||||
return NULL;
|
||||
GPHENTRY *pgph = gphFindParse(pdbbase->pgpHash, name, len, &pdbbase->filterList);
|
||||
filterPlugin *pfilt;
|
||||
|
||||
if (!pgph) return NULL;
|
||||
pfilt = (filterPlugin *)pgph->userPvt;
|
||||
return pfilt->fif;
|
||||
}
|
||||
|
||||
+13
-8
@@ -11,28 +11,33 @@
|
||||
#include "dbDefs.h"
|
||||
#include "dbAddr.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsTypes.h"
|
||||
#include "errMdef.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
enum {parse_stop, parse_continue};
|
||||
|
||||
#ifdef __cplusplus
|
||||
// extern "C" {
|
||||
#endif
|
||||
|
||||
#define DBCHANNEL_MAGIC 0xdbc4a9e1
|
||||
|
||||
#define S_db_notInit (M_dbAccess|21) /*dbChannel not initialized*/
|
||||
|
||||
|
||||
/* A dbChannel points to a record field, and can have multiple filters */
|
||||
typedef struct dbChannel {
|
||||
epicsUInt32 magic;
|
||||
dbAddr addr;
|
||||
ELLLIST filters;
|
||||
} dbChannel;
|
||||
|
||||
typedef struct chFilter chFilter;
|
||||
|
||||
/* Return values from chFilterIf->parse_* routines: */
|
||||
enum {parse_stop, parse_continue};
|
||||
|
||||
/* These routines must be implemented by each filter plug-in */
|
||||
typedef struct chFilterIf {
|
||||
/* Plug-in management */
|
||||
void (* plugin_init)(void);
|
||||
void (* plugin_exit)(void);
|
||||
|
||||
/* Parsing event handlers */
|
||||
int (* parse_start)(chFilter *filter);
|
||||
void (* parse_abort)(chFilter *filter);
|
||||
@@ -68,9 +73,9 @@ struct chFilter {
|
||||
void *puser;
|
||||
};
|
||||
|
||||
epicsShareFunc void dbChannelInit(dbChannel *chan);
|
||||
epicsShareFunc long dbChannelFind(dbChannel *chan, const char *name);
|
||||
epicsShareFunc long dbChannelFind(dbChannel *chan, const char *pname);
|
||||
epicsShareFunc long dbChannelOpen(dbChannel *chan);
|
||||
epicsShareFunc void dbChannelReport(dbChannel *chan, int level);
|
||||
epicsShareFunc long dbChannelClose(dbChannel *chan);
|
||||
|
||||
epicsShareFunc void dbRegisterFilter(const char *key, const chFilterIf *fif);
|
||||
|
||||
@@ -6,165 +6,178 @@
|
||||
\*************************************************************************/
|
||||
|
||||
#include "dbChannel.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "epicsUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
/* Expected call bit definitions */
|
||||
#define e_init 0x00000001
|
||||
#define e_exit 0x00000002
|
||||
#define e_start 0x00000004
|
||||
#define e_abort 0x00000008
|
||||
#define e_end 0x00000010
|
||||
#define e_null 0x00000020
|
||||
#define e_boolean 0x00000040
|
||||
#define e_integer 0x00000080
|
||||
#define e_double 0x00000100
|
||||
#define e_string 0x00000200
|
||||
#define e_start_map 0x00000400
|
||||
#define e_map_key 0x00000800
|
||||
#define e_end_map 0x00001000
|
||||
#define e_start_array 0x00002000
|
||||
#define e_end_array 0x00004000
|
||||
#define e_open 0x00008000
|
||||
#define e_report 0x00010000
|
||||
#define e_close 0x00020000
|
||||
#define e_start 0x00000001
|
||||
#define e_abort 0x00000002
|
||||
#define e_end 0x00000004
|
||||
#define e_null 0x00000008
|
||||
#define e_boolean 0x00000010
|
||||
#define e_integer 0x00000020
|
||||
#define e_double 0x00000040
|
||||
#define e_string 0x00000080
|
||||
#define e_start_map 0x00000100
|
||||
#define e_map_key 0x00000200
|
||||
#define e_end_map 0x00000400
|
||||
#define e_start_array 0x00000800
|
||||
#define e_end_array 0x00001000
|
||||
#define e_open 0x00002000
|
||||
#define e_report 0x00004000
|
||||
#define e_close 0x00008000
|
||||
|
||||
unsigned int e;
|
||||
|
||||
|
||||
void f_init(void)
|
||||
{
|
||||
testOk(e & e_init, "plugin_init expected");
|
||||
}
|
||||
void f_exit(void)
|
||||
{
|
||||
testOk(e & e_exit, "plugin_exit expected");
|
||||
}
|
||||
|
||||
int p_start(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_start, "parse_start expected");
|
||||
testOk(e & e_start, "parse_start called");
|
||||
return parse_continue;
|
||||
}
|
||||
|
||||
void p_abort(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_abort, "parse_abort expected");
|
||||
testOk(e & e_abort, "parse_abort called");
|
||||
}
|
||||
int p_end(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_end, "parse_end expected");
|
||||
testOk(e & e_end, "parse_end called");
|
||||
return parse_continue;
|
||||
}
|
||||
|
||||
int p_null(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_null, "parse_null expected");
|
||||
testOk(e & e_null, "parse_null called");
|
||||
return parse_continue;
|
||||
}
|
||||
int p_boolean(chFilter *filter, int boolVal)
|
||||
{
|
||||
testOk(e & e_boolean, "parse_boolean expected, val = %d", boolVal);
|
||||
testOk(e & e_boolean, "parse_boolean called, val = %d", boolVal);
|
||||
return parse_continue;
|
||||
}
|
||||
int p_integer(chFilter *filter, long integerVal)
|
||||
{
|
||||
testOk(e & e_integer, "parse_integer expected, val = %ld", integerVal);
|
||||
testOk(e & e_integer, "parse_integer called, val = %ld", integerVal);
|
||||
return parse_continue;
|
||||
}
|
||||
int p_double(chFilter *filter, double doubleVal)
|
||||
{
|
||||
testOk(e & e_double, "parse_double expected, val = %g", doubleVal);
|
||||
testOk(e & e_double, "parse_double called, val = %g", doubleVal);
|
||||
return parse_continue;
|
||||
}
|
||||
int p_string(chFilter *filter, const char *stringVal, size_t stringLen)
|
||||
{
|
||||
testOk(e & e_string, "parse_string expected, val = '%.*s'", stringLen, stringVal);
|
||||
testOk(e & e_string, "parse_string called, val = '%.*s'", stringLen,
|
||||
stringVal);
|
||||
return parse_continue;
|
||||
}
|
||||
|
||||
int p_start_map(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_start_map, "parse_start_map expected");
|
||||
testOk(e & e_start_map, "parse_start_map called");
|
||||
return parse_continue;
|
||||
}
|
||||
int p_map_key(chFilter *filter, const char *key, size_t stringLen)
|
||||
{
|
||||
testOk(e & e_map_key, "parse_map_key expected, key = '%.*s'", stringLen, key);
|
||||
testOk(e & e_map_key, "parse_map_key called, key = '%.*s'", stringLen, key);
|
||||
return parse_continue;
|
||||
}
|
||||
int p_end_map(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_end_map, "parse_end_map expected");
|
||||
testOk(e & e_end_map, "parse_end_map called");
|
||||
return parse_continue;
|
||||
}
|
||||
|
||||
int p_start_array(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_start_array, "parse_start_array expected");
|
||||
testOk(e & e_start_array, "parse_start_array called");
|
||||
return parse_continue;
|
||||
}
|
||||
int p_end_array(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_end_array, "parse_end_array expected");
|
||||
testOk(e & e_end_array, "parse_end_array called");
|
||||
return parse_continue;
|
||||
}
|
||||
|
||||
long c_open(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_open, "channel_open expected");
|
||||
testOk(e & e_open, "channel_open called");
|
||||
return 0;
|
||||
}
|
||||
void c_report(chFilter *filter, int level)
|
||||
{
|
||||
testOk(e & e_report, "channel_report expected, level = %d", level);
|
||||
testOk(e & e_report, "channel_report called, level = %d", level);
|
||||
}
|
||||
void c_close(chFilter *filter)
|
||||
{
|
||||
testOk(e & e_close, "channel_close expected");
|
||||
testOk(e & e_close, "channel_close called");
|
||||
}
|
||||
|
||||
chFilterIf testIf =
|
||||
{ f_init, f_exit, p_start, p_abort, p_end, p_null, p_boolean,
|
||||
p_integer, p_double, p_string, p_start_map, p_map_key, p_end_map,
|
||||
p_start_array, p_end_array, c_open, c_report, c_close };
|
||||
chFilterIf anyIf =
|
||||
{ p_start, p_abort, p_end, p_null, p_boolean, p_integer, p_double,
|
||||
p_string, p_start_map, p_map_key, p_end_map, p_start_array, p_end_array,
|
||||
c_open, c_report, c_close };
|
||||
|
||||
chFilterIf scalarIf =
|
||||
{ f_init, f_exit, p_start, p_abort, p_end, p_null, p_boolean,
|
||||
p_integer, p_double, p_string, NULL, NULL, NULL, NULL, NULL, c_open,
|
||||
c_report, c_close };
|
||||
{ p_start, p_abort, p_end, p_null, p_boolean, p_integer, p_double,
|
||||
p_string, NULL, NULL, NULL, NULL, NULL, c_open,
|
||||
c_report, c_close};
|
||||
|
||||
MAIN(dbChannelTest)
|
||||
{
|
||||
dbChannel ch;
|
||||
|
||||
testPlan(33);
|
||||
dbChannelInit(&ch);
|
||||
testPlan(45);
|
||||
|
||||
testOk1(!dbReadDatabase(&pdbbase, "dbChannelTest.dbx", ".:..", NULL));
|
||||
testOk(!!pdbbase, "pdbbase was set");
|
||||
|
||||
e = 0;
|
||||
testOk1(dbChannelFind(&ch, "{}"));
|
||||
testOk1(!dbChannelFind(&ch, "x.NAME$"));
|
||||
testOk1(ch.addr.no_elements > 1);
|
||||
|
||||
e = e_init;
|
||||
dbRegisterFilter("test", &testIf);
|
||||
testOk1(!dbChannelFind(&ch, "x.{}"));
|
||||
|
||||
dbRegisterFilter("any", &anyIf);
|
||||
|
||||
e = e_start | e_null | e_end;
|
||||
testOk1(dbChannelFind(&ch, "{\"test\":null}"));
|
||||
testOk1(!dbChannelFind(&ch, "x.{\"any\":null}"));
|
||||
e = e_close;
|
||||
testOk1(!dbChannelClose(&ch));
|
||||
|
||||
e = e_start | e_start_array | e_boolean | e_integer | e_end_array | e_end;
|
||||
testOk1(dbChannelFind(&ch, "{\"test\":[true,1]}"));
|
||||
|
||||
e = e_start | e_start_map | e_map_key | e_double | e_string | e_end_map | e_end;
|
||||
testOk1(dbChannelFind(&ch, "{\"test\":{\"a\":2.7183,\"b\":\"c\"}}"));
|
||||
|
||||
e = e_init;
|
||||
dbRegisterFilter("scalar", &scalarIf);
|
||||
|
||||
e = e_start | e_null | e_end;
|
||||
testOk1(dbChannelFind(&ch, "{\"scalar\":null}"));
|
||||
testOk1(!dbChannelFind(&ch, "x.{\"scalar\":null}"));
|
||||
|
||||
e = e_report;
|
||||
dbChannelReport(&ch, 0);
|
||||
|
||||
e = e_close;
|
||||
testOk1(!dbChannelClose(&ch));
|
||||
|
||||
e = e_start | e_start_array | e_boolean | e_integer | e_end_array | e_end;
|
||||
testOk1(!dbChannelFind(&ch, "x.{\"any\":[true,1]}"));
|
||||
e = e_close;
|
||||
testOk1(!dbChannelClose(&ch));
|
||||
|
||||
e = e_start | e_start_map | e_map_key | e_double | e_string | e_end_map
|
||||
| e_end;
|
||||
testOk1(!dbChannelFind(&ch, "x.{\"any\":{\"a\":2.7183,\"b\":\"c\"}}"));
|
||||
|
||||
e = e_close | e_start | e_abort;
|
||||
testOk1(dbChannelFind(&ch, "x.{\"scalar\":[null]}"));
|
||||
e = 0;
|
||||
testOk1(!dbChannelClose(&ch));
|
||||
|
||||
e = e_start | e_abort;
|
||||
testOk1(!dbChannelFind(&ch, "{\"scalar\":[null]}"));
|
||||
testOk1(!dbChannelFind(&ch, "{\"scalar\":{}}"));
|
||||
testOk1(dbChannelFind(&ch, "x.{\"scalar\":{}}"));
|
||||
e = 0;
|
||||
testOk1(!dbChannelClose(&ch));
|
||||
|
||||
dbFreeBase(pdbbase);
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# This is a combined minimal DBD and DB file
|
||||
|
||||
recordtype(x) {
|
||||
field(NAME, DBF_STRING) {
|
||||
prompt("Record Name")
|
||||
special(SPC_NOMOD)
|
||||
size(61)
|
||||
}
|
||||
field(VAL, DBF_LONG) {
|
||||
prompt("Value")
|
||||
}
|
||||
}
|
||||
record(x, x) {}
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* $Revision-Id$
|
||||
*
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "dbFldTypes.h"
|
||||
#include "ellLib.h"
|
||||
#include "dbDefs.h"
|
||||
|
||||
|
||||
typedef struct dbMenu {
|
||||
ELLNODE node;
|
||||
char *name;
|
||||
@@ -67,7 +67,7 @@ typedef struct brkTable { /* breakpoint table */
|
||||
long number; /*number of brkInt in this table*/
|
||||
struct brkInt *paBrkInt; /* ptr to array of brkInts */
|
||||
}brkTable;
|
||||
|
||||
|
||||
typedef struct dbFldDes{ /* field description */
|
||||
char *prompt; /*Prompt string for DCT*/
|
||||
char *name; /*Field name*/
|
||||
@@ -128,7 +128,7 @@ typedef struct dbVariableDef {
|
||||
ELLNODE node;
|
||||
char *name;
|
||||
char *type;
|
||||
|
||||
|
||||
}dbVariableDef;
|
||||
|
||||
typedef struct dbRecordType {
|
||||
@@ -164,6 +164,7 @@ typedef struct dbBase {
|
||||
ELLLIST functionList;
|
||||
ELLLIST variableList;
|
||||
ELLLIST bptList;
|
||||
ELLLIST filterList;
|
||||
void *pathPvt;
|
||||
struct dbPvd *ppvd;
|
||||
struct gphPvt *pgpHash;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* $Revision-Id$ */
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "guigroup.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbStaticPvt.h"
|
||||
|
||||
|
||||
int dbStaticDebug = 0;
|
||||
static char *pNullString = "";
|
||||
#define messagesize 100
|
||||
@@ -191,7 +191,7 @@ sizeof(promptINST_IO)/sizeof(char *),
|
||||
sizeof(promptBBGPIB_IO)/sizeof(char *),
|
||||
sizeof(promptRF_IO)/sizeof(char *),
|
||||
sizeof(promptVXI_IO)/sizeof(char *)};
|
||||
|
||||
|
||||
/*forward references for private routines*/
|
||||
static FILE *openOutstream(const char *filename);
|
||||
static void finishOutstream(FILE *stream);
|
||||
@@ -203,7 +203,7 @@ static void zeroDbentry(DBENTRY *pdbentry);
|
||||
static char *getpMessage(DBENTRY *pdbentry);
|
||||
static long putPvLink(DBENTRY *pdbentry,short pvlMask,const char *pvname);
|
||||
static long epicsShareAPI dbAddOnePath (DBBASE *pdbbase, const char *path, unsigned length);
|
||||
|
||||
|
||||
/* internal routines*/
|
||||
static FILE *openOutstream(const char *filename)
|
||||
{
|
||||
@@ -347,7 +347,7 @@ void dbFreeLinkContents(struct link *plink)
|
||||
if(plink->text) free(plink->text);
|
||||
memset((char *)plink,0,sizeof(struct link));
|
||||
}
|
||||
|
||||
|
||||
void dbFreePath(DBBASE *pdbbase)
|
||||
{
|
||||
ELLLIST *ppathList;
|
||||
@@ -366,7 +366,7 @@ void dbFreePath(DBBASE *pdbbase)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long mapLINKTtoFORMT(DBLINK *plink,dbFldDes *pflddes,int *ind)
|
||||
{
|
||||
switch(plink->type) {
|
||||
@@ -407,7 +407,7 @@ static long mapLINKTtoFORMT(DBLINK *plink,dbFldDes *pflddes,int *ind)
|
||||
}
|
||||
return(S_dbLib_badLink);
|
||||
}
|
||||
|
||||
|
||||
static void entryErrMessage(DBENTRY *pdbentry,long status,char *mess)
|
||||
{
|
||||
char message[200];
|
||||
@@ -439,7 +439,7 @@ static void entryErrMessage(DBENTRY *pdbentry,long status,char *mess)
|
||||
strcat(pmessage,mess);
|
||||
errMessage(status,pmessage);
|
||||
}
|
||||
|
||||
|
||||
static void zeroDbentry(DBENTRY *pdbentry)
|
||||
{
|
||||
/*NOTE that pdbbase, message, and formpvt MUST NOT be set to NULL*/
|
||||
@@ -466,7 +466,7 @@ static long putPvLink(DBENTRY *pdbentry,short pvlMask,const char *pvname)
|
||||
dbFldDes *pflddes;
|
||||
DBLINK *plink;
|
||||
char *pname;
|
||||
|
||||
|
||||
dbGetFieldAddress(pdbentry);
|
||||
pflddes = pdbentry->pflddes;
|
||||
if(!pflddes) return(-1);
|
||||
@@ -489,7 +489,7 @@ static long putPvLink(DBENTRY *pdbentry,short pvlMask,const char *pvname)
|
||||
}
|
||||
return(S_dbLib_badLink);
|
||||
}
|
||||
|
||||
|
||||
/*Public only for dbStaticNoRun*/
|
||||
dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
|
||||
{
|
||||
@@ -526,7 +526,7 @@ dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
|
||||
pflddes->ftPvt = pdbDeviceMenu;
|
||||
return(pdbDeviceMenu);
|
||||
}
|
||||
|
||||
|
||||
/* Beginning of Public Routines */
|
||||
|
||||
#define INC_SIZE 256
|
||||
@@ -555,7 +555,7 @@ void epicsShareAPI dbCatString(char **string,int *stringLength,char *src,char *s
|
||||
strcat(*string,src);
|
||||
*stringLength += strlen(src);
|
||||
}
|
||||
|
||||
|
||||
dbBase * epicsShareAPI dbAllocBase(void)
|
||||
{
|
||||
dbBase *pdbbase;
|
||||
@@ -568,6 +568,7 @@ dbBase * epicsShareAPI dbAllocBase(void)
|
||||
ellInit(&pdbbase->functionList);
|
||||
ellInit(&pdbbase->variableList);
|
||||
ellInit(&pdbbase->bptList);
|
||||
ellInit(&pdbbase->filterList);
|
||||
gphInitPvt(&pdbbase->pgpHash,256);
|
||||
dbPvdInitPvt(pdbbase);
|
||||
return (pdbbase);
|
||||
@@ -595,7 +596,7 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
|
||||
brkTable *pbrkTableNext;
|
||||
int i;
|
||||
DBENTRY dbentry;
|
||||
|
||||
|
||||
|
||||
dbInitEntry(pdbbase,&dbentry);
|
||||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
@@ -620,7 +621,7 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
|
||||
free((void *)pdbFldDes->initial);
|
||||
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
|
||||
dbDeviceMenu *pdbDeviceMenu;
|
||||
|
||||
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
@@ -729,12 +730,12 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
|
||||
free((void *)pdbbase);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DBENTRY * epicsShareAPI dbAllocEntry(dbBase *pdbbase)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
|
||||
pdbentry = dbmfMalloc(sizeof(DBENTRY));
|
||||
pdbentry = dbmfMalloc(sizeof(DBENTRY));
|
||||
memset(pdbentry,'\0',sizeof(DBENTRY));
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
return(pdbentry);
|
||||
@@ -780,7 +781,7 @@ void epicsShareAPI dbCopyEntryContents(DBENTRY *pfrom,DBENTRY *pto)
|
||||
pto->formpvt = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long epicsShareAPI dbPath(DBBASE *pdbbase,const char *path)
|
||||
{
|
||||
if(!pdbbase) return(-1);
|
||||
@@ -796,7 +797,7 @@ long epicsShareAPI dbAddPath(DBBASE *pdbbase,const char *path)
|
||||
const char *plast;
|
||||
unsigned expectingPath;
|
||||
unsigned sawMissingPath;
|
||||
|
||||
|
||||
if(!pdbbase) return(-1);
|
||||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||||
if(!ppathList) {
|
||||
@@ -865,7 +866,7 @@ static long epicsShareAPI dbAddOnePath (DBBASE *pdbbase, const char *path, unsig
|
||||
{
|
||||
ELLLIST *ppathList;
|
||||
dbPathNode *pdbPathNode;
|
||||
|
||||
|
||||
if(!pdbbase) return(-1);
|
||||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||||
|
||||
@@ -877,7 +878,7 @@ static long epicsShareAPI dbAddOnePath (DBBASE *pdbbase, const char *path, unsig
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long epicsShareAPI dbWriteRecord(DBBASE *ppdbbase,const char *filename,
|
||||
const char *precordTypename,int level)
|
||||
{
|
||||
@@ -974,7 +975,7 @@ long epicsShareAPI dbWriteRecordFP(
|
||||
dbFinishEntry(pdbentry);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbWriteMenu(
|
||||
DBBASE *ppdbbase,const char *filename,const char *menuName)
|
||||
{
|
||||
@@ -1017,7 +1018,7 @@ long epicsShareAPI dbWriteMenuFP(DBBASE *pdbbase,FILE *fp,const char *menuName)
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbWriteRecordType(
|
||||
DBBASE *pdbbase,const char *filename,const char *recordTypeName)
|
||||
{
|
||||
@@ -1114,7 +1115,7 @@ long epicsShareAPI dbWriteRecordTypeFP(
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbWriteDevice(DBBASE *pdbbase,const char *filename)
|
||||
{
|
||||
FILE *stream;
|
||||
@@ -1156,7 +1157,7 @@ long epicsShareAPI dbWriteDeviceFP(DBBASE *pdbbase,FILE *fp)
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbWriteDriver(DBBASE *pdbbase,const char *filename)
|
||||
{
|
||||
FILE *stream;
|
||||
@@ -1227,7 +1228,7 @@ long epicsShareAPI dbWriteVariableFP(DBBASE *pdbbase,FILE *fp)
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbWriteBreaktable(DBBASE *pdbbase,const char *filename)
|
||||
{
|
||||
FILE *stream;
|
||||
@@ -1262,7 +1263,7 @@ long epicsShareAPI dbWriteBreaktableFP(DBBASE *pdbbase,FILE *fp)
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbFindRecordType(DBENTRY *pdbentry,const char *recordType)
|
||||
{
|
||||
dbBase *pdbbase = pdbentry->pdbbase;
|
||||
@@ -1306,7 +1307,7 @@ int epicsShareAPI dbGetNRecordTypes(DBENTRY *pdbentry)
|
||||
{
|
||||
return(ellCount(&pdbentry->pdbbase->recordTypeList));
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbPutRecordAttribute(
|
||||
DBENTRY *pdbentry, const char *name, const char*value)
|
||||
{
|
||||
@@ -1382,7 +1383,7 @@ long epicsShareAPI dbGetRecordAttribute(DBENTRY *pdbentry, const char *pname)
|
||||
{
|
||||
return dbGetAttributePart(pdbentry, &pname);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbFirstField(DBENTRY *pdbentry,int dctonly)
|
||||
{
|
||||
|
||||
@@ -1426,7 +1427,7 @@ long epicsShareAPI dbNextField(DBENTRY *pdbentry,int dctonly)
|
||||
indfield++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int epicsShareAPI dbGetFieldType(DBENTRY *pdbentry)
|
||||
{
|
||||
dbFldDes *pflddes = pdbentry->pflddes;
|
||||
@@ -1450,7 +1451,7 @@ int epicsShareAPI dbGetNFields(DBENTRY *pdbentry,int dctonly)
|
||||
n = 0;
|
||||
for(indfield=0; indfield<precordType->no_fields; indfield++) {
|
||||
pflddes = precordType->papFldDes[indfield];
|
||||
if(dctonly && (pflddes->field_type==DBF_DEVICE)
|
||||
if(dctonly && (pflddes->field_type==DBF_DEVICE)
|
||||
&& (ellCount(&precordType->devList)==0) ) continue;
|
||||
if(!dctonly || pflddes->promptgroup) n++;
|
||||
}
|
||||
@@ -1488,7 +1489,7 @@ int epicsShareAPI dbGetPromptGroup(DBENTRY *pdbentry)
|
||||
if(!pflddes) return(0);
|
||||
return(pflddes->promptgroup);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbCreateRecord(DBENTRY *pdbentry,const char *precordName)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -1535,7 +1536,7 @@ long epicsShareAPI dbCreateRecord(DBENTRY *pdbentry,const char *precordName)
|
||||
if(!ppvd) {errMessage(-1,"Logic Err: Could not add to PVD");return(-1);}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbDeleteAliases(DBENTRY *pdbentry)
|
||||
{
|
||||
dbBase *pdbbase = pdbentry->pdbbase;
|
||||
@@ -1653,7 +1654,7 @@ long epicsShareAPI dbFindRecord(DBENTRY *pdbentry, const char *pname)
|
||||
return dbFindField(pdbentry, ++pname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbFirstRecord(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -1706,7 +1707,7 @@ char * epicsShareAPI dbGetRecordName(DBENTRY *pdbentry)
|
||||
if(!precnode) return NULL;
|
||||
return precnode->recordname;
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbRenameRecord(DBENTRY *pdbentry,const char *newName)
|
||||
{
|
||||
dbBase *pdbbase = pdbentry->pdbbase;
|
||||
@@ -1752,7 +1753,7 @@ long epicsShareAPI dbRenameRecord(DBENTRY *pdbentry,const char *newName)
|
||||
/*Leave pdbentry pointing to newly renamed record*/
|
||||
return(dbFindRecord(pdbentry,newName));
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbVisibleRecord(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
@@ -1778,7 +1779,7 @@ int epicsShareAPI dbIsVisibleRecord(DBENTRY *pdbentry)
|
||||
if(!precnode) return 0;
|
||||
return precnode->flags & DBRN_FLAGS_VISIBLE ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbCreateAlias(DBENTRY *pdbentry, const char *alias)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -1828,7 +1829,7 @@ int epicsShareAPI dbIsAlias(DBENTRY *pdbentry)
|
||||
if(!precnode) return 0;
|
||||
return precnode->flags & DBRN_FLAGS_ISALIAS ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbCopyRecord(DBENTRY *pdbentry,const char *newRecordName,int overWriteOK)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -1882,7 +1883,7 @@ long epicsShareAPI dbCopyRecord(DBENTRY *pdbentry,const char *newRecordName,int
|
||||
/*Leave pdbentry pointing to newRecordName*/
|
||||
return(dbFindRecord(pdbentry,newRecordName));
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbFindFieldPart(DBENTRY *pdbentry,const char **ppname)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -1967,7 +1968,7 @@ long epicsShareAPI dbFindField(DBENTRY *pdbentry,const char *pname)
|
||||
|
||||
int epicsShareAPI dbFoundField(DBENTRY *pdbentry)
|
||||
{ return((pdbentry->pfield) ? TRUE : FALSE); }
|
||||
|
||||
|
||||
char * epicsShareAPI dbGetString(DBENTRY *pdbentry)
|
||||
{
|
||||
dbFldDes *pflddes = pdbentry->pflddes;
|
||||
@@ -1997,7 +1998,7 @@ char * epicsShareAPI dbGetString(DBENTRY *pdbentry)
|
||||
case DBF_DEVICE:
|
||||
return(dbGetStringNum(pdbentry));
|
||||
case DBF_INLINK:
|
||||
case DBF_OUTLINK:
|
||||
case DBF_OUTLINK:
|
||||
if(!pfield) {strcpy(message,"Field not found"); return(message);}
|
||||
plink = (DBLINK *)pfield;
|
||||
switch(plink->type) {
|
||||
@@ -2138,7 +2139,7 @@ char * epicsShareAPI dbGetString(DBENTRY *pdbentry)
|
||||
}
|
||||
return (message);
|
||||
}
|
||||
|
||||
|
||||
static void cvtDecimalOrHexToShort(char *from,short *value)
|
||||
{
|
||||
if(strspn(from,"0x")==2 || strspn(from,"0X")==2) {
|
||||
@@ -2264,7 +2265,7 @@ long epicsShareAPI dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
goto done;
|
||||
}
|
||||
switch (plink->type) {
|
||||
case CONSTANT:
|
||||
case CONSTANT:
|
||||
case PV_LINK: {
|
||||
short ppOpt = 0;
|
||||
short msOpt = 0;
|
||||
@@ -2428,7 +2429,7 @@ long epicsShareAPI dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
}
|
||||
break;
|
||||
case GPIB_IO: {
|
||||
char *end;
|
||||
char *end;
|
||||
|
||||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||||
pstr = end + 1;
|
||||
@@ -2545,7 +2546,7 @@ done:
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||||
{
|
||||
dbFldDes *pflddes = pdbentry->pflddes;
|
||||
@@ -2591,13 +2592,13 @@ char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||||
return(message);
|
||||
}
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_CHAR :
|
||||
case DBF_CHAR :
|
||||
if(value<-128 || value>127) {
|
||||
strcpy(message,"must have -128<=value<=127");
|
||||
return(message);
|
||||
}
|
||||
return(NULL);
|
||||
case DBF_SHORT :
|
||||
case DBF_SHORT :
|
||||
if(value<-32768 || value>32767) {
|
||||
strcpy(message,"must have -32768<=value<=32767");
|
||||
return(message);
|
||||
@@ -2626,14 +2627,14 @@ char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||||
return(message);
|
||||
}
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_UCHAR :
|
||||
case DBF_UCHAR :
|
||||
if(value>255) {
|
||||
strcpy(message,"must have 0<=value<=255");
|
||||
return(message);
|
||||
}
|
||||
return(NULL);
|
||||
case DBF_ENUM:
|
||||
case DBF_USHORT :
|
||||
case DBF_USHORT :
|
||||
if(value>65535) {
|
||||
strcpy(message,"must have 0<=value<=65535");
|
||||
return(message);
|
||||
@@ -2646,7 +2647,7 @@ char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||||
}
|
||||
}
|
||||
case DBF_FLOAT:
|
||||
case DBF_DOUBLE: {
|
||||
case DBF_DOUBLE: {
|
||||
double value;
|
||||
char *endp;
|
||||
|
||||
@@ -2661,7 +2662,7 @@ char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||||
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
|
||||
char *pchoice;
|
||||
int i;
|
||||
|
||||
|
||||
if(!pdbMenu) return(NULL);
|
||||
for (i = 0; i < pdbMenu->nChoice; i++) {
|
||||
if(!(pchoice = pdbMenu->papChoiceValue[i])) continue;
|
||||
@@ -2699,7 +2700,7 @@ char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||||
strcpy(message,"Not a valid field type");
|
||||
return (message);
|
||||
}
|
||||
|
||||
|
||||
char *epicsShareAPI dbGetRange(DBENTRY *pdbentry)
|
||||
{
|
||||
dbFldDes *pflddes = pdbentry->pflddes;
|
||||
@@ -2729,14 +2730,14 @@ char *epicsShareAPI dbGetRange(DBENTRY *pdbentry)
|
||||
strcpy(message,"Not a valid field type");
|
||||
return (message);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbFirstInfo(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
|
||||
|
||||
pdbentry->pinfonode = NULL;
|
||||
if (!precnode) return (S_dbLib_recNotFound);
|
||||
|
||||
|
||||
pdbentry->pinfonode = (dbInfoNode *)ellFirst(&precnode->infoList);
|
||||
return (pdbentry->pinfonode ? 0 : S_dbLib_infoNotFound);
|
||||
}
|
||||
@@ -2745,11 +2746,11 @@ long epicsShareAPI dbNextInfo(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
dbInfoNode *pinfo;
|
||||
|
||||
|
||||
if (!precnode) return (S_dbLib_recNotFound);
|
||||
pinfo = pdbentry->pinfonode;
|
||||
if (!pinfo) return (S_dbLib_infoNotFound);
|
||||
|
||||
|
||||
pinfo = (dbInfoNode *)ellNext(&pinfo->node);
|
||||
pdbentry->pinfonode = pinfo;
|
||||
return (pinfo ? 0 : S_dbLib_infoNotFound);
|
||||
@@ -2759,10 +2760,10 @@ long epicsShareAPI dbFindInfo(DBENTRY *pdbentry,const char *name)
|
||||
{
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
dbInfoNode *pinfo;
|
||||
|
||||
|
||||
pdbentry->pinfonode = NULL;
|
||||
if (!precnode) return(S_dbLib_recNotFound);
|
||||
|
||||
|
||||
pinfo = (dbInfoNode *)ellFirst(&precnode->infoList);
|
||||
while (pinfo) {
|
||||
if (!strcmp(pinfo->name, name)) {
|
||||
@@ -2778,7 +2779,7 @@ long epicsShareAPI dbDeleteInfo(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||||
|
||||
|
||||
if (!precnode) return (S_dbLib_recNotFound);
|
||||
if (!pinfo) return (S_dbLib_infoNotFound);
|
||||
ellDelete(&precnode->infoList,&pinfo->node);
|
||||
@@ -2841,11 +2842,11 @@ long epicsShareAPI dbPutInfo(DBENTRY *pdbentry,const char *name,const char *stri
|
||||
dbInfoNode *pinfo;
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
if (!precnode) return (S_dbLib_recNotFound);
|
||||
|
||||
|
||||
dbFindInfo(pdbentry, name);
|
||||
pinfo = pdbentry->pinfonode;
|
||||
if (pinfo) return (dbPutInfoString(pdbentry, string));
|
||||
|
||||
|
||||
/*Create new info node*/
|
||||
pinfo = calloc(1,sizeof(dbInfoNode));
|
||||
if (!pinfo) return (S_dbLib_outMem);
|
||||
@@ -2875,7 +2876,7 @@ brkTable * epicsShareAPI dbFindBrkTable(dbBase *pdbbase,const char *name)
|
||||
if(!pgph) return(NULL);
|
||||
return((brkTable *)pgph->userPvt);
|
||||
}
|
||||
|
||||
|
||||
dbMenu * epicsShareAPI dbFindMenu(dbBase *pdbbase,const char *name)
|
||||
{
|
||||
GPHENTRY *pgph;
|
||||
@@ -2933,7 +2934,7 @@ int epicsShareAPI dbGetNMenuChoices(DBENTRY *pdbentry)
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
char * epicsShareAPI dbGetMenuStringFromIndex(DBENTRY *pdbentry, int index)
|
||||
{
|
||||
dbFldDes *pflddes = pdbentry->pflddes;
|
||||
@@ -2996,13 +2997,13 @@ int epicsShareAPI dbGetMenuIndexFromString(DBENTRY *pdbentry, const char *choice
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
drvSup * epicsShareAPI dbFindDriver(dbBase *pdbbase, const char *name) {
|
||||
GPHENTRY *pgph = gphFind(pdbbase->pgpHash,name,&pdbbase->drvList);
|
||||
if (!pgph) return NULL;
|
||||
return (drvSup *) pgph->userPvt;
|
||||
}
|
||||
|
||||
|
||||
int epicsShareAPI dbAllocForm(DBENTRY *psave)
|
||||
{
|
||||
DBENTRY dbEntry;
|
||||
@@ -3076,7 +3077,7 @@ done:
|
||||
dbFinishEntry(pdbentry);
|
||||
return(nlines);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbFreeForm(DBENTRY *pdbentry)
|
||||
{
|
||||
if(pdbentry->formpvt) {
|
||||
@@ -3093,7 +3094,7 @@ char ** epicsShareAPI dbGetFormPrompt(DBENTRY *pdbentry)
|
||||
if(!pform) return(NULL);
|
||||
return(pform->prompt);
|
||||
}
|
||||
|
||||
|
||||
char ** epicsShareAPI dbGetFormValue(DBENTRY *pdbentry)
|
||||
{
|
||||
struct form *pform = pdbentry->formpvt;
|
||||
@@ -3105,7 +3106,7 @@ char ** epicsShareAPI dbGetFormValue(DBENTRY *pdbentry)
|
||||
if(!plink) return(NULL);
|
||||
value = pform->value;
|
||||
switch(pform->linkType) {
|
||||
case FORM_CONSTANT:
|
||||
case FORM_CONSTANT:
|
||||
if(plink->value.constantStr) {
|
||||
strcpy(*value,plink->value.constantStr);
|
||||
} else {
|
||||
@@ -3263,7 +3264,7 @@ char ** epicsShareAPI dbGetFormValue(DBENTRY *pdbentry)
|
||||
}
|
||||
return(pform->value);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbPutForm(DBENTRY *pdbentry,char **value)
|
||||
{
|
||||
struct form *pform = pdbentry->formpvt;
|
||||
@@ -3279,7 +3280,7 @@ long epicsShareAPI dbPutForm(DBENTRY *pdbentry,char **value)
|
||||
if(!plink) return(S_dbLib_badLink);
|
||||
verify = pform->verify;
|
||||
switch(pform->linkType) {
|
||||
case FORM_CONSTANT:
|
||||
case FORM_CONSTANT:
|
||||
**verify = 0; /*Initialize to no error*/
|
||||
if(**value == '\0') break;
|
||||
dvalue = epicsStrtod(*value,&endp);
|
||||
@@ -3580,7 +3581,7 @@ long epicsShareAPI dbPutForm(DBENTRY *pdbentry,char **value)
|
||||
**verify = 0;
|
||||
break;
|
||||
case FORM_VXI_IO:
|
||||
plink->value.vxiio.flag =
|
||||
plink->value.vxiio.flag =
|
||||
((strchr(*value,'Y')||strchr(*value,'y') ? VXIDYNAMIC : VXISTATIC));
|
||||
value++; verify++;
|
||||
lvalue = strtol(*value,&endp,0);
|
||||
@@ -3619,7 +3620,7 @@ long epicsShareAPI dbPutForm(DBENTRY *pdbentry,char **value)
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
char ** epicsShareAPI dbVerifyForm(DBENTRY *pdbentry,char **value)
|
||||
{
|
||||
struct form *pform = pdbentry->formpvt;
|
||||
@@ -3664,7 +3665,7 @@ char * epicsShareAPI dbGetRelatedField(DBENTRY *psave)
|
||||
dbFinishEntry(pdbentry);
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
|
||||
int epicsShareAPI dbGetNLinks(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -3715,7 +3716,7 @@ int epicsShareAPI dbGetLinkType(DBENTRY *pdbentry)
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbCvtLinkToConstant(DBENTRY *pdbentry)
|
||||
{
|
||||
dbFldDes *pflddes;
|
||||
@@ -3779,7 +3780,7 @@ long epicsShareAPI dbCvtLinkToPvlink(DBENTRY *pdbentry)
|
||||
}
|
||||
return(S_dbLib_badLink);
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI dbDumpPath(DBBASE *pdbbase)
|
||||
{
|
||||
ELLLIST *ppathList;
|
||||
@@ -3821,7 +3822,7 @@ void epicsShareAPI dbDumpMenu(dbBase *pdbbase,const char *menuName)
|
||||
}
|
||||
dbWriteMenuFP(pdbbase,stdout,menuName);
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI dbDumpRecordType(DBBASE *pdbbase,const char *recordTypeName)
|
||||
{
|
||||
dbRecordType *pdbRecordType;
|
||||
@@ -3863,7 +3864,7 @@ void epicsShareAPI dbDumpRecordType(DBBASE *pdbbase,const char *recordTypeName)
|
||||
if(recordTypeName) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI dbDumpField(
|
||||
DBBASE *pdbbase,const char *recordTypeName,const char *fname)
|
||||
{
|
||||
@@ -3955,7 +3956,7 @@ void epicsShareAPI dbDumpField(
|
||||
if(recordTypeName) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||||
{
|
||||
dbRecordType *pdbRecordType;
|
||||
@@ -4051,7 +4052,7 @@ void epicsShareAPI dbDumpBreaktable(DBBASE *pdbbase,const char *name)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static char *bus[VXI_IO+1] = {"","","VME","CAMAC","AB",
|
||||
"GPIB","BITBUS","","","","","","INST","BBGPIB","VXI"};
|
||||
void epicsShareAPI dbReportDeviceConfig(dbBase *pdbbase,FILE *report)
|
||||
|
||||
Reference in New Issue
Block a user