Merge branch '7.0' into PSI-7.0

This commit is contained in:
2024-12-05 16:58:15 +01:00
71 changed files with 3807 additions and 875 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ USR_CPPFLAGS += -DUSE_TYPED_RSET -DUSE_TYPED_DSET
# Shared library ABI version.
SHRLIB_VERSION = $(EPICS_DATABASE_MAJOR_VERSION).$(EPICS_DATABASE_MINOR_VERSION).$(EPICS_DATABASE_MAINTENANCE_VERSION)
API_HEADER = dbCoreAPI.h
# dbCoreAPI.h generated earlier during libcom/
dbCore_API = dbCore
LIBRARY_IOC += dbCore
+2 -2
View File
@@ -20,7 +20,7 @@ BPT_DBD += bptTypeJdegF.dbd
BPT_DBD += bptTypeKdegC.dbd
BPT_DBD += bptTypeKdegF.dbd
ifneq (inc,$(strip $(MAKECMDGOALS)))
ifneq ($(filter-out inc,$(strip $(MAKECMDGOALS))),)
DBD += $(BPT_DBD)
endif
@@ -28,5 +28,5 @@ PROD_HOST += makeBpt
makeBpt_SRCS = makeBpt
DOCS += menuConvert.md
HTMLS += menuConvert.html
+6
View File
@@ -62,6 +62,12 @@ DBDINC += menuScan
DBDINC += dbCommon
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
DOCS += $(patsubst %.dbd.pod,%.md,$(dbMenusPod))
DOCS += dbCommonRecord.md
DOCS += dbCommonInput.md
DOCS += dbCommonOutput.md
HTMLS += $(patsubst %.dbd.pod,%.html,$(dbMenusPod))
HTMLS += dbCommonRecord.html
HTMLS += dbCommonInput.html
+52 -2
View File
@@ -62,8 +62,28 @@ DBCORE_API void post_event(int event);
DBCORE_API void scanAdd(struct dbCommon *);
DBCORE_API void scanDelete(struct dbCommon *);
DBCORE_API double scanPeriod(int scan);
DBCORE_API int scanOnce(struct dbCommon *);
DBCORE_API int scanOnceCallback(struct dbCommon *, once_complete cb, void *usr);
/** Shorthand for scanOnceCallback(prec, NULL, NULL)
*/
DBCORE_API int scanOnce(struct dbCommon *prec);
/** @brief scanOnce Request immediate record processing from another thread.
*
* Queue a request for record processing from the dedicated "Once" thread.
* Request may fail if Once queue overflows. See scanOnceSetQueueSize()
*
* @param prec Record to process
* @param cb Function called after target record dbProcess()
* Does not wait for async record completion.
* @param usr Argumentfor cb
* @return Zero on success. Non-zero if the request could not be queued.
*/
DBCORE_API int scanOnceCallback(struct dbCommon *prec, once_complete cb, void *usr);
/** @brief Set Once queue size
*
* Must be called prior to iocInit()
*
* @param size New size. May be smaller
* @return Zero on success
*/
DBCORE_API int scanOnceSetQueueSize(int size);
DBCORE_API int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result);
DBCORE_API void scanOnceQueueShow(const int reset);
@@ -77,9 +97,39 @@ DBCORE_API int scanpel(const char *event_name);
/*print io_event list*/
DBCORE_API int scanpiol(void);
/** @brief Initialize "I/O Intr" source
* @param ppios Pointer to scan list to be initialized
*
* Afterwards this IOSCANPVT may be assigned during a get_ioint_info() callback.
* See typed_dset::get_ioint_info()
*
* @note There is currently no way to free this allocation.
*/
DBCORE_API void scanIoInit(IOSCANPVT *ppios);
/** @brief Request processing of all associated records from callback threads
* @param pios The scan list
* @pre pios must be initialized by scanIoInit()
* @return
*/
DBCORE_API unsigned int scanIoRequest(IOSCANPVT pios);
/** @brief Process all records on the scan list for the specificed priority.
*
* Also executes the callback set by scanIoSetComplete()
*
* @param pios The scan list
* @param prio one of priorityLow through priorityHigh (defined in callback.h).
* A value between 0 and NUM_CALLBACK_PRIORITIES-1 .
* @return Zero if the scan list was empty or 1<<prio
* @since 3.16.0.1
*/
DBCORE_API unsigned int scanIoImmediate(IOSCANPVT pios, int prio);
/** @brief Set scan list completion callback
*
* Replace the callback which will be invoked after record processing begins.
* Asynchronous record processing may be ongoing.
*
* @since 3.15.0.2
*/
DBCORE_API void scanIoSetComplete(IOSCANPVT, io_scan_complete, void *usr);
#ifdef __cplusplus
@@ -17,7 +17,8 @@ C<MAYBE> or C<NO WAY> would not be accepted as choices for the field.
Also, the choices C<yes>, C<No>, and C<Yes> are not valid choices since they
don't match the case of C<NO> or C<YES>.
The integer values C<0> and C<1> may often be used instead however, they are
used as an index into the choices so C<0> becomes C<NO> and C<1> becomes <YES>.
used as an index into the choices so C<0> becomes C<NO> and C<1> becomes
C<YES>.
=menu menuYesNo
+1
View File
@@ -190,6 +190,7 @@ unsigned short recGblResetAlarms(void *precord)
if(strcmp(pdbc->namsg, pdbc->amsg)!=0) {
strcpy(pdbc->amsg, pdbc->namsg);
pdbc->namsg[0] = '\0';
stat_mask = DBE_ALARM;
}
+1 -1
View File
@@ -14,7 +14,7 @@ SRC_DIRS += $(IOCDIR)/dbtemplate
PROD_CMD += msi
msi_SRCS = msi.cpp
HTMLS += msi.html
DOCS += msi.md
INC += dbLoadTemplate.h
INC += dbtoolsIocRegister.h
@@ -1,445 +0,0 @@
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h1>msi: Macro Substitution and Include Tool</h1>
<h2>Introduction</h2>
<p>msi is a general purpose macro substitution/include tool. It accepts as input
an ascii template file. It looks for lines containing two reserved command
names: <tt>include</tt> and <tt>substitute</tt>. It also looks for and performs
substitutions on macros of the form $(var) and ${var}. It uses the macLib
routines from EPICS Base to perform the substitutions, so it also accepts the
default value and value definition syntax that macLib implements.</p>
<p>msi also allows substitutions to be specified via a separate substitution
file. This substitution file allows the same format as the substitution files
accepted by the EPICS IOC's dbLoadTemplate command.</p>
<h2>Command Syntax:</h2>
<pre>msi -V -g -D -o<i>outfile</i> -I<i>dir</i> -M<i>subs</i> -S<i>subfile</i> <i>template</i></pre>
<p>All parameters are optional. The -o, -I, -M, and -S switches may be
separated from their associated value string by spaces if desired. Output will
be written to stdout unless the -o option is given.</p>
<p>Switches have the following meanings:</p>
<dl>
<dt><tt>-V</tt></dt>
<dd>Verbose warnings; if this parameter is specified then any undefined or
recursive macros discovered in the template will be considered an error and
will be marked in the output file. An error message will be shown, and when
msi terminates it will do so with an exit status of 2.</dd>
<dt><tt>-g</tt></dt>
<dd>When this flag is given all macros defined in a substitution file will
have global scope and thus their values will persist until a new value is
given for this macro. This flag is provided for backwards compatibility as
this was the behavior of previous versions of msi, but it does not follow
common scoping rules and is discouraged.</dd>
<dt><tt>-D</tt></dt>
<dd>Output dependency information suitable for including by a Makefile to
stdout instead of performing the macro substitutions. The <tt>-o</tt> option
must be given to specify the target name for the dependency rules. Other
options should be given exactly as will be used in the macro substitution
process.</dd>
<dt><tt>-o</tt> <i>file</i></dt>
<dd>Output will be written to the specifed file rather than to the standard
output.</dd>
<dt><tt>-I</tt> <i>dir</i></dt>
<dd>This parameter, which may be repeated or contain a colon-separated (or
semi-colon separated on Windows) list of directory paths, specifies a search
path for include commands. For example:
<blockquote>
<pre>msi -I /home/mrk/examples:. -I.. template</pre>
</blockquote>
specifies that all named files should be searched for in the following
locations in the order given:
<ol>
<li><tt>/home/mrk/examples</tt></li>
<li><tt>.</tt> (the current directory)</li>
<li><tt>..</tt> (the parent of the current directory)</li>
</ol>
</dd>
<dt><tt>-M</tt> <i>substitutions</i></dt>
<dd>This parameter specifies macro values for the template instance.
Multiple macro values can be specified in one substitution parameter, or in
multiple <tt>-M</tt> parameters. For example:
<blockquote>
<pre>msi -M "a=aval,b=bval" -Mc=cval template</pre>
</blockquote>
specifies that in the template file each occurrence of:
<dl>
<dd><tt>$(a)</tt> or <tt>${a}</tt> is replaced by <tt>aval</tt></dd>
<dd><tt>$(b)</tt> or <tt>${b}</tt> is replaced by <tt>bval</tt></dd>
<dd><tt>$(c)</tt> or <tt>${c}</tt> is replaced by <tt>cval</tt></dd>
</dl>
</dd>
<dt><tt>-S</tt> <i>subfile</i></dt>
<dd>The substitution file. See below for format.</dd>
<dt><i>template</i></dt>
<dd> The input file. If no file is specified then input is taken from
stdin, i.e. msi can be used as a filter. See below for a description of
commands that can be embedded in the template file.</dd>
</dl>
<p>It is not possible to display usage by just typing <tt>msi</tt> since
executing the command with no arguments is a valid command. To show usage
specify an illegal switch, e.g.</p>
<blockquote>
<pre>msi -help</pre>
</blockquote>
<h2>Exit Status</h2>
<dl>
<dt>0<dd>Success.
<dt>1<dd>Can't open/create file, or other I/O error.
<dt>2<dd>Undefined macros encountered with the <tt>-V</tt> option specified.
</dl>
<h2>Template File Format</h2>
<p>This file contains the text to be read and written to the output after macro
substitution is performed. If no file is given then input is read from stdin.
Variable instances to be substituted by macro values are expressed in the
template using the syntax <tt>$(</tt><i>name</i><tt>)</tt> or
<tt>${</tt><i>name</i><tt>}</tt>. The template can also provide default values
to be used when a macro has not been given a value, using the syntax
<tt>$(</tt><i>name</i><tt>=</tt><i>default</i><tt>)</tt> or
<tt>${</tt><i>name</i><tt>=</tt><i>default</i><tt>}</tt>.</p>
<p>For example, using the command</p>
<blockquote>
<pre>msi -M name=Marty template</pre>
</blockquote>
<p>where the file template contains</p>
<blockquote>
<pre>My name is $(name)
My age is $(age=none of your business)</pre>
</blockquote>
<p>results in this output:</p>
<blockquote>
<pre>My name is Marty
My age is none of your business</pre>
</blockquote>
<p>Macro variables and their default values can be expressed in terms of other
macros if necessary, to almost any level of complexity. Recursive definitions
will generate warning messages on stderr and result in undefined output.</p>
<p>The template file is read and processed one line at a time, where the
maximum length of a line before and/or after macro expansion is 1023 characters
&mdash; longer input or output lines will cause msi to fail. Within the context
of a single line, macro expansion does not occur when the variable instance
appears inside a single-quoted string, or where the dollar sign <tt>$</tt> is
preceded by a back-slash character <tt>\</tt>, but as with the standard Unix
shells, variables inside double quoted strings are expanded properly.</p>
<p>However neither back-slash characters nor quotes of either variety are
removed when generating the output file, so depending on what is being output
the single quote behaviour may not be useful and may even be a hinderance. It
cannot be disabled in the current version of msi.</p>
<h3>Template file commands</h3>
<p>In addition to the regular text and variable instances described above, the
template file may also contain commands which allow the insertion of other
template files and the ability to set macro values inside the template file
itself. These commands are:</p>
<blockquote>
<pre>include "file"
substitute "var=value,var=value,..."</pre>
</blockquote>
<p>Lines containing commands must be in one of these forms:</p>
<ul>
<li><tt>include "</tt><i>filename</i><tt>"</tt></li>
<li><tt>substitute "</tt><i>name1=value1, name2=value2, ...</i><tt>"</tt></li>
</ul>
<p>White space is allowed before and after the command verb, and after the
quoted string. If embedded quotes are needed, the backslash character
<tt>\</tt> can be used as an escape character. For example</p>
<blockquote>
<pre>substitute "a=\"val\""</pre>
</blockquote>
<p>specifies that (unless <tt>a</tt> is subsequently redefined) wherever a
<tt>$(a)</tt> macro appears in the template below this point, the text
<tt>"val"</tt> (including the double quote characters) will appear in the
output instead.</p>
<p>If a line does match either syntax above it is just passed to macLib for
processing without any notification. Thus the input line:</p>
<blockquote>
<pre>include "myfile" #include file</pre>
</blockquote>
<p>would just be passed to macLib, i.e. it would <em>not</em> be considered an
include command.</p>
<p>As an example of these commands, let the Unix command be:</p>
<blockquote>
<pre>msi template</pre>
</blockquote>
<p>and file includeFile contain:</p>
<blockquote>
<pre>first name is ${first}
family name is ${family}</pre>
</blockquote>
<p>and template is</p>
<blockquote>
<pre>substitute "first=Marty,family=Kraimer"
include "includeFile"
substitute "first=Irma,family=Kraimer"
include "includeFile"</pre>
</blockquote>
<p>then the following is written to the output.</p>
<blockquote>
<pre>first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer</pre>
</blockquote>
<p>Note that the IOC's <tt>dbLoadTemplate</tt> command does not support the
<tt>substitute</tt> syntax in template files, although the <tt>include</tt>
syntax is supported.</p>
<h2>Substitution File Format</h2>
<p>The optional substitution file has three formats: regular, pattern, and
dbTemplate format. We will discuss each separately.</p>
<h3>Regular format</h3>
<blockquote>
<pre>global {gbl_var1=gbl_val1, gbl_var2=gbl_val2, ...}
{var1=set1_val1, var2=set1_val2, ...}
{var2=set2_val2, var1=set2_val1, ...}
global {gbl_var1=gbl_val3, gbl_var2=gbl_val4, ...}
{var1=set3_val1, var2=set3_val2, ...}
{var2=set4_val2, var1=set4_val1, ...}</pre>
</blockquote>
<p>The template file is output with macro substitutions performed once for each
set of braces containing macro replacement values.</p>
<h3>Pattern format</h3>
<blockquote>
<pre>global {gbl_var1=gbl_val1, gbl_var2=gbl_val2, ...}
pattern {var1, var2, ...}
{set1_val1, set1_val2, ...}
{set2_val1, set2_val2, ...}
pattern {var2, var1, ...}
global {gbl_var1=gbl_val3, gbl_var2=gbl_val4, ...}
{set3_val2, set3_val1, ...}
{set4_val2, set4_val2, ...}</pre>
</blockquote>
<p>This produces the same result as the regular format example above.</p>
<h3>dbLoadTemplate Format</h3>
<p>This format is an extension of the format accepted by the EPICS IOC command
<tt>dbLoadTemplate</tt>, and allows templates to be expanded on the host rather
by using dbLoadTemplate at IOC boot time.</p>
<blockquote>
<pre>global {gbl_var1=gbl_val1, gbl_var2=gbl_val2, ...}
file templatefile {
<i>pattern format or regular format</i>
}
file "${WHERE}/template2" {
<i>pattern format or regular format</i>
}</pre>
</blockquote>
<p>For the dbTemplate format, the template filename does not have to be given
on the command line, and is usually specified in the substitutions file
instead. If a template filename is given on the command line it will override
the filenames listed in the substitutions files.</p>
<h3>Syntax for all formats</h3>
<p>A comment line may appear anywhere in a substitution file, and will be
ignored. A comment line is any line beginning with the character <tt>#</tt>,
which must be the very first character on the line.</p>
<p>Global definitions may supplement or override the macro values supplied on
the command-line using the <tt>-M</tt> switch, and set default values that will
survive for the remainder of the file unless another global definition of the
same macro changes it.</p>
<p>For definitions within braces given in any of the file formats, a separator
must be given between items. A separator is either a comma, or one or more of
the standard white space characters (space, formfeed, newline, carriage return,
tab or vertical tab).</p>
<p>Each item within braces can be an alphanumeric token, or a double-quoted
string. A back-slash character <tt>\</tt> can be used to escape a quote
character needed inside a quoted string. These three sets of substitutions are
all equivalent:</p>
<blockquote>
<pre>{a=aa b=bb c="\"cc\""}
{b="bb",a=aa,c="\"cc\""}
{
c="\"cc\""
b=bb
a="aa"
}</pre>
</blockquote>
<p>Within a substitutions file, the file name may appear inside double quotation
marks; these are required if the name contains certain characters or environment
variable macros of the form ${ENV_VAR} or $(ENV_VAR), which will be expanded
before the file is opened.</p>
<h3>Regular substitution example</h3>
<p>Let the command be:</p>
<blockquote>
<pre>msi -S substitute template</pre>
</blockquote>
<p>The file <tt>template</tt> contains</p>
<blockquote>
<pre>first name is ${first}
family name is ${family}</pre>
</blockquote>
<p> and the file <tt>substitute</tt> is</p>
<blockquote>
<pre>global {family=Kraimer}
{first=Marty}
{first=Irma}</pre>
</blockquote>
<p>The following is the output produced:</p>
<blockquote>
<pre>first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer</pre>
</blockquote>
<h3>Pattern substitution example</h3>
<p>Let the command be:</p>
<blockquote>
<pre>msi -S pattern template</pre>
</blockquote>
<p>The file <tt>pattern</tt> contains</p>
<blockquote>
<pre>pattern {first,last}
{Marty,Kraimer}
{Irma,Kraimer}</pre>
</blockquote>
<p>and <tt>template</tt> is the same as the previous example:</p>
<blockquote>
<pre>first name is ${first}
family name is ${family}</pre>
</blockquote>
<p>This is the output:</p>
<blockquote>
<pre>first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer</pre>
</blockquote>
<h3>dbTemplate example</h3>
Let the command be
<blockquote>
<pre>msi -S xxx.substitutions</pre>
</blockquote>
<tt>xxx.substitutions</tt> is
<blockquote>
<pre>file template {
pattern {first,last}
{Marty,Kraimer}
{Irma,Kraimer}
pattern {last,first}
{Smith,Bill}
{Smith,Mary}
}
file template {
{first=Marty,last=Kraimer}
{first=Irma,last=Kraimer}
}</pre>
</blockquote>
<tt>template</tt> is the same as in the previous example..
<p>The following is written to the output</p>
<blockquote>
<pre>first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer
first name is Bill
last name is Smith
first name is Mary
last name is Smith
first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer</pre>
</blockquote>
</body>
</html>
+384
View File
@@ -0,0 +1,384 @@
# msi: Macro Substitution and Include Tool
(msitool)=
## Introduction
msi is a general purpose macro substitution/include tool.
It accepts as input an ascii template file. It looks for lines containing two reserved
command names: `include` and `substitute`. It also looks for and performs
substitutions on macros of the form `$(var)` and `${var}`. It uses the
macLib routines from EPICS Base to perform the substitutions, so it also
accepts the default value and value definition syntax that macLib
implements.
msi also allows substitutions to be specified via a separate
substitution file. This substitution file allows the same format as the
substitution files accepted by the EPICS IOC's dbLoadTemplate command.
## Command Syntax
`msi -V -g -o outfile -I dir -M subs -S subfile template`
All parameters are optional. The -o, -I, -M, and -S switches may be
separated from their associated value string by spaces if desired.
Output will be written to stdout unless the -o option is given.
Switches have the following meanings:
- **-V**
Verbose warnings; if this parameter is specified then any undefined
macro discovered in the template file which does not have an
associated default value is considered an error. An error message is
generated, and when msi terminates it will do so with an exit status
of 2.
- **-g**
When this flag is given all macros defined in a substitution file
will have global scope and thus their values will persist until a
new value is given for this macro. This flag is provided for
backwards compatibility as this was the behavior of previous
versions of msi, but it does not follow common scoping rules and is
discouraged.
- **-o _file_**
Output will be written to the specifed file rather than to the
standard output.
- **-I _dir_**
This parameter, which may be repeated or contain a colon-separated
(or semi-colon separated on Windows) list of directory paths,
specifies a search path for include commands. For example:
msi -I /home/mrk/examples:. -I.. template
specifies that all named files should be searched for in the following locations,
in the order given:
1. /home/mrk/examples
2. . (the current directory)
3. .. (the parent of the current directory)
- **-M _substitutions_**
This parameter specifies macro values for the template instance.
Multiple macro values can be specified in one substitution
parameter, or in multiple -M parameters. For example:
msi -M "a=aval,b=bval" -Mc=cval template
specifies that in the template file each occurrence of:
- `$(a)` or `${a}` is replaced by _aval_
- `$(b)` or `${b}` is replaced by _bval_
- `$(c)` or `${c}` is replaced by _cval_
- **-S _subfile_**
The substitution file. See below for format.
- **_template_**
The input file. If no file is specified then input is taken from
stdin, i.e. msi can be used as a filter. See below for a description
of commands that can be embedded in the template file.
It is not possible to display usage by just typing msi since executing
the command with no arguments is a valid command. To show usage specify
an illegal switch, e.g.
msi -help
## Exit Status
- **0**
Success.
- **1**
Can't open/create file, or other I/O error.
- **2**
Undefined macros encountered with the -V option specified.
## Template File Format
This file contains the text to be read and written to the output after
macro substitution is performed. If no file is given then input is read
from stdin. Variable instances to be substituted by macro values are
expressed in the template using the syntax \$(_name_) or \${_name_}. The
template can also provide default values to be used when a macro has not
been given a value, using the syntax \$(_name_=_default_) or \${_name_=_default_}.
For example, using the command
msi -M name=Marty template
where the file template contains
My name is $(name)
My age is $(age=none of your business)
results in this output:
My name is Marty
My age is none of your business
Macro variables and their default values can be expressed in terms of
other macros if necessary, to almost any level of complexity. Recursive
definitions will generate warning messages on stderr and result in
undefined output.
The template file is read and processed one line at a time, where the
maximum length of a line before and/or after macro expansion is 1023
characters; longer input or output lines will cause msi to fail. Within
the context of a single line, macro expansion does not occur when the
variable instance appears inside a single-quoted string, or where the
dollar sign $ is preceded by a back-slash character \, but as with the
standard Unix shells, variables inside double quoted strings are
expanded properly.
However neither back-slash characters nor quotes of either variety are
removed when generating the output file, so depending on what is being
output the single quote behaviour may not be useful and may even be a
hinderance. It cannot be disabled in the current version of msi.
### Template file commands
In addition to the regular text and variable instances described above,
the template file may also contain commands which allow the insertion of
other template files and the ability to set macro values inside the
template file itself. These commands are:
include "file"
substitute "var=value,var=value,..."
Lines containing commands must be in one of these forms:
- include "_filename_"
- substitute "_name1=value1, name2=value2, ..._"
White space is allowed before and after the command verb, and after the
quoted string. If embedded quotes are needed, the backslash character \
can be used as an escape character. For example
substitute "a=\"val\""
specifies that (unless a is subsequently redefined) wherever a $(a)
macro appears in the template below this point, the text
"val" (including the double quote characters) will appear in the output
instead.
If a line does match either syntax above it is just passed to macLib for
processing without any notification. Thus the input line:
include "myfile" #include file
would just be passed to macLib, i.e. it would _not_ be considered an
include command.
As an example of these commands, let the Unix command be:
msi template
and file includeFile contain:
first name is ${first}
family name is ${family}
and template is
substitute "first=Marty,family=Kraimer"
include "includeFile"
substitute "first=Irma,family=Kraimer"
include "includeFile"
then the following is written to the output.
first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer
Note that the IOC's dbLoadTemplate command does not support the
substitute syntax in template files, although the include syntax is
supported.
## Substitution File Format
The optional substitution file has three formats: regular, pattern, and
dbTemplate format. We will discuss each separately.
### Regular format
global {gbl_var1=gbl_val1, gbl_var2=gbl_val2, ...}
{var1=set1_val1, var2=set1_val2, ...}
{var2=set2_val2, var1=set2_val1, ...}
global {gbl_var1=gbl_val3, gbl_var2=gbl_val4, ...}
{var1=set3_val1, var2=set3_val2, ...}
{var2=set4_val2, var1=set4_val1, ...}
The template file is output with macro substitutions performed once for
each set of braces containing macro replacement values.
### Pattern format
global {gbl_var1=gbl_val1, gbl_var2=gbl_val2, ...}
pattern {var1, var2, ...}
{set1_val1, set1_val2, ...}
{set2_val1, set2_val2, ...}
pattern {var2, var1, ...}
global {gbl_var1=gbl_val3, gbl_var2=gbl_val4, ...}
{set3_val2, set3_val1, ...}
{set4_val2, set4_val2, ...}
This produces the same result as the regular format example above.
### dbLoadTemplate Format
This format is an extension of the format accepted by the EPICS IOC
command dbLoadTemplate, and allows templates to be expanded on the host
rather by using dbLoadTemplate at IOC boot time.
global {gbl_var1=gbl_val1, gbl_var2=gbl_val2, ...}
file templatefile {
/pattern format or regular format/
}
file "${WHERE}/template2" {
/pattern format or regular format/
}
For the dbTemplate format, the template filename does not have to be
given on the command line, and is usually specified in the substitutions
file instead. If a template filename is given on the command line it
will override the filenames listed in the substitutions files.
### Syntax for all formats
A comment line may appear anywhere in a substitution file, and will be
ignored. A comment line is any line beginning with the character #,
which must be the very first character on the line.
Global definitions may supplement or override the macro values supplied
on the command-line using the -M switch, and set default values that
will survive for the remainder of the file unless another global
definition of the same macro changes it.
For definitions within braces given in any of the file formats, a
separator must be given between items. A separator is either a comma, or
one or more of the standard white space characters (space, formfeed,
newline, carriage return, tab or vertical tab).
Each item within braces can be an alphanumeric token, or a double-quoted
string. A back-slash character \ can be used to escape a quote character
needed inside a quoted string. These three sets of substitutions are all
equivalent:
{a=aa b=bb c="\"cc\""}
{b="bb",a=aa,c="\"cc\""}
{
c="\"cc\""
b=bb
a="aa"
}
Within a substitutions file, the file name may appear inside double
quotation marks; these are required if the name contains certain
characters or environment variable macros of the form `${ENV_VAR}` or
`$(ENV_VAR)`, which will be expanded before the file is opened.
### Regular substitution example
Let the command be:
msi -S substitute template
The file template contains
first name is ${first}
family name is ${family}
and the file `substitute` is
global {family=Kraimer}
{first=Marty}
{first=Irma}
The following is the output produced:
first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer
### Pattern substitution example
Let the command be:
msi -S pattern template
The file pattern contains
pattern {first,last}
{Marty,Kraimer}
{Irma,Kraimer}
and template is the same as the previous example:
first name is ${first}
family name is ${family}
This is the output:
first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer
### dbTemplate example
Let the command be
msi -S xxx.substitutions
`xxx.substitutions` is
file template {
pattern {first,last}
{Marty,Kraimer}
{Irma,Kraimer}
pattern {last,first}
{Smith,Bill}
{Smith,Mary}
}
file template {
{first=Marty,last=Kraimer}
{first=Irma,last=Kraimer}
}
`template` is the same as in the previous example.
The following is written to the output
first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer
first name is Bill
last name is Smith
first name is Mary
last name is Smith
first name is Marty
family name is Kraimer
first name is Irma
family name is Kraimer
@@ -0,0 +1,96 @@
# IOC Component Reference
This document provides reference information about the record types,
menus, link types and channel filters included with EPICS Base.
## Introduction and IOC Concepts
- [Introduction to EPICS](https://docs.epics-controls.org/en/latest/getting-started/EPICS_Intro.html)
- [Process Database Concepts](https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html)
## Record Type Definitions
These sections describe common aspects of the record types:
```{toctree}
:titlesonly:
dbCommonRecord
dbCommonInput
dbCommonOutput
```
These are the record types supplied with EPICS Base:
```{toctree}
:titlesonly:
aaiRecord
aaoRecord
aiRecord
aoRecord
aSubRecord
biRecord
boRecord
calcoutRecord
calcRecord
compressRecord
dfanoutRecord
eventRecord
fanoutRecord
histogramRecord
int64inRecord
int64outRecord
longinRecord
longoutRecord
lsiRecord
lsoRecord
mbbiDirectRecord
mbbiRecord
mbboDirectRecord
mbboRecord
permissiveRecord
printfRecord
selRecord
seqRecord
stateRecord
stringinRecord
stringoutRecord
subArrayRecord
subRecord
waveformRecord
```
## Menu Definitions
Menu field choices are documented with the record type that defines them, or
here for the global menus that are used by multiple record types:
```{toctree}
:titlesonly:
menuAlarmSevr
menuAlarmStat
menuConvert
menuFtype
menuIvoa
menuOmsl
menuPini
menuPost
menuPriority
menuScan
menuSimm
menuYesNo
```
## Other Components
EPICS Base also comes with extensible sets of server Channel Filters and IOC
Database Link types, which are documented here:
```{toctree}
:titlesonly:
filters
links
```
@@ -0,0 +1,170 @@
=head1 EPICS Component Reference Manual
This document provides reference information about the record types,
menus, link types and channel filters included with EPICS Base.
Many details about the record and menu definitions are derived automatically
from the source code at build time.
=head2 Introduction and IOC Concepts
These links point to an external website where introductory and overview
documentation is now being published.
=over
=item * L<Introduction to EPICS|https://docs.epics-controls.org/en/latest/guides/EPICS_Intro.html>
=item * L<Process Database Concepts|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html>
=back
=head2 Record Type Definitions
These sections describe common aspects of the record types:
=over
=item * L<Fields Common to All Record Types|dbCommonRecord>
=item * L<Fields Common to Input Record Types|dbCommonInput>
=item * L<Fields Common to Output Record Types|dbCommonOutput>
=back
These are the record types supplied with EPICS Base:
=over
=item * L<Analog Array Input Record (aai)|aaiRecord>
=item * L<Analog Array Output Record (aao)|aaoRecord>
=item * L<Analog Input Record (ai)|aiRecord>
=item * L<Analog Output Record (ao)|aoRecord>
=item * L<Array Subroutine Record (aSub)|aSubRecord>
=item * L<Binary Input Record (bi)|biRecord>
=item * L<Binary Output Record (bo)|boRecord>
=item * L<Calculation Output Record (calcout)|calcoutRecord>
=item * L<Calculation Record (calc)|calcRecord>
=item * L<Compression Record (compress)|compressRecord>
=item * L<Data Fanout Record (dfanout)|dfanoutRecord>
=item * L<Event Record (event)|eventRecord>
=item * L<Fanout Record (fanout)|fanoutRecord>
=item * L<Histogram Record (histogram)|histogramRecord>
=item * L<64-bit Integer Input Record (int64in)|int64inRecord>
=item * L<64-bit Integer Output Record (int64out)|int64outRecord>
=item * L<Long Input Record (longin)|longinRecord>
=item * L<Long Output Record (longout)|longoutRecord>
=item * L<Long String Input Record (lsi)|lsiRecord>
=item * L<Long String Output Record (lso)|lsoRecord>
=item * L<Multi-Bit Binary Input Direct Record (mbbiDirect)|mbbiDirectRecord>
=item * L<Multi-Bit Binary Input Record (mbbi)|mbbiRecord>
=item * L<Multi-Bit Binary Output Direct Record (mbboDirect)|mbboDirectRecord>
=item * L<Multi-Bit Binary Output Record (mbbo)|mbboRecord>
=item * L<Permissive Record (permissive)|permissiveRecord>
=item * L<Printf Record (printf)|printfRecord>
=item * L<Select Record (sel)|selRecord>
=item * L<Sequence Record (seq)|seqRecord>
=item * L<State Record (state)|stateRecord>
=item * L<String Input Record (stringin)|stringinRecord>
=item * L<String Output Record (stringout)|stringoutRecord>
=item * L<Sub-Array Record (subArray)|subArrayRecord>
=item * L<Subroutine Record (sub)|subRecord>
=item * L<Waveform Record (waveform)|waveformRecord>
=back
=head2 Menu Definitions
Menu field choices are documented with the record type that defines them, or
here for the global menus that are used by multiple record types:
=over
=item * L<Alarm Severity Menu|menuAlarmSevr>
=item * L<Alarm Status Menu|menuAlarmStat>
=item * L<Analog Conversions Menu|menuConvert>
=item * L<Field Type Menu|menuFtype>
=item * L<Invalid Value Output Action Menu|menuIvoa>
=item * L<Output Mode Select Menu|menuOmsl>
=item * L<Process at iocInit Menu|menuPini>
=item * L<Post Monitors Menu|menuPost>
=item * L<Priority Menu|menuPriority>
=item * L<Scan Menu|menuScan>
=item * L<Simulation Mode Menu|menuSimm>
=item * L<YesE<sol>No Menu|menuYesNo>
=back
=head2 Other Components
EPICS Base also comes with extensible sets of server Channel Filters and IOC
Database Link types, which are documented here:
=over
=item * L<Channel Filters|filters>
=item * L<IOC Database Link Types|links>
=back
=head2 Corrections and Updates
Corrections to these documents can be submitted as patch files to the EPICS
core developers, or as GitHub pull requests to the 7.0 branch of Base.
These document sources can be found under C<modules/database/src> tree, mostly
in the C<std/rec> and C<ioc/db> directories in files with extension C<.dbd.pod>.
The documentation source format is a combination of the EPICS DBD file format
with an extended version of Perl's POD (plain old documentation); run
C<perldoc pod> for details of POD.
+3
View File
@@ -30,6 +30,9 @@ include $(STDDIR)/filters/Makefile
include $(STDDIR)/link/Makefile
include $(STDDIR)/softIoc/Makefile
DOCS += ComponentReference.md
HTMLS += ComponentReference.html
include $(TOP)/configure/RULES
include $(STDDIR)/rec/RULES
+1 -1
View File
@@ -18,5 +18,5 @@ dbRecStd_SRCS += sync.c
dbRecStd_SRCS += decimate.c
dbRecStd_SRCS += utag.c
DOCS += filters.md
HTMLS += filters.html
+1
View File
@@ -16,4 +16,5 @@ dbRecStd_SRCS += lnkCalc.c
dbRecStd_SRCS += lnkState.c
dbRecStd_SRCS += lnkDebug.c
DOCS += links.md
HTMLS += links.html
+5
View File
@@ -54,8 +54,13 @@ stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords))
dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords))
DOCS += $(patsubst %.dbd.pod,%.md,$(notdir $(wildcard ../rec/*Record.dbd.pod)))
HTMLS += $(patsubst %.dbd.pod,%.html,$(notdir $(wildcard ../rec/*Record.dbd.pod)))
vpath %.png $(SRC_DIRS)
DOCS += image/compress-1.png
DOCS += image/compress-2.png
HTMLS += image/compress-1.png
HTMLS += image/compress-2.png
+1
View File
@@ -34,6 +34,7 @@ PERL_SCRIPTS += dbdToRecordtypeH.pl
PERL_SCRIPTS += dbdExpand.pl
PERL_SCRIPTS += dbExpand.pl
PERL_SCRIPTS += dbdToHtml.pl
PERL_SCRIPTS += dbdToMD.pl
PERL_SCRIPTS += registerRecordDeviceDriver.pl
HTMLS += dbdToHtml.html
+307
View File
@@ -0,0 +1,307 @@
#!/usr/bin/env perl
#*************************************************************************
# Copyright (c) 2012 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.
#*************************************************************************
use strict;
use FindBin qw($Bin);
use lib ("$Bin/../../lib/perl");
use DBD;
use DBD::Parser;
use EPICS::Getopts;
use EPICS::macLib;
use EPICS::PodMD;
use EPICS::Readfile;
use Pod::Usage;
=head1 NAME
dbdToMD.pl - Convert DBD file with POD to Markdown
=head1 SYNOPSIS
B<dbdToMD.pl> [B<-h>] [B<-D>] [B<-I> dir] [B<-o> file] file.dbd.pod
=head1 DESCRIPTION
Generates MArkdown documentation from a B<.dbd.pod> file.
=head1 OPTIONS
B<dbdToMD.pl> understands the following options:
=over 4
=item B<-h>
Help, display usage information.
=item B<-H>
Conversion help, display information about converting reference documentation
from the EPICS Wiki into a B<.dbd.pod> file for use with this tool.
=item B<-I>
Path to look for include files.
=item B<-o> file
Name of the output file to be created.
=back
If no output filename is set, the file created will be named after the input
file, removing any directory components in the path and replacing any
B<.dbd.pod> file extension with B<.md>.
=cut
our ($opt_h, $opt_H, @opt_I, $opt_o);
my $tool = 'dbdToMD.pl';
getopts('hHI@o:') or
pod2usage(2);
pod2usage(-verbose => 2) if $opt_H;
pod2usage(1) if $opt_h;
pod2usage("$tool: No input file given.\n") if @ARGV != 1;
my $dbd = DBD->new();
my $infile = shift @ARGV;
$infile =~ m/\.dbd.pod$/ or
pod2usage("$tool: Input file '$infile' must have '.dbd.pod' extension.\n");
ParseDBD($dbd, Readfile($infile, 0, \@opt_I));
if (!$opt_o) {
($opt_o = $infile) =~ s/\.dbd\.pod$/.md/;
$opt_o =~ s/^.*\///;
$opt_o =~ s/dbCommonRecord/dbCommon/;
}
(my $title = $opt_o) =~ s/\.md$//;
open my $out, '>', $opt_o or
die "Can't create $opt_o: $!\n";
$SIG{__DIE__} = sub {
die @_ if $^S; # Ignore eval deaths
close $out;
unlink $opt_o;
};
sub make_fragment {
my $fragment = $_[1];
$fragment =~ s/\W+/-/g;
$fragment = lc($fragment);
$_[1] = $fragment;
}
my $podRst = EPICS::PodMD->new(
perldoc_url_prefix => '',
perldoc_fragment_format => make_fragment,
markdown_fragment_format => make_fragment,
);
# Parse the Pod text from the root DBD object
my $pod = join "\n",
map {
# Handle a 'recordtype' Pod directive
if (m/^ =recordtype \s+ (\w+) /x) {
my $rn = $1;
my $rtyp = $dbd->recordtype($rn);
die "Unknown recordtype '$rn' in $infile POD directive\n"
unless $rtyp;
rtypeToMD($rtyp, $dbd);
}
# Handle a 'menu' Pod directive
elsif (m/^ =menu \s+ (\w+) /x) {
my $mn = $1;
my $menu = $dbd->menu($mn);
die "Unknown menu '$mn' in $infile POD directive\n"
unless $menu;
menuToMD($menu);
}
elsif (m/^ =title \s+ (.*)/x) {
$title = $1;
"=head1 $title";
}
else {
$_;
}
} $dbd->pod;
$podRst->output_fh($out);
$podRst->parse_string_document($pod);
close $out;
sub menuToMD {
my ($menu) = @_;
my $index = 0;
return "| Index | Identifier | Choice String |",
"| ----- | ---------- | ------------- |",
map({choiceTableRow($_, $index++)} $menu->choices);
}
sub choiceTableRow {
my ($ch, $index) = @_;
my ($id, $name) = @{$ch};
return "| $index | $id | $name |";
}
sub rtypeToMD {
my ($rtyp, $dbd) = @_;
return map {
# Handle a 'fields' Pod directive
if (m/^ =fields \s+ (\w+ (?:\s* , \s* \w+ )* )/x) {
my @names = split /\s*,\s*/, $1;
# Look up the named fields
my @fields = map {
my $field = $rtyp->field($_);
die "Unknown field name '$_' in $infile POD\n"
unless $field;
$field;
} @names;
# Generate Pod for the table
"| Field | Summary | Type | DCT | Default | Read | Write | CA PP |",
"| ----- | ------- | ---- | --- | ------- | ---- | ----- | ----- |",
map({fieldTableRow($_, $dbd)} @fields);
}
# Handle a 'menu' Pod directive
elsif (m/^ =menu \s+ (\w+) /x) {
my $mn = $1;
my $menu = $dbd->menu($mn);
die "Unknown menu '$mn' in $infile POD directive\n"
unless $menu;
menuToMD($menu);
}
else {
# Raw text line
$_;
}
} $rtyp->pod;
}
sub fieldTableRow {
my ($fld, $dbd) = @_;
my @md;
push @md, $fld->name, $fld->attribute('prompt');
my $type = $fld->public_type;
if ($type eq 'STRING') {
$type .= ' [' . $fld->attribute('size') . ']';
} elsif ($type eq 'MENU') {
my $mn = $fld->attribute('menu');
my $menu = $dbd->menu($mn);
my $mnl = lc($mn);
my $url = $menu ? "/menu-$mnl" : "${mn}.md";
#just pass a L directive for the parser
$type .= " L<$mn|$url>";
}
push @md, $type;
push @md, $fld->attribute('promptgroup') ? 'Yes' : 'No';
push @md, $fld->attribute('initial') || ' ';
push @md, $fld->readable;
push @md, $fld->writable;
push @md, $fld->attribute('pp') eq 'TRUE' ? 'Yes' : 'No';
return '| ' . join(' | ', @md) . ' |';
}
# Native type presented to dbAccess users
sub DBD::Recfield::public_type {
my $fld = shift;
m/^ =type \s+ (.+) /x && return $1 for $fld->comments;
my $type = $fld->dbf_type;
$type =~ s/^DBF_//;
return $type;
}
# Check if this field is readable
sub DBD::Recfield::readable {
my $fld = shift;
m/^ =read \s+ (?i) (Yes|No) /x && return $1 for $fld->comments;
return 'Probably'
if $fld->attribute('special') eq "SPC_DBADDR";
return $fld->dbf_type eq 'DBF_NOACCESS' ? 'No' : 'Yes';
}
# Check if this field is writable
sub DBD::Recfield::writable {
my $fld = shift;
m/^ =write \s+ (?i) (Yes|No) /x && return $1 for $fld->comments;
my $special = $fld->attribute('special');
return 'No'
if $special eq "SPC_NOMOD";
return 'Maybe'
if $special eq "SPC_DBADDR";
return $fld->dbf_type eq "DBF_NOACCESS" ? 'No' : 'Yes';
}
=pod
=head1 Converting Wiki Record Reference to POD
If you open the src/std/rec/aiRecord.dbd.pod file in your favourite plain text
editor you'll see what input was required to generate the aiRecord.html file.
The text markup language we're using is a standard called POD (Plain Old
Documentation) which is used by Perl developers, but you don't need to know Perl
at all to be able to use it.
When we add POD markup to a record type, we rename its *Record.dbd file to
.dbd.pod in the src/std/rec directory; no other changes are needed for the build
system to find it by its new name. The POD content is effectively just a new
kind of comment that appears in .dbd.pod files, which the formatter knows how to
convert into Markdown. The build also generates a plain *Record.dbd file from this
same input file by stripping out all of the POD markup.
Documentation for Perl's POD markup standard can be found online at
L<https://perldoc.perl.org/perlpod.html> or you may be able to type 'perldoc
perlpod' into a Linux command-line to see the same text. We added a few POD
keywords of our own to handle the table generation, and I'll cover those briefly
below.
POD text can appear almost anywhere in a dbd.pod file. It always starts with a
line "=[keyword] [additional text...]" where [keyword] is "title", "head1"
through "head4" etc.. The POD text ends with a line "=cut". There must be a
blank line above every POD line, and in many cases below it as well.
The POD keywords we have added are "title", "recordtype", "menu", "fields",
"type", "read" and "write". The last 3 are less common but are used in some of
the other record types such as the waveform and aSub records.
The most interesting of our new keywords is "fields", which takes a list of
record field names on the same line after the keyword and generates an Markdown
Table describing those fields based on the field description found in the DBD
parts. In the ai documentation the first such table covers the DTYP and INP
fields.
Note that the "=fields" line must appear inside the DBD's declaration of the
record type, i.e. after the line
recordtype(ai) {
The "type", "read" and "write" POD keywords are used inside an individual record
field declaration and provide information for the "Type", "Read" and "Write"
columns of the field's table output for fields where this information is
normally supplied by the record support code. Usage examples for these keywords
can be found in the aai and aSub record types.
If you look at the L<aoRecord.dbd.pod> file you'll see that the POD there starts
by documenting a record-specific menu definition. The "menu" keyword generates a
table that lists all the choices found in the named menu. Any MENU fields in the
field tables that refer to a locally-defined menu will generate a link to a
document section which must be titled "Menu [menuName]".
=cut