EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

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

Subject: Re: macro substitution
From: [email protected] (William Lupton)
To: [email protected]
Date: Mon, 12 Feb 96 17:13:43 HST
Dear all,

  Having read and thought about Jim and Nick's comments, how about this as
a modified proposal? I've added more detail and put some notes at the end.
I haven't always given credit for suggestions but have often incorporated
them silently.

  William

------------------------------------------------------------------------

1. Macro substitution library
-----------------------------

This library could be used directly by applications which need to support
macro substitution. It will be implemented on all platforms.

1.1 Core library
----------------

The core library provides a minimal set of core operations. Some utility
routines, described later, use core routines to provide a more convenient
interface for some purposes.

a) long macOpen ( MAC_HANDLE *handle );

   Creates a new macro substitution context and returns an opaque handle to
   that context. An application can, if it desires, have several active
   contexts, although most will not.

b) long macIoctl( MAC_HANDLE  handle, char *name, void *value );

   Provides control over various "tuning" parameters. An initial list (which
   can grow) might be:

   name				default value
   ----				-------------
   errRoutine			errPrintf	?
   subsChars			"$()"
   verbose			TRUE

c) long macRead ( MAC_HANDLE  handle, char *name, long maxlen, char *value );

   Returns up to maxlen characters of the value of macro "name". Will always
   be zero-terminated. If value had to be truncated, function return will be
   1 (if not, it will be 0).

   If the value itself contains a macro reference then the reference will be
   expanded recursively. This expansion will detect a direct or indirect self
   reference.

   Any attempt to translate an undefined macro will leave the macro reference
   unchanged and will return -1 as the function value

d) long macWrite( MAC_HANDLE  handle, char *name, char *value );

   Sets the value of the macro "name". If "value" is NULL, undefines "name"
   (it's not an error if "name" was already undefined). Macros referenced
   by "value" need not be defined at this point (like the default GNU make
   behavior).

   Should there be control (as GNU make has via the "=" or ":=" operator)
   over whether macros should be expanded recursively or simply? If so there
   should be a flags argument to macWrite().

e) long macClose( MAC_HANDLE  handle );

   Marks a handle invalid, and frees all storage associated with it.

f) long macPush( MAC_HANDLE   handle );

   Marks the start of a new scoping level such that all definitions made up
   until the next macPop() call will be lost on macPop() and those current
   at macPush() will be re-instated.

   May not be implemented first time round.

g) long macPop( MAC_HANDLE    handle );

   See above.

h) Error handling

   Let's assume that these routines conform to 0 (=OK) for success, -1 (=ERROR)
   for failure, and small positive values for extra info.

   Let's also assume that errors are reported using an errPrintf()-compatible
   routine (or printf()?).

   A "verbose" variable will control error reporting.

1.2 Utility library
-------------------

These are convenience functions.

a) macConvert( char *defns, char **pairs[] );

   This takes a set of macro definitions in "a=xxx,b=yyy" format and converts
   them into an array of pointers to character strings which are, in order,
   "first name", "first value", "second name", "second value" etc. The array
   is terminated with two NULL pointers and all storage is allocated contig-
   uously so that it can be freed with a single call to free().

   This routine is independent of any handle and provides a generally useful
   service which may be used elsewhere. Any macro references in values are
   not expanded at this point since the referenced macros may be defined or
   redefined before the macro actually has to be translated.

a) long macDefine( MAC_HANDLE handle, char *pairs[] );

   This takes an array of pairs as defined above and installs them as
   definitions by calling macWrite(). The pairs array is terminated by
   a NULL pointer.

   If macWrite() has a flags field to control recursive expansion, so also
   should macDefine().

g) long macSubst( MAC_HANDLE handle, char *src, long maxlen, char *dest );

   This operates on a string which may contain macro references. It parses
   the string looking for macro references and passes them to macRead() for
   translation. It returns the expanded string in the supplied argument.

   Any undefined macros will be left unexpanded. The function value will
   be 0 for success, -1 if any translations failed and 1 if successful
   except that there were two many characters for the supplied string.

h) long macReport( MAC_HANDLE handle );

   This dumps details of current definitions to standard output. It's purely
   for debugging purposes.


2. Macro substitution tool
--------------------------

