Support "link(name, lset)" syntax in DBD files
Both Perl and dbStaticLib support included. Also added a new std/link directory for link types. Nothing looks up the registered link support tables yet.
This commit is contained in:
@@ -44,6 +44,13 @@ typedef struct devSup {
|
||||
struct dsxt *pdsxt; /* Extended device support */
|
||||
}devSup;
|
||||
|
||||
typedef struct linkSup {
|
||||
ELLNODE node;
|
||||
char *name;
|
||||
char *lset_name;
|
||||
struct lset *lset;
|
||||
} linkSup;
|
||||
|
||||
typedef struct dbDeviceMenu {
|
||||
int nChoice;
|
||||
char **papChoice;
|
||||
@@ -162,6 +169,7 @@ typedef struct dbBase {
|
||||
ELLLIST menuList;
|
||||
ELLLIST recordTypeList;
|
||||
ELLLIST drvList;
|
||||
ELLLIST linkList;
|
||||
ELLLIST registrarList;
|
||||
ELLLIST functionList;
|
||||
ELLLIST variableList;
|
||||
|
||||
@@ -38,6 +38,7 @@ static int yyreset(void)
|
||||
"field" return(tokenFIELD);
|
||||
"device" return(tokenDEVICE);
|
||||
"driver" return(tokenDRIVER);
|
||||
"link" return(tokenLINK);
|
||||
"breaktable" return(tokenBREAKTABLE);
|
||||
"record" return(tokenRECORD);
|
||||
"grecord" return(tokenGRECORD);
|
||||
|
||||
@@ -75,6 +75,7 @@ static void dbRecordtypeFieldItem(char *name,char *value);
|
||||
static void dbDevice(char *recordtype,char *linktype,
|
||||
char *dsetname,char *choicestring);
|
||||
static void dbDriver(char *name);
|
||||
static void dbLinkType(char *name, char *lset_name);
|
||||
static void dbRegistrar(char *name);
|
||||
static void dbFunction(char *name);
|
||||
static void dbVariable(char *name, char *type);
|
||||
@@ -785,6 +786,26 @@ static void dbDriver(char *name)
|
||||
ellAdd(&pdbbase->drvList,&pdrvSup->node);
|
||||
}
|
||||
|
||||
static void dbLinkType(char *name, char *lset_name)
|
||||
{
|
||||
linkSup *pLinkSup;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
pgphentry = gphFind(pdbbase->pgpHash, name, &pdbbase->linkList);
|
||||
if (pgphentry) {
|
||||
return;
|
||||
}
|
||||
pLinkSup = dbCalloc(1,sizeof(linkSup));
|
||||
pLinkSup->name = epicsStrDup(name);
|
||||
pLinkSup->lset_name = epicsStrDup(lset_name);
|
||||
pgphentry = gphAdd(pdbbase->pgpHash, pLinkSup->name, &pdbbase->linkList);
|
||||
if (!pgphentry) {
|
||||
yyerrorAbort("gphAdd failed");
|
||||
}
|
||||
pgphentry->userPvt = pLinkSup;
|
||||
ellAdd(&pdbbase->linkList, &pLinkSup->node);
|
||||
}
|
||||
|
||||
static void dbRegistrar(char *name)
|
||||
{
|
||||
dbText *ptext;
|
||||
|
||||
@@ -86,6 +86,14 @@ static void dbDumpDriverCallFunc(const iocshArgBuf *args)
|
||||
dbDumpDriver(*iocshPpdbbase);
|
||||
}
|
||||
|
||||
/* dbDumpLink */
|
||||
static const iocshArg * const dbDumpLinkArgs[] = { &argPdbbase};
|
||||
static const iocshFuncDef dbDumpLinkFuncDef = {"dbDumpLink",1,dbDumpLinkArgs};
|
||||
static void dbDumpLinkCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbDumpLink(*iocshPpdbbase);
|
||||
}
|
||||
|
||||
/* dbDumpRegistrar */
|
||||
static const iocshArg * const dbDumpRegistrarArgs[] = { &argPdbbase};
|
||||
static const iocshFuncDef dbDumpRegistrarFuncDef = {"dbDumpRegistrar",1,dbDumpRegistrarArgs};
|
||||
@@ -160,6 +168,7 @@ void dbStaticIocRegister(void)
|
||||
iocshRegister(&dbDumpFieldFuncDef, dbDumpFieldCallFunc);
|
||||
iocshRegister(&dbDumpDeviceFuncDef, dbDumpDeviceCallFunc);
|
||||
iocshRegister(&dbDumpDriverFuncDef, dbDumpDriverCallFunc);
|
||||
iocshRegister(&dbDumpLinkFuncDef, dbDumpLinkCallFunc);
|
||||
iocshRegister(&dbDumpRegistrarFuncDef,dbDumpRegistrarCallFunc);
|
||||
iocshRegister(&dbDumpFunctionFuncDef, dbDumpFunctionCallFunc);
|
||||
iocshRegister(&dbDumpVariableFuncDef, dbDumpVariableCallFunc);
|
||||
|
||||
@@ -458,6 +458,7 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
dbVariableDef *pvarNext;
|
||||
drvSup *pdrvSup;
|
||||
drvSup *pdrvSupNext;
|
||||
linkSup *plinkSup;
|
||||
brkTable *pbrkTable;
|
||||
brkTable *pbrkTableNext;
|
||||
chFilterPlugin *pfilt;
|
||||
@@ -558,6 +559,11 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
free((void *)pdrvSup);
|
||||
pdrvSup = pdrvSupNext;
|
||||
}
|
||||
while ((plinkSup = (linkSup *) ellGet(&pdbbase->linkList))) {
|
||||
free(plinkSup->lset_name);
|
||||
free(plinkSup->name);
|
||||
free(plinkSup);
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbbase->registrarList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
@@ -1070,6 +1076,21 @@ long dbWriteDriverFP(DBBASE *pdbbase,FILE *fp)
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbWriteLinkFP(DBBASE *pdbbase, FILE *fp)
|
||||
{
|
||||
linkSup *plinkSup;
|
||||
|
||||
if (!pdbbase) {
|
||||
fprintf(stderr, "pdbbase not specified\n");
|
||||
return -1;
|
||||
}
|
||||
for (plinkSup = (linkSup *) ellFirst(&pdbbase->linkList);
|
||||
plinkSup; plinkSup = (linkSup *) ellNext(&plinkSup->node)) {
|
||||
fprintf(fp, "link(%s,%s)\n", plinkSup->name, plinkSup->lset_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long dbWriteRegistrarFP(DBBASE *pdbbase,FILE *fp)
|
||||
{
|
||||
dbText *ptext;
|
||||
@@ -3107,6 +3128,12 @@ char * dbGetRelatedField(DBENTRY *psave)
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
linkSup* dbFindLinkSup(dbBase *pdbbase, const char *name) {
|
||||
GPHENTRY *pgph = gphFind(pdbbase->pgpHash,name,&pdbbase->linkList);
|
||||
if (!pgph) return NULL;
|
||||
return (linkSup *) pgph->userPvt;
|
||||
}
|
||||
|
||||
int dbGetNLinks(DBENTRY *pdbentry)
|
||||
{
|
||||
dbRecordType *precordType = pdbentry->precordType;
|
||||
@@ -3460,6 +3487,15 @@ void dbDumpDriver(DBBASE *pdbbase)
|
||||
dbWriteDriverFP(pdbbase,stdout);
|
||||
}
|
||||
|
||||
void dbDumpLink(DBBASE *pdbbase)
|
||||
{
|
||||
if(!pdbbase) {
|
||||
fprintf(stderr,"pdbbase not specified\n");
|
||||
return;
|
||||
}
|
||||
dbWriteLinkFP(pdbbase,stdout);
|
||||
}
|
||||
|
||||
void dbDumpRegistrar(DBBASE *pdbbase)
|
||||
{
|
||||
if(!pdbbase) {
|
||||
|
||||
@@ -99,6 +99,7 @@ epicsShareFunc long dbWriteDeviceFP(DBBASE *pdbbase, FILE *fp);
|
||||
epicsShareFunc long dbWriteDriver(DBBASE *pdbbase,
|
||||
const char *filename);
|
||||
epicsShareFunc long dbWriteDriverFP(DBBASE *pdbbase, FILE *fp);
|
||||
epicsShareFunc long dbWriteLinkFP(DBBASE *pdbbase, FILE *fp);
|
||||
epicsShareFunc long dbWriteRegistrarFP(DBBASE *pdbbase, FILE *fp);
|
||||
epicsShareFunc long dbWriteFunctionFP(DBBASE *pdbbase, FILE *fp);
|
||||
epicsShareFunc long dbWriteVariableFP(DBBASE *pdbbase, FILE *fp);
|
||||
@@ -208,6 +209,9 @@ epicsShareFunc drvSup * dbFindDriver(dbBase *pdbbase,
|
||||
const char *name);
|
||||
epicsShareFunc char * dbGetRelatedField(DBENTRY *pdbentry);
|
||||
|
||||
epicsShareFunc linkSup * dbFindLinkSup(dbBase *pdbbase,
|
||||
const char *name);
|
||||
|
||||
epicsShareFunc int dbGetNLinks(DBENTRY *pdbentry);
|
||||
epicsShareFunc long dbGetLinkField(DBENTRY *pdbentry, int index);
|
||||
epicsShareFunc int dbGetLinkType(DBENTRY *pdbentry);
|
||||
@@ -227,6 +231,7 @@ epicsShareFunc void dbDumpField(DBBASE *pdbbase,
|
||||
epicsShareFunc void dbDumpDevice(DBBASE *pdbbase,
|
||||
const char *recordTypeName);
|
||||
epicsShareFunc void dbDumpDriver(DBBASE *pdbbase);
|
||||
epicsShareFunc void dbDumpLink(DBBASE *pdbbase);
|
||||
epicsShareFunc void dbDumpRegistrar(DBBASE *pdbbase);
|
||||
epicsShareFunc void dbDumpFunction(DBBASE *pdbbase);
|
||||
epicsShareFunc void dbDumpVariable(DBBASE *pdbbase);
|
||||
|
||||
@@ -20,7 +20,7 @@ static int yyAbort = 0;
|
||||
%token tokenINCLUDE tokenPATH tokenADDPATH
|
||||
%token tokenALIAS tokenMENU tokenCHOICE tokenRECORDTYPE
|
||||
%token tokenFIELD tokenINFO tokenREGISTRAR
|
||||
%token tokenDEVICE tokenDRIVER tokenBREAKTABLE
|
||||
%token tokenDEVICE tokenDRIVER tokenLINK tokenBREAKTABLE
|
||||
%token tokenRECORD tokenGRECORD tokenVARIABLE tokenFUNCTION
|
||||
%token <Str> tokenSTRING tokenCDEFS
|
||||
|
||||
@@ -46,6 +46,7 @@ database_item: include
|
||||
| tokenRECORDTYPE recordtype_head recordtype_body
|
||||
| device
|
||||
| driver
|
||||
| link
|
||||
| registrar
|
||||
| function
|
||||
| variable
|
||||
@@ -162,6 +163,13 @@ driver: tokenDRIVER '(' tokenSTRING ')'
|
||||
dbDriver($3); dbmfFree($3);
|
||||
};
|
||||
|
||||
link: tokenLINK '(' tokenSTRING ',' tokenSTRING ')'
|
||||
{
|
||||
if(dbStaticDebug>2) printf("link %s %s\n",$3,$5);
|
||||
dbLinkType($3,$5);
|
||||
dbmfFree($3); dbmfFree($5);
|
||||
};
|
||||
|
||||
registrar: tokenREGISTRAR '(' tokenSTRING ')'
|
||||
{
|
||||
if(dbStaticDebug>2) printf("registrar %s\n",$3);
|
||||
|
||||
@@ -20,6 +20,7 @@ dbRecStd_RCS += dbRecStd.rc
|
||||
include $(STDDIR)/rec/Makefile
|
||||
include $(STDDIR)/dev/Makefile
|
||||
include $(STDDIR)/filters/Makefile
|
||||
include $(STDDIR)/link/Makefile
|
||||
include $(STDDIR)/softIoc/Makefile
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
17
src/std/link/Makefile
Normal file
17
src/std/link/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# This is a Makefile fragment, see src/std/Makefile.
|
||||
|
||||
SRC_DIRS += $(STDDIR)/link
|
||||
|
||||
DBD += links.dbd
|
||||
|
||||
# dbRecStd_SRCS += ...
|
||||
|
||||
HTMLS += links.html
|
||||
|
||||
92
src/std/link/links.dbd.pod
Normal file
92
src/std/link/links.dbd.pod
Normal file
@@ -0,0 +1,92 @@
|
||||
=head1 Link Types
|
||||
|
||||
Links are an extensible mechanism for adding new kinds of database link,
|
||||
using JSON for link addresses.
|
||||
The following link types are available in this release:
|
||||
|
||||
=over
|
||||
|
||||
=item * L<Constant|/"Constant Link const">
|
||||
|
||||
=item * L<Database|/"Database Link db">
|
||||
|
||||
=item * L<Channel Access|/"Channel Access Link ca">
|
||||
|
||||
=back
|
||||
|
||||
=head2 Using Links
|
||||
|
||||
...
|
||||
must appear inside a pair of braces C< {} > expressed as a JSON
|
||||
(L<JavaScript Object Notation|http://www.json.org/>) object, which allows link
|
||||
parameters to be defined as needed.
|
||||
|
||||
Note that due to the required presence of the double-quote characters in the
|
||||
JSON strings in a link field value string in a database file, it will usually
|
||||
be necessary to escape all double-quote characters in the JSON object by
|
||||
preceding them with a backslash C< \ > character.
|
||||
Database configuration tools that support this link mechanism must be careful
|
||||
to handle these escapes correctly on reading and writing string values from/to
|
||||
a .db file.
|
||||
|
||||
=head2 Filter Reference
|
||||
|
||||
=cut
|
||||
|
||||
link(const,lsetConst)
|
||||
|
||||
=head3 Constant Link C<"const">
|
||||
|
||||
...
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
...
|
||||
|
||||
=head4 Example
|
||||
|
||||
...
|
||||
|
||||
=cut
|
||||
|
||||
link(db,lsetDatabase)
|
||||
|
||||
=head3 Database Link C<"db">
|
||||
|
||||
...
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
...
|
||||
|
||||
=head4 Example
|
||||
|
||||
...
|
||||
|
||||
=cut
|
||||
|
||||
link(ca,lsetChannelAccess)
|
||||
|
||||
=head3 Channel Access Link C<"ca">
|
||||
|
||||
...
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
...
|
||||
|
||||
=over
|
||||
|
||||
=item ...
|
||||
|
||||
...
|
||||
|
||||
=back
|
||||
|
||||
...
|
||||
|
||||
=head4 Example
|
||||
|
||||
...
|
||||
|
||||
=cut
|
||||
@@ -9,8 +9,10 @@
|
||||
|
||||
softIoc.dbd$(DEP): $(COMMON_DIR)/stdRecords.dbd
|
||||
softIoc.dbd$(DEP): $(COMMON_DIR)/filters.dbd
|
||||
softIoc.dbd$(DEP): $(COMMON_DIR)/links.dbd
|
||||
$(COMMON_DIR)/softIoc.dbd: $(COMMON_DIR)/stdRecords.dbd
|
||||
$(COMMON_DIR)/softIoc.dbd: $(COMMON_DIR)/filters.dbd
|
||||
$(COMMON_DIR)/softIoc.dbd: $(COMMON_DIR)/links.dbd
|
||||
$(COMMON_DIR)/softIoc.dbd: $(STDDIR)/softIoc/Makefile
|
||||
|
||||
softMain$(DEP): epicsInstallDir.h
|
||||
|
||||
@@ -16,6 +16,9 @@ include "stdRecords.dbd"
|
||||
# Channel filters & plugins
|
||||
include "filters.dbd"
|
||||
|
||||
# Link types
|
||||
include "links.dbd"
|
||||
|
||||
# Standard device support
|
||||
include "devSoft.dbd"
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use warnings;
|
||||
use DBD::Base;
|
||||
use DBD::Breaktable;
|
||||
use DBD::Driver;
|
||||
use DBD::Link;
|
||||
use DBD::Menu;
|
||||
use DBD::Recordtype;
|
||||
use DBD::Recfield;
|
||||
@@ -21,6 +22,7 @@ sub new {
|
||||
my $this = {
|
||||
'DBD::Breaktable' => {},
|
||||
'DBD::Driver' => {},
|
||||
'DBD::Link' => {},
|
||||
'DBD::Function' => {},
|
||||
'DBD::Menu' => {},
|
||||
'DBD::Recordtype' => {},
|
||||
@@ -80,6 +82,10 @@ sub drivers {
|
||||
return shift->{'DBD::Driver'};
|
||||
}
|
||||
|
||||
sub links {
|
||||
return shift->{'DBD::Link'};
|
||||
}
|
||||
|
||||
sub functions {
|
||||
return shift->{'DBD::Function'};
|
||||
}
|
||||
|
||||
22
src/tools/DBD/Link.pm
Normal file
22
src/tools/DBD/Link.pm
Normal file
@@ -0,0 +1,22 @@
|
||||
package DBD::Link;
|
||||
use DBD::Base;
|
||||
@ISA = qw(DBD::Base);
|
||||
|
||||
sub init {
|
||||
my ($this, $name, $lset) = @_;
|
||||
$this->SUPER::init($lset, "link support (lset)");
|
||||
$this->{KEY} = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
sub key {
|
||||
return shift->{KEY};
|
||||
}
|
||||
|
||||
sub equals {
|
||||
my ($a, $b) = @_;
|
||||
return $a->SUPER::equals($b)
|
||||
&& $a->{KEY} eq $b->{KEY};
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -13,6 +13,7 @@ use DBD::Base;
|
||||
use DBD::Breaktable;
|
||||
use DBD::Device;
|
||||
use DBD::Driver;
|
||||
use DBD::Link;
|
||||
use DBD::Menu;
|
||||
use DBD::Recordtype;
|
||||
use DBD::Recfield;
|
||||
@@ -26,6 +27,7 @@ sub OutputDBD {
|
||||
OutputMenus($out, $dbd->menus);
|
||||
OutputRecordtypes($out, $dbd->recordtypes);
|
||||
OutputDrivers($out, $dbd->drivers);
|
||||
OutputLinks($out, $dbd->links);
|
||||
OutputRegistrars($out, $dbd->registrars);
|
||||
OutputFunctions($out, $dbd->functions);
|
||||
OutputVariables($out, $dbd->variables);
|
||||
@@ -78,6 +80,13 @@ sub OutputDrivers {
|
||||
foreach keys %{$drivers};
|
||||
}
|
||||
|
||||
sub OutputLinks {
|
||||
my ($out, $links) = @_;
|
||||
while (my ($name, $link) = each %{$links}) {
|
||||
printf $out "link(%s, %s)\n", $link->key, $name;
|
||||
}
|
||||
}
|
||||
|
||||
sub OutputRegistrars {
|
||||
my ($out, $registrars) = @_;
|
||||
printf $out "registrar(%s)\n", $_
|
||||
|
||||
@@ -13,6 +13,7 @@ use DBD::Base;
|
||||
use DBD::Breaktable;
|
||||
use DBD::Device;
|
||||
use DBD::Driver;
|
||||
use DBD::Link;
|
||||
use DBD::Menu;
|
||||
use DBD::Recordtype;
|
||||
use DBD::Recfield;
|
||||
@@ -37,6 +38,11 @@ sub ParseDBD {
|
||||
my ($driver_name) = unquote($1);
|
||||
$dbd->add(DBD::Driver->new($driver_name));
|
||||
}
|
||||
elsif (m/\G link \s* \( \s* $RXstr \s*, \s* $RXstr \s* \)/oxgc) {
|
||||
print "Link $1, $2\n" if $debug;
|
||||
my ($key, $lset) = unquote($1, $2);
|
||||
$dbd->add(DBD::Link->new($key, $lset));
|
||||
}
|
||||
elsif (m/\G registrar \s* \( \s* $RXstr \s* \)/oxgc) {
|
||||
print "Registrar: $1\n" if $debug;
|
||||
my ($registrar_name) = unquote($1);
|
||||
|
||||
@@ -23,6 +23,7 @@ PERL_MODULES += DBD/Base.pm
|
||||
PERL_MODULES += DBD/Breaktable.pm
|
||||
PERL_MODULES += DBD/Device.pm
|
||||
PERL_MODULES += DBD/Driver.pm
|
||||
PERL_MODULES += DBD/Link.pm
|
||||
PERL_MODULES += DBD/Function.pm
|
||||
PERL_MODULES += DBD/Menu.pm
|
||||
PERL_MODULES += DBD/Output.pm
|
||||
|
||||
Reference in New Issue
Block a user