[Top] [Contents] [Index] [ ? ]

AutoGen

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] [ ? ]

1. Introduction

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:

  1. The flag character in the flag string,
  2. code to process the flag when it is encountered,
  3. a global state variable or two, and
  4. a line in the usage text.

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] [ ? ]

1.1 The Purpose of AutoGen

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:

  1. The definitions are completely separate from the template. By completely isolating the definitions from the template it greatly increases the flexibility of the template implementation. A secondary goal is that a template user only needs to specify those data that are necessary to describe his application of a template.

  2. Each datum in the definitions is named. Thus, the definitions can be rearranged, augmented and become obsolete without it being necessary to go back and clean up older definition files. Reduce incompatibilities!

  3. Multiple values for a given name create an array of values. These arrays of values are used to control the replication of sections of the template.

  4. There are named collections of definitions. They form a nested hierarchy. Associated values are collected and associated with a group name. These associated data are used collectively in sets of substitutions.

  5. The template has special markers to indicate where substitutions are required, much like the ${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.

  6. These same markers are used, in conjunction with enclosed keywords, to indicate sections of text that are to be skipped and for sections of text that are to be repeated. This is a major improvement over using C preprocessing macros. With the C preprocessor, you have no way of selecting output text because it is an unvarying, mechanical substitution process.

  7. Finally, we supply methods for carefully controlling the output. Sometimes, it is just simply easier and clearer to compute some text or a value in one context when its application needs to be later. So, functions are available for saving text or values for later use.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 A Simple Example

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] [ ? ]

1.3 csh/zsh caveat

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:

  1. It handles 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.
  2. At the beginning of each scriptlet, the command \\cd $PWD is inserted. This ensures that cd is not aliased to something peculiar and each scriptlet starts life in the execution directory.
  3. At the end of each scriptlet, the command 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] [ ? ]

1.4 A User's Perspective

 
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] [ ? ]

2. AutoGen Definitions File

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.

2.1 The Identification Definition  
2.2 Named Definitions  
2.3 Dynamic Text  
2.4 Controlling What Gets Processed  
2.5 Pre-defined Names  
2.6 Commenting Your Definitions  
2.7 What it all looks like.  
2.8 YACC Language Grammar  
2.9 AutoGen without Definitions  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 The Identification Definition

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:

  1. It tries to open `./template-name'. If it fails,
  2. it tries `./template-name.tpl'.
  3. It searches for either of these files in the directories listed in the templ-dirs command line option.

If AutoGen fails to find the template file in one of these places, it prints an error message and exits.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 Named Definitions

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.

2.2.1 Naming a Value  
2.2.2 Definition List  
2.2.3 Double Quote String  
2.2.4 Single Quote String  
2.2.6 An Unquoted String  
2.2.5 Shell Output String  
2.2.7 Scheme Result String  
2.2.8 A Here String  
2.2.9 Concatenated Strings  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2.1 Naming a Value

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] [ ? ]

2.2.2 Definition List

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] [ ? ]

2.2.3 Double Quote String

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] [ ? ]

2.2.4 Single Quote String

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] [ ? ]

2.2.5 Shell Output String

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] [ ? ]

2.2.6 An Unquoted String

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] [ ? ]

2.2.7 Scheme Result String

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] [ ? ]

2.2.8 A Here String

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 first string contains no new line characters. The first character is the dollar sign, the last the back quote.

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] [ ? ]

2.2.9 Concatenated Strings

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] [ ? ]

2.3 Dynamic Text

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] [ ? ]

2.4 Controlling What Gets Processed

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> ]
Will add the name to the define list as if it were a DEFINE program argument. Its value will be the first non-whitespace token following the name. Quotes are not processed.

After the definitions file has been processed, any remaining entries in the define list will be added to the environment.

#elif
This must follow an #if otherwise it will generate an error. It will be ignored.

#else
This must follow an #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
This must follow an #if, #ifdef or #ifndef. In all cases, this will resume normal processing of text.

#endshell
Ends the text processed by a command shell into autogen definitions.

#error [ <descriptive text> ]
This directive will cause AutoGen to stop processing and exit with a status of EXIT_FAILURE.

#if [ <ignored conditional expression> ]
#if expressions are not analyzed. Everything from here to the matching #endif is skipped.

#ifdef name-to-test
The definitions that follow, up to the matching #endif will be processed only if there is a corresponding -Dname command line option.

#ifndef name-to-test
The definitions that follow, up to the matching #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
This directive will insert definitions from another file into the current collection. If the file name is adorned with double quotes or angle brackets (as in a C program), then the include is ignored.

#line
Alters the current line number and/or file name. You may wish to use this directive if you extract definition source from other files. getdefs uses this mechanism so AutoGen will report the correct file and approximate line number of any errors found in extracted definitions.

#shell
Invokes $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
Will remove any entries from the define list that match the undef name pattern.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5 Pre-defined Names

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

