Merged the loadable-support branch
This commit is contained in:
@@ -15,6 +15,26 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.</p>
|
||||
<h2 align="center">Changes between 3.15.0.1 and 3.15.0.2</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Full support for loadable support modules</h3>
|
||||
|
||||
<p>Apparently later versions of Base 3.14 permitted support modules to be loaded
|
||||
from a shared library at runtime without the IOC having been linked against that
|
||||
shared library; the registerRecordDeviceDriver.pl program would accept a partial
|
||||
DBD file containing just the entries needed for the library and generate the
|
||||
appropriate registration code. In 3.15 however the registerRecordDeviceDriver.pl
|
||||
program was replaced by one using the new DBD file parser, and in this a device
|
||||
support entry would only be accepted after first loading the record type that it
|
||||
depended on.</p>
|
||||
|
||||
<p>The parser has been modified to accept device entries without having seen the
|
||||
record type first, although a warning is given when that happens. To remove the
|
||||
warning the DBD file can provide a record type declaration instead (no fields
|
||||
can be defined, so the braces must be empty), before the device() entry. The
|
||||
result will generate the correct registration code for the device entry without
|
||||
including anything for any merely declared record types. The generated code can
|
||||
be linked into a shared library and loaded by an IOC at runtime using dlload.
|
||||
</p>
|
||||
|
||||
<h3>Parallel callback threads</h3>
|
||||
|
||||
<p>The general purpose callback facility can run multiple parallel callback
|
||||
|
||||
@@ -62,6 +62,7 @@ static void dbMenuChoice(char *name,char *value);
|
||||
static void dbMenuBody(void);
|
||||
|
||||
static void dbRecordtypeHead(char *name);
|
||||
static void dbRecordtypeEmpty(void);
|
||||
static void dbRecordtypeBody(void);
|
||||
static void dbRecordtypeFieldHead(char *name,char *type);
|
||||
static void dbRecordtypeFieldItem(char *name,char *value);
|
||||
@@ -607,6 +608,23 @@ static void dbRecordtypeCdef(char *text) {
|
||||
return;
|
||||
}
|
||||
|
||||
static void dbRecordtypeEmpty(void)
|
||||
{
|
||||
tempListNode *ptempListNode;
|
||||
dbRecordType *pdbRecordType;
|
||||
|
||||
if (duplicate) {
|
||||
duplicate = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbRecordType = ptempListNode->item;
|
||||
epicsPrintf("Declaration of recordtype(%s) preceeded full definition.\n",
|
||||
pdbRecordType->name);
|
||||
yyerrorAbort(NULL);
|
||||
}
|
||||
|
||||
static void dbRecordtypeBody(void)
|
||||
{
|
||||
dbRecordType *pdbRecordType;
|
||||
|
||||
@@ -100,7 +100,12 @@ recordtype_head: '(' tokenSTRING ')'
|
||||
dbRecordtypeHead($2); dbmfFree($2);
|
||||
};
|
||||
|
||||
recordtype_body: '{' recordtype_field_list '}'
|
||||
recordtype_body: '{' '}'
|
||||
{
|
||||
if(dbStaticDebug>2) printf("empty recordtype_body\n");
|
||||
dbRecordtypeEmpty();
|
||||
}
|
||||
| '{' recordtype_field_list '}'
|
||||
{
|
||||
if(dbStaticDebug>2) printf("recordtype_body\n");
|
||||
dbRecordtypeBody();
|
||||
@@ -215,14 +220,14 @@ record_head: '(' tokenSTRING ',' tokenSTRING ')'
|
||||
dbRecordHead($2,$4,0); dbmfFree($2); dbmfFree($4);
|
||||
};
|
||||
|
||||
record_body: /*Null*/
|
||||
record_body: /* empty */
|
||||
{
|
||||
if(dbStaticDebug>2) printf("null record_body\n");
|
||||
dbRecordBody();
|
||||
}
|
||||
| '{' '}'
|
||||
{
|
||||
if(dbStaticDebug>2) printf("record_body - no fields\n");
|
||||
if(dbStaticDebug>2) printf("empty record_body\n");
|
||||
dbRecordBody();
|
||||
}
|
||||
| '{' record_field_list '}'
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/* osi/os/default/epicsFindSymbol.c */
|
||||
/* osi/os/RTEMS/osdFindSymbol.c */
|
||||
|
||||
#include <dlfcn.h>
|
||||
/* GESYS could support this, but must use compile-time detection
|
||||
* as the code must build for non-GESYS systems as well.
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsFindSymbol.h"
|
||||
|
||||
epicsShareFunc void * epicsLoadLibrary(const char *name)
|
||||
{
|
||||
return dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc const char *epicsLoadError(void)
|
||||
{
|
||||
return dlerror();
|
||||
return "epicsLoadLibrary not implemented";
|
||||
}
|
||||
|
||||
epicsShareFunc void * epicsShareAPI epicsFindSymbol(const char *name)
|
||||
{
|
||||
return dlsym(0, name);
|
||||
return 0;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* osi/os/WIN32/epicsFindSymbol.c */
|
||||
/* osi/os/WIN32/osdFindSymbol.c */
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -6,16 +6,22 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* osi/os/default/epicsFindSymbol.c */
|
||||
/* osi/os/default/osdFindSymbol.c */
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsFindSymbol.h"
|
||||
|
||||
epicsShareFunc void * epicsLoadLibrary(const char *name)
|
||||
{ return 0; }
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc const char *epicsLoadError(void)
|
||||
{ return "epicsLoadLibrary not implemented"; }
|
||||
{
|
||||
return "epicsLoadLibrary not implemented";
|
||||
}
|
||||
|
||||
epicsShareFunc void * epicsShareAPI epicsFindSymbol(const char *name)
|
||||
{ return 0;}
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* osi/os/default/epicsFindSymbol.c */
|
||||
/* osi/os/posix/osdFindSymbol.c */
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2009 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.
|
||||
\*************************************************************************/
|
||||
/* osi/os/default/epicsFindSymbol.c */
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsFindSymbol.h"
|
||||
|
||||
epicsShareFunc void * epicsLoadLibrary(const char *name)
|
||||
{
|
||||
return dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
|
||||
}
|
||||
|
||||
epicsShareFunc const char *epicsLoadError(void)
|
||||
{
|
||||
return dlerror();
|
||||
}
|
||||
|
||||
epicsShareFunc void * epicsShareAPI epicsFindSymbol(const char *name)
|
||||
{
|
||||
return dlsym(0, name);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* osi/os/vxWorks/osiFindSymbol */
|
||||
/* osi/os/vxWorks/osdFindSymbol */
|
||||
|
||||
/* This is needed for vxWorks 6.8 to prevent an obnoxious compiler warning */
|
||||
#define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
|
||||
|
||||
@@ -59,9 +59,12 @@ sub ParseDBD {
|
||||
\s* $RXstr \s* , \s*$RXstr \s* \)/oxgc) {
|
||||
print "Device: $1, $2, $3, $4\n" if $debug;
|
||||
my $rtyp = $dbd->recordtype($1);
|
||||
dieContext("Unknown record type '$1'")
|
||||
unless defined $rtyp;
|
||||
$rtyp->add_device(DBD::Device->new($2, $3, $4));
|
||||
if (!defined $rtyp) {
|
||||
$rtyp = DBD::Recordtype->new($1);
|
||||
warn "Device using undefined record type '$1', place-holder created\n";
|
||||
$dbd->add($rtyp);
|
||||
}
|
||||
$rtyp->add_device(DBD::Device->new($2, $3, $4));
|
||||
} else {
|
||||
last unless m/\G (.*) $/moxgc;
|
||||
dieContext("Syntax error in '$1'");
|
||||
|
||||
@@ -83,7 +83,9 @@ sub toCdefs {
|
||||
}
|
||||
|
||||
sub equals {
|
||||
my ($a, $b) = @_;
|
||||
my ($new, $known) = @_;
|
||||
return 0 if ! $known->fields;
|
||||
return 1 if ! $new->fields;
|
||||
dieContext("Duplicate definition of record type '$a->{NAME}'");
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ use EPICS::Path;
|
||||
use EPICS::Getopts;
|
||||
use Text::Wrap;
|
||||
|
||||
our ($opt_D, @opt_I, $opt_o);
|
||||
our ($opt_D, @opt_I, $opt_o, $opt_l);
|
||||
|
||||
getopts('Do:I@') or
|
||||
die "Usage: registerRecordDeviceDriver [-D] [-o out.c] [-I dir] in.dbd subname [TOP]";
|
||||
getopts('Dlo:I@') or
|
||||
die "Usage: registerRecordDeviceDriver [-D] [-l] [-o out.c] [-I dir] in.dbd subname [TOP]";
|
||||
|
||||
my @path = map { split /[:;]/ } @opt_I; # FIXME: Broken on Win32?
|
||||
|
||||
@@ -69,37 +69,52 @@ print $out (<< "END");
|
||||
#include "iocshRegisterCommon.h"
|
||||
#include "registryCommon.h"
|
||||
|
||||
END
|
||||
|
||||
print $out (<< "END") if $opt_l;
|
||||
#define epicsExportSharedSymbols
|
||||
#include "shareLib.h"
|
||||
|
||||
END
|
||||
|
||||
print $out (<< "END");
|
||||
extern "C" {
|
||||
|
||||
END
|
||||
|
||||
my %rectypes = %{$dbd->recordtypes};
|
||||
my @rtypnames;
|
||||
my @dsets;
|
||||
if (%rectypes) {
|
||||
my @rtypnames = sort keys %rectypes;
|
||||
my @allrtypnames = sort keys %rectypes;
|
||||
# Record types with no fields defined are declarations,
|
||||
# for building shared libraries containing device support.
|
||||
@rtypnames = grep { scalar $rectypes{$_}->fields } @allrtypnames;
|
||||
|
||||
# Declare the record support entry tables
|
||||
print $out wrap('epicsShareExtern rset ', ' ',
|
||||
join(', ', map {"*pvar_rset_${_}RSET"} @rtypnames)), ";\n\n";
|
||||
if (@rtypnames) {
|
||||
# Declare the record support entry tables
|
||||
print $out wrap('epicsShareExtern rset ', ' ',
|
||||
join(', ', map {"*pvar_rset_${_}RSET"} @rtypnames)), ";\n\n";
|
||||
|
||||
# Declare the RecordSizeOffset functions
|
||||
print $out "typedef int (*rso_func)(dbRecordType *pdbRecordType);\n";
|
||||
print $out wrap('epicsShareExtern rso_func ', ' ',
|
||||
join(', ', map {"pvar_func_${_}RecordSizeOffset"} @rtypnames)), ";\n\n";
|
||||
# Declare the RecordSizeOffset functions
|
||||
print $out "typedef int (*rso_func)(dbRecordType *pdbRecordType);\n";
|
||||
print $out wrap('epicsShareExtern rso_func ', ' ',
|
||||
join(', ', map {"pvar_func_${_}RecordSizeOffset"} @rtypnames)), ";\n\n";
|
||||
|
||||
# List of record type names
|
||||
print $out "static const char * const recordTypeNames[] = {\n";
|
||||
print $out wrap(' ', ' ', join(', ', map {"\"$_\""} @rtypnames));
|
||||
print $out "\n};\n\n";
|
||||
# List of record type names
|
||||
print $out "static const char * const recordTypeNames[] = {\n";
|
||||
print $out wrap(' ', ' ', join(', ', map {"\"$_\""} @rtypnames));
|
||||
print $out "\n};\n\n";
|
||||
|
||||
# List of pointers to each RSET and RecordSizeOffset function
|
||||
print $out "static const recordTypeLocation rtl[] = {\n";
|
||||
print $out join(",\n", map {
|
||||
" {pvar_rset_${_}RSET, pvar_func_${_}RecordSizeOffset}"
|
||||
} @rtypnames);
|
||||
print $out "\n};\n\n";
|
||||
# List of pointers to each RSET and RecordSizeOffset function
|
||||
print $out "static const recordTypeLocation rtl[] = {\n";
|
||||
print $out join(",\n", map {
|
||||
" {pvar_rset_${_}RSET, pvar_func_${_}RecordSizeOffset}"
|
||||
} @rtypnames);
|
||||
print $out "\n};\n\n";
|
||||
}
|
||||
|
||||
for my $rtype (@rtypnames) {
|
||||
for my $rtype (@allrtypnames) {
|
||||
my @devices = $rectypes{$rtype}->devices;
|
||||
for my $dtype (@devices) {
|
||||
my $dset = $dtype->name;
|
||||
@@ -206,7 +221,7 @@ print $out (<< 'END');
|
||||
|
||||
END
|
||||
|
||||
print $out (<< 'END') if %rectypes;
|
||||
print $out (<< 'END') if %rectypes && @rtypnames;
|
||||
registerRecordTypes(pbase, NELEMENTS(rtl), recordTypeNames, rtl);
|
||||
END
|
||||
|
||||
|
||||
Reference in New Issue
Block a user