GENERATE(1)

NAME
generate - Generate files from script

SYNOPSIS
generate [-D macro=definition] [-i directory] [-q] [-v] [-s] [script ...]

The 'D' option adds the macro definition to the list. If the '=' is not present then 'macro' is defined to the null string.

The 'i' option changes the include directory. Default is /usr/package under Unix and C:\PACKAGE under MSDOS.

The 'q' option causes the program to work quietly. The 'v' option reverses this.

The 's' option causes leading spaces on each line to be stripped before processing. It also strips off the '!' character if it is the first non-space character on the line.

If the file name on the command line is a directory then a file in that directory called script is used.

DESCRIPTION
Generate reads the named files (or stdin if no files named) and provisionally outputs each line with macro substitution. If the first character is '@' then it is taken to be a directive and various actions are taken as described below. An unescaped hash (#) in the input stream causes all input from that character to the end of the current line to be ignored. Blank lines are also ignored. The sequence "\<newline>" is converted to a space.

A dollar sign signifies the start of a macro unless escaped by a backslash. If it is followed by an open parentheses then everything up to the closing parentheses is the macro. If not followed by an open parentheses then the single character following the dollar sign is the macro. A macro is replaced by its definition as in the following example:

    @DEFINE hello goodbye

This defines hello such that instances in the text of "$(hello)" are replaced by "goodbye". See below for more information on defining macros.

If there is a colon embedded in the macro then it separates the name of the macro from arguments to it. Arguments are separated by commas. The arguments are numbered from 0 to 9. In the definition of the macro positional parameters which consist of a dollar sign followed by a digit are replaced by the argument from the macro call. For example:

    @DEFINE foo bar $0 zap $1
    ...
    $(foo:none,gun) --> bar none zap gun

Defaults are allowed:
    @DEFINE foo bar $0 zap $(1:gun)
    ...
    $(foo:none) --> same result as above
Note that "\$" is treated as a single "$". Macro processing is not performed within quotes unless the quotes are escaped.

It is an error to define a macro that already exists.

Four special macros are defined, '@', '=', '%' and '?'. The first is a strlen operator, the second is a calc operator. The third generates a series of numbers. The fourth evaluates to its second argument if the first is not blank and to its third argument otherwise. Naturally this will normally be used with a variable in the first argument.

    $(@:Hello) ----> 5
    $(=:$(@:Hello) + $(@:world)) ----> 10
    $(%: 1 2 3 6 - 9) ----> 1 2 3 6 7 8 9
    $(?: something, expr1, expr2) ----> expr1
    $(?: , expr1, expr2) ----> expr2

Predefined macros:

    __FILE__
        Current file being used for input

    __LINE__
        Current line in current file

    __OFILE__
        Current file being used for output

    __INCLUDE__
        Active include directory

    __USER__
        Current user taken from USER environment variable, LOGNAME environment variable or, if Unix, from the actual login name.

    __DATE__
        The date when the script was interpreted.

    __TIME__
        The time when the script was interpreted.

    __UNIX__
        Defined if compiled under Unix

    __MSDOS__
        Defined if compiled under MS DOS

    __PID__
        Process ID under Unix or 0 under MSDOS

Predefined macros cannot be cleared.

A sample script file is included in driver.pck. This is designed to create a skeleton device driver for SVR4 systems.

DIRECTIVES
This defines a new macro, for example:

    @DEFINE hello goodbye

This defines hello such that instances in the text of "$(hello)" are replaced by "goodbye". See above for more details on macro substitution.

This removes a previously defined macro. It is not an error to undefine a macro that was not defined to begin with.

This operates like define except that the directive is ignored if the macro is already defined. This is equivalent to:

    @IFNDEF foo
        @DEFINE foo bar
    @ENDIF

This allows a macro to be redefined. The macro must already exist in order to redefine it. The importance of this command is that it modifies the definition of the original macro and so can be used in a block while affecting macros outside of the block. Here is a sample use of this command:

    @DEFAULT foo x y z
    @FOR bar a b c
        @REDEFINE foo $(foo) $(bar)
        @CLEAR bar
    @END
    @PRINT $(foo) # Should print "x y z a b c"

Note: Due to the nature of this command, the redefinition is evaluated for macro processing before assignment to avoid recursive definitions. This means that parameter passing cannot be use in these definitions.

This looks for an environment variable matching the first argument. If it is found a macro is defined as its value. If it is not found and a string is included then the macro is defined as that string. If neither case is true the macro is not defined.

This reads a line from the standard input regardless of the current input file and assigns it to the name given as its argument. If the input line is empty and a second argument is supplied then that becomes the definition. Note that unlike GETENV this command always creates a macro definition.

This tests if the macro is currently defined and performs the statements up till the balancing @ELIFDEF, @ELIFNDEF, @ELSE or @ENDIF if so in the case if @IFDEF and if not in the case of @IFNDEF.

After an @IFDEF or @IFNDEF a series of @ELIFDEFs and @ELIFNDEFs may appear. If The macro is defined (or not for @ELIFNDEF) and no blocks have been performed since the balancing @IFDEF or @IFNDEF then the statements up till the balancing @ELIFDEF, @ELIFNDEF, @ELSE or @ENDIF are performed.

Note: The IFDEF family evaluates the macro before testing as well as evaluating the macro definition. This makes testing of macros with positional parameters a little tricky. Example:

    @DEFINE X Y
    @DEFINE Z $(X) $(1:foo) $2 bar
    @DEFINE A $Z
    ...
    @IFDEF A Y foo bar
        PASSED
    @ENDIF

This passes but note the double space between foo and bar.

IF previous balancing block has been performed the statements up till the balancing @ENDIF are performed.

Closing line for above statements.

Does for loop processing. The arguments are a macro name followed by the strings to assign each time through the loop.

This marks the end of a @FOR loop.

The named file is included at the current point in the processing just as if it had been part of the current file with the exception that @IF type statements must balance within a particular file. If the file name starts with a '/' ('\' allowed as well for MSDOS compatibility) or a '.' then that file is used, otherwise the package directory is prepended before the open is performed. The default package directory is compiled into the program and may be changed with a -i option on the command line. Under Unix, if the file name has a colon it is taken to be in the form host:port and a socket is opened to the specified host and port with the output used as the input to generate.

Causes all following output to be directed to the named file until another @FILE directive. If the name is "stdout", or if no file is named, the output goes to the standard output.

Like @FILE but output is appended to file if it already exists.

Prints the text following the directive to be printed on the standard output no matter what the current output file is.

Similar to @PRINT except that processing stops at that point.

Causes the the balance of the current file to be ignored. Still experimental. Needs some work in cleaning up @FOR loops.

Useful for debugging. Shows all the currently defined macros and their definitions.

Clears all user defined macros. If a macro is given then all macros that were defined since the named macro was defined are cleared. The named macro itself is not cleared.

Causes all subsequent output to be surrounded by quote characters. The characters to use are determined by the argument to @QUOTE. The first character is the open quote and the second is the close quote. If there is only one character it is used for both open and close. If there is no argument then quoting is turned off.

ENVIRONMENT
If an environment variable exists with the base name of the program, the string so defined is stuffed into the argument stream as if it followed the file name on the command line but preceded any actual command line arguments. See getarg(3) for more details.

WISH LIST
I want to add some sort of virtual file mechanism. This means that there will be new directives VFILE, VINCLUDE and VAPPEND. These do the same as the similarly named directives except the file is a virtual one and does not actually happen in the file system. There are a number of ways to deal with this concept but the best ones are Unix specific or at least would work best with a flat address system and virtual memory.

AUTHOR
D'Arcy J.M. Cain
Toronto, Ontario
Email: darcy@druid.net