are used. The associated names are converted to lower case, surrounded by doubled underscores and non-symbol characters are replaced with underscores. For example, for Solaris on a sparc platform, you would get these definitions:

For Linux and other operating systems that only support the uname(2) call, AutoGen will use these values:

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] [ ? ]

2.6 Commenting Your Definitions

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] [ ? ]

2.7 What it all looks like.

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] [ ? ]

2.8 YACC Language Grammar

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] [ ? ]

2.9 AutoGen without Definitions

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] [ ? ]

3. AutoGen Template

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] [ ? ]

3.1 Format of the Pseudo Macro

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] [ ? ]

3.2 Naming a value

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] [ ? ]

3.3 Macro Expression Syntax

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] [ ? ]

3.3.1 Apply Code

The "apply code" selected determines the method of evaluating the expression. There are five apply codes, including the non-use of an apply code.

`no apply code'
This is the most common expression type. Expressions of this sort come in three flavors:

`<value-name>'
The result is the value of value-name, if defined. Otherwise it is the empty string.

`<basic-expr>'
The result of the basic expression is the result of the full expression, See section 3.3.2 Basic Expression.

`<value-name> <basic-expr>'
If there is a defined value for value-name, then the basic-expr is evaluated. Otherwise, the result is the empty string.

`% <value-name> <basic-expr>'
If 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` +]
This would cause the shell to evaluate "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.

`? <value-name> <basic-expr-1> <basic-expr-2>'
Two basic-expr-s are required. If the value-name is defined, then the first basic-expr-1 is evaluated, otherwise basic-expr-2 is.

`- <value-name> <basic-expr>'
Evaluate basic-expr only if value-name is not defined.

`?% <value-name> <basic-expr-1> <basic-expr-2>'
This combines the functions of `?' and `%'. If 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` +]
This would cause the shell to evaluate "cat $bar". If foo were not defined, then the result would be the name of our current directory.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3.2 Basic Expression

A basic expression can have one of the following forms:

`'STRING''
A single quoted string. Backslashes can be used to protect single quotes ('), 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"'
A double quoted string. This is a cooked text string as in C, except that they are not concatenated with adjacent strings. Evaluating "STRING" will output STRING with all backslash sequences interpreted.

``STRING`'
A back quoted string. When this expression is evaluated, STRING is first interpreted as a cooked string (as in `"STRING"') and evaluated as a shell expression by the AutoGen server shell. This expression is replaced by the stdout output of the shell.

`(STRING)'
A parenthesized expression. It will be passed to the Guile interpreter for evaluation and replaced by the resulting value.

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] [ ? ]

3.4 AutoGen Scheme Functions

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.

3.4.1 `ag-function?' - test for function  
3.4.2 `base-name' - base output name  
3.4.3 `count' - definition count  
3.4.4 `def-file' - definitions file name  
3.4.5 `dne' - "Do Not Edit" warning  
3.4.6 `error' - display message and exit  
3.4.7 `error-source-line' - display of file & line  
3.4.8 `exist?' - test for value name  
3.4.9 `first-for?' - detect first iteration  
3.4.10 `for-by' - set iteration step  
3.4.11 `for-from' - set initial index  
3.4.12 `for-index' - get current loop index  
3.4.13 `for-sep' - set loop separation string  
3.4.14 `for-to' - set ending index  
3.4.15 `get' - get named value  
3.4.16 `high-lim' - get highest value index  
3.4.17 `last-for?' - detect last iteration  
3.4.18 `len' - get count of values  
3.4.19 `low-lim' - get lowest value index  
3.4.20 `match-value?' - test for matching value  
3.4.21 `out-delete' - delete current output file  
3.4.22 `out-depth' - output file stack depth  
3.4.23 `out-move' - change name of output file  
3.4.24 `out-name' - current output file name  
3.4.25 `out-pop' - close current output file  
3.4.26 `out-push-add' - append output to file  
3.4.27 `out-push-new' - purge and create output file  
3.4.28 `out-resume' - resume current output file  
3.4.29 `out-suspend' - suspend current output file  
3.4.30 `out-switch' - close and create new output  
3.4.31 `set-writable' - Make the output file be writable  
3.4.32 `stack' - make list of AutoGen values  
3.4.33 `suffix' - get the current suffix  
3.4.34 `tpl-file' - get the template file name  
3.4.35 `tpl-file-line' - get the template file and line number  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.1 `ag-function?' - test for function

Usage: (ag-function? ag-name)
return SCM_BOOL_T if a specified name is a user-defined AutoGen macro, otherwise return SCM_BOOL_F.

Arguments:
ag-name - name of AutoGen macro


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.2 `base-name' - base output name

Usage: (base-name)
Returns a string containing the base name of the output file(s). Generally, this is also the base name of the definitions file.

This Scheme function takes no arguments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.3 `count' - definition count

Usage: (count ag-name)
Count the number of entries for a definition. The input argument must be a string containing the name of the AutoGen values to be counted. If there is no value associated with the name, the result is an SCM immediate integer value of zero.

Arguments:
ag-name - name of AutoGen value


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.4 `def-file' - definitions file name

Usage: (def-file)
Get the name of the definitions file. Returns the name of the source file containing the AutoGen definitions.

This Scheme function takes no arguments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.5 `dne' - "Do Not Edit" warning

Usage: (dne prefix [ first_prefix ])
Generate a "DO NOT EDIT" or "EDIT WITH CARE" warning string. Which depends on whether or not the --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] [ ? ]