A "macsub" (or "mactool"?) application will be written which would use the
above library and use a command like:

macsub a=b,c=d e=f -Iaaa -Ibbb

to parse a file like:

# comment
%include filename
%xxx = ppp
%yyy = $(xxx)
<arbitrary text containing macro references>

There would also be options to read and write specified files, control the
comment character, control the command prefix, change the macro substitution
characters etc.

Syntax would be a loose subset of corresponding GNU make syntax (see later
discussion of whether we should take our lead from shells or makes).

The use of a command prefix should be optional and perhaps it should default
to an empty string. However there will be cases where the file in question
has a syntax over which we have no control, which may include assignments,
"set" commands, "define" commands etc. This is why I proposed a command
prefix, which might be an arbitrary string such as "macro " or might just
be "%" as in the above example.

The tool can also support the following syntax (or perhaps some equivalent
syntax which will sit more easily inside a file that may have a completely
different syntax from it?):

file gizmo_database.db
{
    i1{ pre=part1,parm=big,   alarm_limit=20 }
    i2{ pre=part2,parm=medium,alarm_limit=30 }
}

as an implied multiple include of "gizmo_database.db" with the specified
macro definitions for each include (here's a good application for macPush()
and macPop() actually). Can someone enlighten me as to the significance of the
"i1" and "i2" bits? Are they needed?


3. Notes
--------

1. I did not add a "subs" argument to macOpen() since this seemed to me rather
   like adding the first line to be written to a file to the fopen() call. I
   felt that macWrite() should be the only core routine that should be able to
   define a macro... but feel free to disagree with this point of view.

2. I added the requirement that the pairs array be NULL-terminated. An alter-
   native would be to have a count argument to macDefine() (which Jim called
   macModify()).

3. I swapped the parameters to macConvert() to be input followed by output.
   I also fixed my "maxlen" parameters similarly. An alternative to the use
   of maxlen would be to allocate the returned string and use a char **.

4. Jim said:
> I feel that one of the important uses for this library is dbLoadRecords()
> which runs on the IOC.  This tools should not be openning any more than one
> file.  The substitions are required to be on the vxWorks command
> line as they are today and nothing must be embedded in the ".db", except
> the $(var) variables.  In other words, I feel that in many instances that
> embedding substitution information at the top of files is not appropriate.

   Agreed. My best current example for embedding information would be where
   you want to generate a master .alhConfig file which wants to include the
   same file n times, one for each IOC and wants to set the ioc macro approp-
   riately each time (of course, we don't have many IOCs...). Of course, this
   is also solved by the "file" proposal.

5. Jim also said:
> 1) Allow syntax such as "A=$(B),B=$(C),C=3"
>    or "pv_name=$(subsystem)$(sector)$(crate),subsystem=RF,sector=5,crate=7"
> 
> 2) Dissallow and print an error message for "A=$(B),B=$(C),C=$(A)".
> 
> 3) Allow "A=\$(B)" to assign $(B) to A instead of the value of B.
> 
> 4) Allow A=\,,B=\",C="this,is\" a test",C='this,\' is a test'
>    to perform as expected.
> 
> Items 3 and 4 are checked by what I called macConvert(), 1 and 2 are
> probably checked by the core library.

   ...and Nick said:
> (Pedantic point) should we have literal `$' represented by \$ (shell
> syntax) or $$ (make syntax)?
> 
> > 4) Allow A=\,,B=\",C="this,is\" a test",C='this,\' is a test'
> >    to perform as expected.
> 
> This also highlights differences between shell and make syntaxes.
> 
> I would like to add a point (which works in make, but not in csh):
> 
> 5) A=$(B$(C)) should work...
> 
> On balance (and at the moment - my feelings may change) I would lean
> towards a make syntax rather than a shell syntax.

   I also favor going with make syntax rather than shell syntax. I would
   also imagine that supporting $(fred:%=%.o) type pattern operators might
   be useful in the future, and these can be modeled on make too. Similarly
   other built-in macros.


Navigate by Date:
Prev: Re: macro substitution Nick Rees
Next: EPICS support for Precision Micro Control products? Paul Stomski
Index: 1994  1995  <19961997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: macro substitution Nick Rees
Next: Re: macro substitution William Lupton
Index: 1994  1995  <19961997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 10 Aug 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·