EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: gen_iocsh_reg.pl
From: "Johnson, Andrew N. via Tech-talk" <[email protected]>
To: Benjamin Franksen <[email protected]>, EPICS Techtalk <[email protected]>
Date: Mon, 29 Apr 2019 17:11:31 +0000
I have long considered that a good way to register commands would be to
define them in a DBD file with some new syntax/keywords, and provide a
tool that generates the necessary code at build time as a .c or .cpp
file. I have never looked at implementing this, but Ben's script shows
the possibilities. If anyone is interested in tackling that approach I
would be happy to discuss what would need to be done.

- Andrew


On 4/29/19 9:12 AM, Michael Davidsaver via Tech-talk wrote:
> This reminds me.  I added a boilerplate reduction helper
> in the pvAccessCPP module.  This has now appeared in several
> epics 7.0 releases.
>
> Usage looks like:
>
>> #include <pv/iocshelper.h>
>> void startPVAServer(const char *names) ...
>> ...
>> void someRegistar() {
>>   epics::iocshRegister<const char*, &startPVAServer>("startPVAServer", "provider names");
> Ugly, still somewhat repetitive ('const char*' appears twice),
> and currently only for functions with between 0 and 3 arguments
> due to the limitations of c++98.
>
> https://github.com/epics-base/pvAccessCPP/blob/master/src/ioc/pv/iocshelper.h
>
>
> On 4/26/19 8:44 AM, Benjamin Franksen via Tech-talk wrote:
>> I recently wrote this little perl script (attached) to automate the
>> writing of iocsh registration code using a trivial but (I think)
>> complete declarative specification "language" that is easy to compose on
>> the command line or in a Makefile. I am posting the code and an example
>> of what it does in the hope that it may turn out to be useful for others.
>>
>> Here is the help output (slightly re-formatted for this email):
>>
>> """
>>> gen_iocsh_reg.pl -h
>> Usage: gen_iocsh_reg.pl [REG=<registrar>] <command>=[<args>] ...
>> where
>>   <registrar> is the name of a C function to register the commands (if
>>     not specified you'll have to call iocshRegister yourself for each
>>     command)
>>   <command> is the name of a command (in C as well as in the shell)
>>   <args> is a comma separated list of argument descriptions <arg>
>>   <arg> describes an argument to the underlying C command and is either
>>     * a constant literal value (for instance 0 or "a string"), or
>>     * an iocsh argument description of the form <name>:<type> (for
>>       instance card_number:Int) where <type> is one of {Int, Double,
>>       String}.
>> Only arguments of the <name>:<type> sort are exposed as arguments to the
>> command in the shell.
>> """
>>
>> Here is a real-world example use case,. This is from a Makefile in one
>> of our projects:
>>
>> """
>> iocshExtra.c:
>>         $(PERL) $(BII_SCRIPTS_BIN)/gen_iocsh_reg.pl REG=registerIocshExtra\
>>          asDump=0,0,verbosity:Int \
>>          bootShow= bootChange= \
>>          gevShow= gevDelete=name:String
>> gevUpdate=name:String,value:String > $@
>> """
>>
>> From this it generates the following boilerplate code:
>>
>> """
>> /*
>>  * IOC shell command registration
>>  */
>>
>> #include "epicsExport.h"
>> #include "iocsh.h"
>>
>> static const iocshArg asDumpArg0 = { "verbosity", iocshArgInt };
>> static const iocshArg *const asDumpArgs[] = {
>>     &asDumpArg0
>> };
>> static const iocshFuncDef asDumpDef = {"asDump", 1, asDumpArgs};
>> static void asDumpWrapper(const iocshArgBuf *args) {
>>     asDump(0, 0, args[0].ival);
>> }
>>
>> static const iocshArg *const bootChangeArgs[] = {};
>> static const iocshFuncDef bootChangeDef = {"bootChange", 0, bootChangeArgs};
>> static void bootChangeWrapper(const iocshArgBuf *args) {
>>     bootChange();
>> }
>>
>> static const iocshArg *const bootShowArgs[] = {};
>> static const iocshFuncDef bootShowDef = {"bootShow", 0, bootShowArgs};
>> static void bootShowWrapper(const iocshArgBuf *args) {
>>     bootShow();
>> }
>>
>> static const iocshArg gevDeleteArg0 = { "name", iocshArgString };
>> static const iocshArg *const gevDeleteArgs[] = {
>>     &gevDeleteArg0
>> };
>> static const iocshFuncDef gevDeleteDef = {"gevDelete", 1, gevDeleteArgs};
>> static void gevDeleteWrapper(const iocshArgBuf *args) {
>>     gevDelete(args[0].sval);
>> }
>>
>> static const iocshArg *const gevShowArgs[] = {};
>> static const iocshFuncDef gevShowDef = {"gevShow", 0, gevShowArgs};
>> static void gevShowWrapper(const iocshArgBuf *args) {
>>     gevShow();
>> }
>>
>> static const iocshArg gevUpdateArg0 = { "name", iocshArgString };
>> static const iocshArg gevUpdateArg1 = { "value", iocshArgString };
>> static const iocshArg *const gevUpdateArgs[] = {
>>     &gevUpdateArg0,
>>     &gevUpdateArg1
>> };
>> static const iocshFuncDef gevUpdateDef = {"gevUpdate", 2, gevUpdateArgs};
>> static void gevUpdateWrapper(const iocshArgBuf *args) {
>>     gevUpdate(args[0].sval, args[1].sval);
>> }
>>
>> static void registerIocshExtra(void) {
>>     static int firstTime = 1;
>>     if (firstTime) {
>>         firstTime = 0;
>>         iocshRegister(&asDumpDef, asDumpWrapper);
>>         iocshRegister(&bootChangeDef, bootChangeWrapper);
>>         iocshRegister(&bootShowDef, bootShowWrapper);
>>         iocshRegister(&gevDeleteDef, gevDeleteWrapper);
>>         iocshRegister(&gevShowDef, gevShowWrapper);
>>         iocshRegister(&gevUpdateDef, gevUpdateWrapper);
>>     }
>> }
>> epicsExportRegistrar(registerIocshExtra);
>> """
>>
>> Cheers
>> Ben
>>
>

-- 
Complexity comes for free, Simplicity you have to work for.


References:
gen_iocsh_reg.pl Benjamin Franksen via Tech-talk
Re: gen_iocsh_reg.pl Michael Davidsaver via Tech-talk

Navigate by Date:
Prev: Re: Stopping IOC boot on failure to load database Johnson, Andrew N. via Tech-talk
Next: Re: Pmac Slits Davis, Mark via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: gen_iocsh_reg.pl Michael Davidsaver via Tech-talk
Next: MasarService run error =?gb18030?b?MTIz?= via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
ANJ, 29 Apr 2019 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·