3.4.6 `error' - display message and exit

Usage: (error message)
The argument is a string that printed out as part of an error message. The message is formed from the formatting string:

 
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] [ ? ]

3.4.7 `error-source-line' - display of file & line

Usage: (error-source-line)
This function is only invoked just before Guile displays an error message. It displays the file name and line number that triggered the evaluation error. You should not need to invoke this routine directly. Guile will do it automatically.

This Scheme function takes no arguments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.8 `exist?' - test for value name

Usage: (exist? ag-name)
return SCM_BOOL_T iff a specified name has an AutoGen value. The name may include indexes and/or member names. All but the last member name must be an aggregate definition. For example:
 
(exist? "foo[3].bar.baz")
will yield true if all of the following is true:
There is a member value of either group or string type named 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] [ ? ]

3.4.9 `first-for?' - detect first iteration

Usage: (first-for? [ for_var ])
Returns SCM_BOOL_T if the named FOR loop (or, if not named, the current innermost loop) is on the first pass through the data. Outside of any FOR loop, it returns SCM_UNDEFINED. See section 3.6.13 FOR - Emit a template block multiple times.

Arguments:
for_var - Optional - which for loop


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.10 `for-by' - set iteration step

Usage: (for-by by)
This function records the "step by" information for an AutoGen FOR function. Outside of the FOR macro itself, this function will emit an error. See section 3.6.13 FOR - Emit a template block multiple times.

Arguments:
by - the iteration increment for the AutoGen FOR macro


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.11 `for-from' - set initial index

Usage: (for-from from)
This function records the initial index information for an AutoGen FOR function. Outside of the FOR macro itself, this function will emit an error. See section 3.6.13 FOR - Emit a template block multiple times.

Arguments:
from - the initial index for the AutoGen FOR macro


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.12 `for-index' - get current loop index

Usage: (for-index [ for_var ])
Returns the current index for the named FOR loop. If not named, then the index for the innermost loop. Outside of any FOR loop, it returns SCM_UNDEFINED. See section 3.6.13 FOR - Emit a template block multiple times.

Arguments:
for_var - Optional - which for loop


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.13 `for-sep' - set loop separation string

Usage: (for-sep separator)
This function records the separation string that is to be inserted between each iteration of an AutoGen FOR function. This is often nothing more than a comma. Outside of the FOR macro itself, this function will emit an error.

Arguments:
separator - the text to insert between the output of each FOR iteration


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.14 `for-to' - set ending index

Usage: (for-to to)
This function records the terminating value information for an AutoGen FOR function. Outside of the FOR macro itself, this function will emit an error. See section 3.6.13 FOR - Emit a template block multiple times.

Arguments:
to - the final index for the AutoGen FOR macro


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.15 `get' - get named value

Usage: (get ag-name)
Get the first string value associated with the name. It will always return either the associated string value, or the empty string.

Arguments:
ag-name - name of AutoGen value


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.16 `high-lim' - get highest value index

Usage: (high-lim ag-name)
Returns the highest index associated with an array of definitions. This is generally, but not necessarily, one less than the 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] [ ? ]

3.4.17 `last-for?' - detect last iteration

Usage: (last-for? [ for_var ])
Returns SCM_BOOL_T if the named FOR loop (or, if not named, the current innermost loop) is on the last pass through the data. Outside of any FOR loop, it returns SCM_UNDEFINED. See section 3.6.13 FOR - Emit a template block multiple times.

Arguments:
for_var - Optional - which for loop


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.18 `len' - get count of values

Usage: (len ag-name)
If the named object is a group definition, then "len" is the same as "count". Otherwise, if it is one or more text definitions, then it is the sum of their string lengths. If it is a single text definition, then it is equivalent to (string-length (get "ag-name")).

Arguments:
ag-name - name of AutoGen value


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.19 `low-lim' - get lowest value index

Usage: (low-lim ag-name)
Returns the lowest index associated with an array of definitions.

Arguments:
ag-name - name of AutoGen value


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.20 `match-value?' - test for matching value

Usage: (match-value? op ag-name test-str)
This function answers the question, "Is there an AutoGen value named 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.
The value name must follow the same rules as the 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]