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  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 
<== Date ==> <== Thread ==>

Subject: gen_iocsh_reg.pl
From: Benjamin Franksen via Tech-talk <tech-talk@aps.anl.gov>
To: EPICS Techtalk <tech-talk@aps.anl.gov>
Date: Fri, 26 Apr 2019 17:44:32 +0200
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

Attachment: gen_iocsh_reg.pl
Description: Perl program

Attachment: signature.asc
Description: OpenPGP digital signature


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

Navigate by Date:
Prev: Re: GPIB replies lost? Benjamin Franksen via Tech-talk
Next: Re: gen_iocsh_reg.pl Benjamin Franksen 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 
Navigate by Thread:
Prev: RE: A call to 'assert(dbLockIsInitialized)' by thread '_main_' [SOLVED] Iain Marcuson via Tech-talk
Next: Re: gen_iocsh_reg.pl Benjamin Franksen 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 
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 ·