| [Top] | [Contents] | [Index] | [ ? ] |
This file documents AutoGen, a tool designed for generating program files that contain repetitive text with varied substitutions. This document is very long because it is intended as a reference document. For a quick start example, See section 1.2 A Simple Example. For a simple example of Automated Option processing, See section 7.3 Quick Start. For a full list of the Automated Option features, See section 7.1 AutoOpts Features.
This edition documents version 5.2, January 2002.
1. Introduction AutoGen's Purpose 2. AutoGen Definitions File 3. AutoGen Template 4. Augmenting AutoGen 5. Invoking autogen Invoking AutoGen 6. What Gets Installed Where 7. Automated Option Processing 8. Add-on packages for AutoGen 9. Hints, helps and FAQs 10. Some ideas for the future. Concept Index General index Function Index Function index
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
AutoGen is a tool designed for generating program files that contain repetitive text with varied substitutions. Its goal is to simplify the maintenance of programs that contain large amounts of repetitious text. This is especially valuable if there are several blocks of such text that must be kept synchronized.
One common example is the problem of maintaining the code required for processing program options. Processing options requires a minimum of four different constructs be kept in proper order in different places in your program. You need at least:
You will need more things besides this if you choose to implement long option names, rc/ini file processing, environment variables and so on. All of this can be done mechanically; with the proper templates and this program. In fact, it has already been done and AutoGen itself uses it See section 7. Automated Option Processing. For a simple example of Automated Option processing, See section 7.3 Quick Start. For a full list of the Automated Option features, See section 7.1 AutoOpts Features.
1.1 The Purpose of AutoGen 1.2 A Simple Example 1.3 csh/zsh caveat 1.4 A User's Perspective
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The idea of this program is to have a text file, a template if you will, that contains the general text of the desired output file. That file includes substitution expressions and sections of text that are replicated under the control of separate definition files.
AutoGen was designed with the following features:
${VAR} construct in a shell here
doc. These markers are not fixed strings. They are specified at the
start of each template. Template designers know best what fits into their
syntax and can avoid marker conflicts.
We did this because it is burdensome and difficult to avoid conflicts using either M4 tokenizaion or C preprocessor substitution rules. It also makes it easier to specify expressions that transform the value. Of course, our expressions are less cryptic than the shell methods.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This is just one simple example that shows a few basic features.
If you are interested, you also may run "make check" with the
VERBOSE enviornment variable set and see a number of other
examples in the `agen5/test/testdir' directory.
Assume you have an enumeration of names and you wish to associate some string with each name. Assume also, for the sake of this example, that it is either too complex or too large to maintain easily by hand. We will start by writing an abbreviated version of what the result is supposed to be. We will use that to construct our output templates.
In a header file, `list.h', you define the enumeration and the global array containing the associated strings:
typedef enum {
IDX_ALPHA,
IDX_BETA,
IDX_OMEGA } list_enum;
extern const char* az_name_list[ 3 ];
|
Then you also have `list.c' that defines the actual strings:
#include "list.h"
const char* az_name_list[] = {
"some alpha stuff",
"more beta stuff",
"final omega stuff" };
|
First, we will define the information that is unique for each enumeration name/string pair.
autogen definitions list;
list = { list_element = alpha;
list_info = "some alpha stuff"; };
list = { list_info = "more beta stuff";
list_element = beta; };
list = { list_element = omega;
list_info = "final omega stuff"; };
|
The autogen definitions list; entry defines the file as an
AutoGen definition file that uses a template named list. That is
followed by three list entries that define the associations
between the enumeration names and the strings. The order of the
differently named elements inside of list is unimportant. They are
reversed inside of the beta entry and the output is unaffected.
Now, to actually create the output, we need a template or two that can be expanded into the files you want. In this program, we use a single template that is capable of multiple output files.
It looks something like this. (For a full description, See section 3. AutoGen Template.)
[+ AutoGen5 template h c +]
[+ CASE (suffix) +][+
== h +]
typedef enum {[+
FOR list "," +]
IDX_[+ (string-upcase! (get "list_element")) +][+
ENDFOR list +] } list_enum;
extern const char* az_name_list[ [+ (count "list") +] ];
[+
== c +]
#include "list.h"
const char* az_name_list[] = {[+
FOR list "," +]
"[+list_info+]"[+
ENDFOR list +] };[+
ESAC +]
|
The [+ AutoGen5 template h c +] text tells AutoGen that this is
an AutoGen version 5 template file; that it is to be processed twice;
that the start macro marker is [+; and the end marker is
+]. The template will be processed first with a suffix value of
h and then with c. Normally, the suffix values are
appended to the `base-name' to create the output file name.
The [+ == h +] and [+ == c +] CASE selection clauses
select different text for the two different passes. In this example,
the output is nearly disjoint and could have been put in two separate
templates. However, sometimes there are common sections and this is
just an example.
The [+FOR list "," +] and [+ ENDFOR list +] clauses delimit
a block of text that will be repeated for every definition of list.
Inside of that block, the definition name-value pairs that
are members of each list are available for substitutions.
The remainder of the macros are expressions. Some of these contain
special expression functions that are dependent on AutoGen named values;
others are simply Scheme expressions, the result of which will be
inserted into the output text. Other expressions are names of AutoGen
values. These values will be inserted into the output text. For example,
[+list_info+] will result in the value associated with
the name list_info being inserted between the double quotes and
(string-upcase! (get "list_element")) will first "get" the value
associated with the name list_element, then change the case of
all the letters to upper case. The result will be inserted into the
output document.
If you have compiled AutoGen, you can copy out the template and definitions, run `autogen' and produce exactly the hypothesized desired output.
One more point, too. Lets say you decided it was too much trouble to figure out how to use AutoGen, so you created this enumeration and string list with thousands of entries. Now, requirements have changed and it has become necessary to map a string containing the enumeration name into the enumeration number. With AutoGen, you just alter the template to emit the table of names. It will be guaranteed to be in the correct order, missing none of the entries. If you want to do that by hand, well, good luck.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
AutoGen tries to use your normal shell so that you can supply shell code in a manner you are accustomed to using. If, however, you use csh or zsh, you cannot do this. Csh is sufficiently difficult to program that it is unsupported. Zsh, though largely programmable, also has some anomolies that make it incompatible with AutoGen usage. Therefore, when invoking AutoGen from these environments, you must be certain to set the SHELL environment variable to a Bourne-derived shell. e.g., sh, ksh or bash.
Any shell you choose for your own scripts need to follow these basic requirements:
trap $sig ":" without output to standard out.
This is done when the server shell is first started.
If your shell does not handle this, then it may be able to by
loading functions from its start up files.
\\cd $PWD
is inserted. This ensures that cd is not aliased to something
peculiar and each scriptlet starts life in the execution directory.
echo mumble is
appended. The program you use as a shell must emit the single
argument mumble on a line by itself.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Alexandre wrote: > > I'd appreciate opinions from others about advantages/disadvantages of > each of these macro packages. |
I am using AutoGen in my pet project, and find one of its best points to be that it separates the operational data from the implementation.
Indulge me for a few paragraphs, and all will be revealed: In the manual, Bruce cites the example of maintaining command line flags inside the source code; traditionally spreading usage information, flag names, letters and processing across several functions (if not files). Investing the time in writing a sort of boiler plate (a template in AutoGen terminology) pays by moving all of the option details (usage, flags names etc.) into a well structured table (a definition file if you will), so that adding a new command line option becomes a simple matter of adding a set of details to the table.
So far so good! Of course, now that there is a template, writing all of that tedious optargs processing and usage functions is no longer an issue. Creating a table of the options needed for the new project and running AutoGen generates all of the option processing code in C automatically from just the tabular data. AutoGen in fact already ships with such a template... AutoOpts.
One final consequence of the good separation in the design of AutoGen is that it is retargetable to a greater extent. The egcs/gcc/fixinc/inclhack.def can equally be used (with different templates) to create a shell script (inclhack.sh) or a c program (fixincl.c).
This is just the tip of the iceberg. AutoGen is far more powerful than these examples might indicate, and has many other varied uses. I am certain Bruce or I could supply you with many and varied examples, and I would heartily recommend that you try it for your project and see for yourself how it compares to m4.
As an aside, I would be interested to see whether someone might be persuaded to rationalise autoconf with AutoGen in place of m4... Ben, are you listening? autoconf-3.0! `kay? =)O|
Sincerely,
Gary V. Vaughan
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This chapter describes the syntax and semantics of the AutoGen definition file. In order to instantiate a template, you normally must provide a definitions file that identifies itself and contains some value definitions. Consequently, we keep it very simple. For "advanced" users, there are preprocessing directives and comments that may be used as well.
The definitions file is used to associate values with names. When multiple values are associated with a single name, an implicit array of values is formed. Values may be either simple strings or compound collections of name-value pairs. An array may not contain both simple and compound members. Fundamentally, it is as simple as:
prog_name = "autogen";
flag = {
name = templ_dirs;
value = L;
descrip = "Template search directory list";
};
|
For purposes of commenting and controlling the processing of the
definitions, C-style comments and most C preprocessing directives are
honored. The major exception is that the #if directive is
ignored, along with all following text through the matching
#endif directive. The C preprocessor is not actually invoked, so
C macro substitution is not performed.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The first definition in this file is used to identify it as a
AutoGen file. It consists of the two keywords,
`autogen' and `definitions' followed by the default
template name and a terminating semi-colon (;). That is:
AutoGen Definitions template-name; |
Note that, other than the name template-name, the words `AutoGen' and `Definitions' are searched for without case sensitivity. Most lookups in this program are case insensitive.
Also, if the input contains more identification definitions, they will be ignored. This is done so that you may include (see section 2.4 Controlling What Gets Processed) other definition files without an identification conflict.
AutoGen uses the name of the template to find the corresponding template file. It searches for the file in the following way, stopping when it finds the file:
If AutoGen fails to find the template file in one of these places, it prints an error message and exits.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Any name may have multiple values associated with it in the definition file. If there is more than one instance, the only way to expand all of the copies of it is by using the FOR (see section 3.6.13 FOR - Emit a template block multiple times) text function on it, as described in the next chapter.
There are two kinds of definitions, `simple' and `compound'. They are defined thus (see section 2.8 YACC Language Grammar):
compound_name '=' '{' definition-list '}' ';'
simple_name '=' string ';'
no_text_name ';'
|
No_text_name is a simple definition with a shorthand empty string
value. The string values for definitions may be specified in any of
several formation rules.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The names may be a simple name taking the next available index, or may specify an index by name or number. For example:
txt_name txt_name[2] txt_name[ DEF_NAME ] |
DEF_NAME must be defined to have a numeric value.
If you do specify an index, you must take care not to cause conflicts.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
definition-list is a list of definitions that may or may not
contain nested compound definitions. Any such definitions may
only be expanded within a FOR block iterating over the
containing compound definition. See section 3.6.13 FOR - Emit a template block multiple times.
Here is, again, the example definitions from the previous chapter, with three additional name value pairs. Two with an empty value assigned (first and last), and a "global" group_name.
autogen definitions list;
group_name = example;
list = { list_element = alpha; first;
list_info = "some alpha stuff"; };
list = { list_info = "more beta stuff";
list_element = beta; };
list = { list_element = omega; last;
list_info = "final omega stuff"; };
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The string follows the C-style escaping (\, \n, \f,
\v, etc.), plus octal character numbers specified as \ooo.
The difference from "C" is that the string may span multiple lines.
Like ANSI "C", a series of these strings, possibly intermixed with
single quote strings, will be concatenated together.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This is similar to the shell single-quote string. However, escapes
\ are honored before another escape, single quotes '
and hash characters #. This latter is done specifically
to disambiguate lines starting with a hash character inside
of a quoted string. In other words,
foo = ' #endif '; |
could be misinterpreted by the definitions scanner, whereas this would not:
foo = ' \#endif '; |
As with the double quote string, a series of these, even intermixed
with double quote strings, will be concatenated together.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This is assembled according to the same rules as the double quote string, except that there is no concatenation of strings and the resulting string is written to a shell server process. The definition takes on the value of the output string.
NB The text is interpreted by a server shell. There may be
left over state from previous ` processing and it may
leave state for subsequent processing. However, a cd
to the original directory is always issued before the new
command is issued.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A simple string that does not contain white space may be left
unquoted. The string must not contain any of the characters special to
the definition text (i.e. ", #, ', (,
), ,, ;, <, =, >, [,
], `, {, or }). This list is subject to
change, but it will never contain underscore (_), period
(.), slash (/), colon (:), hyphen (-) or
backslash (\\). Basically, if the string looks like it is a
normal DOS or UNIX file or variable name, and it is not one of two
keywords (`autogen' or `definitions') then it is OK to not
quote it, otherwise you should.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A scheme result string must begin with an open parenthesis (.
The scheme expression will be evaluated by Guile and the
value will be the result. The AutoGen expression functions
are disabled at this stage, so do not use them.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A `here string' is formed in much the same way as a shell here doc. It is denoted with a doubled less than character and, optionally, a hyphen. This is followed by optional horizontal white space and an ending marker-identifier. This marker must follow the syntax rules for identifiers. Unlike the shell version, however, you must not quote this marker. The resulting string will start with the first character on the next line and continue up to but not including the newline that precedes the line that begins with the marker token. No backslash or any other kind of processing is done on this string. The characters are copied directly into the result string.
Here are two examples:
str1 = <<- STR_END
$quotes = " ' `
STR_END;
str2 = << STR_END
$quotes = " ' `
STR_END;
STR_END;
|
The second string contains one new line character. The first character
is the tab character preceeding the dollar sign. The last character is
the semicolon after the STR_END. That STR_END does not
end the string because it is not at the beginning of the line. In the
preceeding case, the leading tab was stripped.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If single or double quote characters are used, then you also have the option, a la ANSI-C syntax, of implicitly concatenating a series of them together, with intervening white space ignored.
NB You cannot use directives to alter the string content. That is,
str = "foo"
#ifdef LATER
"bar"
#endif
;
|
will result in a syntax error. The preprocessing directives are not carried out by the C preprocessor. However,
str = '"foo\n" #ifdef LATER " bar\n" #endif '; |
Will work. It will enclose the `#ifdef LATER'
and `#endif' in the string. But it may also wreak
havoc with the definition processing directives. The hash
characters in the first column should be disambiguated with
an escape \ or join them with previous lines:
"foo\n#ifdef LATER....
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are several methods for including dynamic content inside a definitions
file. Three of them are mentioned above (2.2.5 Shell Output String and
see section 2.2.7 Scheme Result String) in the discussion of string formation rules.
Another method uses the #shell processing directive.
It will be discussed in the next section (see section 2.4 Controlling What Gets Processed).
Guile/Scheme may also be used to yield to create definitions.
When the Scheme expression is preceeded by a backslash and single quote, then the expression is expected to be an alist of names and values that will be used to create AutoGen definitions.
This method can be be used as follows:
\'( (name (value-expression))
(name2 (another-expr)) )
|
This is entirely equivalent to:
name = (value-expression); name2 = (another-expr); |
Under the covers, the expression gets handed off to a Guile function
named alist->autogen-def in an expression that looks like this:
(alist->autogen-def
( (name (value-expression)) (name2 (another-expr)) ) )
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Definition processing directives can only be processed
if the '#' character is the first character on a line. Also, if you
want a '#' as the first character of a line in one of your string
assignments, you should either escape it by preceding it with a
backslash `\', or by embedding it in the string as in "\n#".
All of the normal C preprocessing directives are recognized, though
several are ignored. There is also an additional #shell -
#endshell pair. Another minor difference is that AutoGen
directives must have the hash character (#) in column 1.
The ignored directives are:
`#assert', `#ident', `#pragma', and `#if'.
Note that when ignoring the #if directive, all intervening
text through its matching #endif is also ignored,
including the #else clause.
The AutoGen directives that affect the processing of definitions are:
#define name [ <text> ]
After the definitions file has been processed, any remaining entries in the define list will be added to the environment.
#elif
#if
otherwise it will generate an error.
It will be ignored.
#else
#if, #ifdef or #ifndef.
If it follows the #if, then it will be ignored. Otherwise,
it will change the processing state to the reverse of what it was.
#endif
#if, #ifdef or #ifndef.
In all cases, this will resume normal processing of text.
#endshell
#error [ <descriptive text> ]
#if [ <ignored conditional expression> ]
#if expressions are not analyzed. Everything from here
to the matching #endif is skipped.
#ifdef name-to-test
#endif will be
processed only if there is a corresponding -Dname command line
option.
#ifndef name-to-test
#endif will be
processed only if there is not a corresponding -Dname
command line option or there was a canceling -Uname option.
#include unadorned-file-name
#line
getdefs uses this mechanism so AutoGen will report the correct
file and approximate line number of any errors found in extracted
definitions.
#shell
$SHELL or `/bin/sh' on a script that should
generate AutoGen definitions. It does this using the same server
process that handles the back-quoted ` text.
CAUTION let not your $SHELL be csh.
#undef name-to-undefine
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When AutoGen starts, it tries to determine several names from the
operating environment and put them into environment variables for use in
both #ifdef tests in the definitions files and in shell scripts
with environment variable tests. __autogen__ is always defined.
For other names, AutoGen will first try to use the POSIX version of the
sysinfo(2) system call. Failing that, it will try for the POSIX
uname(2) call. If neither is available, then only
"__autogen__" will be inserted into the environment.
If sysinfo(2) is available, the strings associated with
SI_SYSNAME (e.g., "__sunos__")
SI_HOSTNAME (e.g., "__ellen__")
SI_ARCHITECTURE (e.g., "__sparc__")
SI_HW_PROVIDER (e.g., "__sun_microsystems__")
SI_PLATFORM (e.g., "__sun_ultra_5_10__")
SI_MACHINE (e.g., "__sun4u__")
For Linux and other operating systems that only support the
uname(2) call, AutoGen will use these values:
sysname (e.g., "__linux__")
machine (e.g., "__i586__")
nodename (e.g., "__bach__")
By testing these pre-defines in my definitions, you can select
pieces of the definitions without resorting to writing shell
scripts that parse the output of uname(1). You can also
segregate real C code from autogen definitions by testing for
"__autogen__".
#ifdef __bach__ location = home; #else location = work; #endif |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The definitions file may contain C and C++ style comments.
/* * This is a comment. It continues for several lines and closes * when the characters '*' and '/' appear together. */ // this comment is a single line comment |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This is an extended example:
autogen definitions `template-name';
/*
* This is a comment that describes what these
* definitions are all about.
*/
global = "value for a global text definition.";
/*
* Include a standard set of definitions
*/
#include standards.def
a_block = {
a_field;
a_subblock = {
sub_name = first;
sub_field = "sub value.";
};
#ifdef FEATURE
a_subblock = {
sub_name = second;
};
#endif
};
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The processing directives and comments are not part of the grammar. They are handled by the scanner/lexer. The following was extracted directly from the defParse.y source file:
definitions : identity def_list TK_END
{ $$ = (YYSTYPE)(rootDefCtx.pDefs = (tDefEntry*)$2); } ;
def_list : definition { $$ = $1; }
| definition def_list { $$ = addSibMacro( $1, $2 ); }
| identity def_list { $$ = $2; }
;
identity : TK_AUTOGEN TK_DEFINITIONS anyname ';'
{ $$ = identify( $3 ); }
;
definition : value_name ';'
{ $$ = makeMacro( $1, (YYSTYPE)"", VALTYP_TEXT ); }
| value_name '=' text_list ';'
{ $$ = makeMacroList( $1, $3, VALTYP_TEXT ); }
| value_name '=' block_list ';'
{ $$ = makeMacroList( $1, $3, VALTYP_BLOCK ); }
;
text_list : anystring { $$ = startList( $1 ); }
| anystring ',' text_list { $$ = appendList( $1, $3 ); }
;
block_list : def_block { $$ = startList( $1 ); }
| def_block ',' block_list { $$ = appendList( $1, $3 ); }
;
def_block : '{' def_list '}' { $$ = $2; } ;
anystring : anyname { $$ = $1; }
| TK_STRING { $$ = $1; }
| TK_NUMBER { $$ = $1; } ;
anyname : TK_OTHER_NAME { $$ = $1; }
| TK_VAR_NAME { $$ = $1; } ;
value_name : TK_VAR_NAME
{ $$ = findPlace( $1, (YYSTYPE)NULL ); }
| TK_VAR_NAME '[' TK_NUMBER ']'
{ $$ = findPlace( $1, $3 ); }
| TK_VAR_NAME '[' TK_VAR_NAME ']'
{ $$ = findPlace( $1, $3 ); }
;
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
It is entirely possible to write a template that does not depend upon
external definitions. Such a template would likely have an unvarying
output, but be convenient nonetheless because of an external library
of either AutoGen or Scheme functions, or both. This can be accommodated
by providing the --override-tpl and --no-definitions
options on the command line. See section 5. Invoking autogen.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The AutoGen template file defines the content of the output text. It is composed of two parts. The first part consists of a pseudo macro invocation and commentary. It is followed by the template proper.
This pseudo macro is special. It is used to identify the file as a AutoGen template file, fixing the starting and ending marks for the macro invocations in the rest of the file, specifying the list of suffixes to be generated by the template and, optionally, the shell to use for processing shell commands embedded in the template.
AutoGen-ing a file consists of copying text from the template to the output file until a start macro marker is found. The text from the start marker to the end marker constitutes the macro text. AutoGen macros may cause sections of the template to be skipped or processed several times. The process continues until the end of the template is reached. The process is repeated once for each suffix specified in the pseudo macro.
This chapter describes the format of the AutoGen template macros and the usage of the AutoGen native macros. Users may augment these by defining their own macros. See section 3.6.4 DEFINE - Define a user AutoGen macro.
3.1 Format of the Pseudo Macro 3.2 Naming a value 3.3 Macro Expression Syntax 3.4 AutoGen Scheme Functions 3.5 Common Scheme Functions 3.6 AutoGen Native Macros 3.7 Redirecting Output
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The pseudo-macro starts with up to seven (7) punctuation characters used
for the template start-macro marker, followed by the autogen magic
marker (autogen5), the template marker (template), zero or
more suffix specifications, scheme expressions and the end-macro marker.
It may also consist of up to seven (7) punctuation characters. Interspersed
may be comment lines (blank lines or lines starting with a hash mark
[#]) and edit mode markers (text between pairs of -*-
characters).
As an example, assume we want to use [+ and +] as the start
and end macro markers, and we wish to produce a `.c' and a `.h'
file, then the first macro invocation will look something like this:
[+ AutoGen5 template -*- Mode: emacs-mode-of-choice -*- h=chk-%s.h c # make sure we don't use csh: (setenv "SHELL" "/bin/sh") +] |
Note It is generally a good idea to use some sort of opening
bracket in the starting macro and closing bracket in the ending
macro (e.g. {, (, [, or even <
in the starting macro). It helps both visually and with editors
capable of finding a balancing parenthesis. The closing marker
may not begin with an open parenthesis, as that is used
to enclose a scheme expression.
It is also helpful to avoid using the comment marker (#);
the POSIXly acceptable file name characters period (.),
hyphen (-) and underscore (_); and finally, it is
advisable to avoid using any of the quote characters double,
single or back-quote. But there is no special check for any of
these advisories.
Detailed description:
The starting macro marker must be the first non-white space characters encountered in the file. The marker consists of all the contiguous ASCII punctuation characters found there. With optional intervening white space, this marker must be immediately followed by the keywords, "autogen5" and "template". Capitalization of these words is not important. This is followed by zero, one or more suffix specifications and, possibly, a scheme expression.
Suffix specifications consist of a sequence of POSIX compliant file name
characters and, optionally, an equal sign and a file name "printf"-style
formatting string. Two string arguments are allowed for that string:
the base name of the definition file and the current suffix (that being
the text to the left of the equal sign). (Note "POSIX compliant file
name characters" consist of alphanumerics plus the period (.),
hyphen (-) and underscore (_) characters.) If there are
no suffix specifications, then the generated file will be written to the
stdout file descriptor.
The scheme expression is intended to allow the template writer to specify the shell program that must be used to interpret the shell commands in the template. It can have no effect on any shell commands in the definitions file, as that file will have been processed by the time the pseudo macro is interpreted. You can specify the shell as follows:
(setenv "SHELL" "/bin/sh") |
This works because AutoGen examines the value of the SHELL environment
variable in order to select the shell to run. If that shell is allowed
to be csh, AutoGen will break. If it is allowed to be zsh,
AutoGen may break. Your milage may vary.
The pseudo macro ends with an end macro marker. Like the starting macro marker, it consists of a contiguous sequence of arbitrary punctuation characters. However, additionally, it may not begin with any of the POSIX file name characters and it may not contain the start macro marker.
This pseudo macro may appear on one or several lines of text.
Intermixed may be comment lines (completely blank or starting with the
hash character # in column 1), and file content markers (text
between -*- pairs on a single line). This may be used to
establish editing "modes" for the file. These are ignored by
AutoGen.
The template proper starts after the pseudo-macro. The starting character is either the first non-whitespace character or the first character after the new-line that follows the end macro marker.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When an AutoGen value is specified in a template, it is specified by name. The name may be a simple name, or a compound name of several components. Since each named value in AutoGen is implicitly an array of one or more values, each component may have an index associated with it.
It looks like this:
comp-name-1 . comp-name-2 [ 2 ] |
Note that if there are multiple components to a name, each component
name is separated by a dot (.). Indexes follow a component name,
enclosed in square brackets ([ and ]). The index may be
either an integer or an integer-valued define name. The first component
of the name is searched for in the current definition level. If not
found, higher levels will be searched until either a value is found,
or there are no more definition levels. Subsequent components of the
name must be found within the context of the newly-current definition
level. Also, if the named value is prefixed by a dot (.), then
the value search is started in the current context only. No higher
levels are searched.
If someone rewrites this, I'll incorporate it. :-)
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
AutoGen has two types of expressions: full expressions and basic ones. A full AutoGen expression can appear by itself, or as the argument to certain AutoGen built-in macros: CASE, IF, ELIF, INCLUDE, INVOKE (explicit invocation, see section 3.6.16 INVOKE - Invoke a User Defined Macro), and WHILE. If it appears by itself, the result is inserted into the output. If it is an argument to one of these macros, the macro code will act on it sensibly.
You are constrained to basic expressions only when passing arguments to user defined macros, See section 3.6.4 DEFINE - Define a user AutoGen macro.
The syntax of a full AutoGen expression is:
[[ <apply-code> ] <value-name> ] [ <basic-expr-1> [ <basic-expr-2> ]] |
How the expression is evaluated depends upon the presence or absence
of the apply code and value name. The "value name" is the name of
an AutoGen defined value, or not. If it does not name such a value,
the expression result is generally the empty string. All expressions
must contain either a value-name or a basic-expr.
3.3.1 Apply Code 3.3.2 Basic Expression
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The "apply code" selected determines the method of evaluating the expression. There are five apply codes, including the non-use of an apply code.
value-name, if defined.
Otherwise it is the empty string.
value-name, then the basic-expr
is evaluated. Otherwise, the result is the empty string.
value-name is defined, use basic-expr as a format
string for sprintf. Then, if the basic-expr is either a back-quoted
string or a parenthesized expression, then hand the result to the
appropriate interpreter for further evaluation. Otherwise, for single
and double quote strings, the result is the result of the sprintf operation.
Naturally, if value-name is not defined, the result is the empty
string.
For example, assume that foo had the string value, bar:
[+ % foo `printf '%%x\\n' $%s` +] |
printf '%x\n' $bar".
Assuming that the shell variable bar had a numeric value,
the expression result would be that number, in hex. Note the need
for doubled percent characters and backslashes.
basic-expr-s are required. If the value-name is
defined, then the first basic-expr-1 is evaluated, otherwise
basic-expr-2 is.
basic-expr only if value-name is not defined.
value-name is
defined, it behaves exactly like `%', above, using basic-expr-1.
If not defined, then basic-expr-2 is evaluated.
For example, assume again that foo had the string value, bar:
[+ ?% foo `cat $%s` `pwd` +] |
cat $bar".
If foo were not defined, then the result would be the name
of our current directory.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A basic expression can have one of the following forms:
'), hash characters (#), or backslashes (\)
in the string. All other characters of STRING are output as-is when the
single quoted string is evaluated. Backslashes are processed before the hash
character for consistency with the definition syntax. It is needed there
to avoid preprocessing conflicts.
STRING" will output STRING with all
backslash sequences interpreted.
Additionally, other than in the % and ?% expressions, the
Guile expressions may be introduced with the Guile comment character
(;) and you may put a series of Guile expressions within a single
macro. They will be implicitly evaluated as if they were arguments
to the (begin ...) expression. The result will be the the
result of the last Guile expression evaluated.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
AutoGen uses Guile to interpret Scheme expressions within AutoGen macros. All of the normal Guile functions are available, plus several extensions (see section 3.5 Common Scheme Functions) have been added to augment the repertoire of string manipulation functions and manage the state of AutoGen processing.
This section describes those functions that are specific to AutoGen. Please take note that these AutoGen specific functions are not loaded and thus not made available until after the command line options have been processed and the AutoGen definitions have been loaded. They may, of course, be used in Scheme functions that get defined at those times, but they cannot be invoked.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
ag-name - name of AutoGen macro
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This Scheme function takes no arguments.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
ag-name - name of AutoGen value
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This Scheme function takes no arguments.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
--writable command line
option was set. The first argument is a per-line string prefix.
The optional second argument is a prefix for the first-line and,
in read-only mode, activates the editor hints:
-*- buffer-read-only: t -*- vi: set ro: |
Arguments:
prefix - string for starting each output line
first_prefix - Optional - for the first output line
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
DEFINITIONS ERROR in %s line %d for %s: %s\n |
The first three arguments to this format are provided by the routine and are: The name of the template file, the line within the template where the error was found, and the current output file name.
After displaying the message, the current output file is removed and autogen exits with the EXIT_FAILURE error code. IF, however, the argument begins with the number 0 (zero), or the string is the empty string, then processing continues with the next suffix.
Arguments:
message - message to display before exiting
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This Scheme function takes no arguments.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(exist? "foo[3].bar.baz") |
baz for some group value bar that
is a member of the foo group with index 3.
There may be multiple entries of bar within
foo, only one needs to contain a value for baz.
Arguments:
ag-name - name of AutoGen value
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
for_var - Optional - which for loop
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
by - the iteration increment for the AutoGen FOR macro
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
from - the initial index for the AutoGen FOR macro
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
for_var - Optional - which for loop
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
separator - the text to insert between the output of
each FOR iteration
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
to - the final index for the AutoGen FOR macro
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
ag-name - name of AutoGen value
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
count value. (The indexes may be specified, rendering a
non-zero based or sparse array of values.)
This is very useful for specifying the size of a zero-based array of values where not all values are present. For example:
tMyStruct myVals[ [+ (+ 1 (high-lim "my-val-list")) +] ]; |
Arguments:
ag-name - name of AutoGen value
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
for_var - Optional - which for loop
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(string-length (get "ag-name")).
Arguments:
ag-name - name of AutoGen value
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Arguments:
ag-name - name of AutoGen value
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ag-name with a value that matches the pattern test-str
using the match function op?" Return SCM_BOOL_T iff at least
one occurrence of the specified name has such a value. The operator
can be any function that takes two string arguments and yields a
boolean. It is expected that you will use one of the string matching
functions provided by AutoGen.
ag-name argument for exist? (see section 3.4.8 `exist?' - test for value name).
Arguments:
op - boolean result operator
ag-name - name of AutoGen value
test-str - string to test against
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] |