• No results found

Generating main procedures

7 Automated Option Processing

7.5 Option Definitions

7.5.4 Generating main procedures

When AutoOpts generates the code to parse the command line options, it has the ability to produce any of several types of main() procedures. This is done by specifying a global structured value for main. The values that it contains are dependent on the value set for the one value it must have: main-type.

The recognized values for main-type are guile, shell-process, shell-parser, main, include, invoke, and for-each.

7.5.4.1 guile: main and inner main procedures

When the main-type is specified to be guile, a main() procedure is generated that calls gh_enter(), providing it with a generated inner_main() to invoke. If you must perform certain tasks before calling gh_enter(), you may specify such code in the value for the before-guile-boot attribute.

The inner_main() procedure itself will process the command line arguments (by calling optionProcess(), seeSection 7.6.32.14 [libopts-optionProcess], page 139), and then either invoke the code specified with the guile-main attribute, or else export the parsed options to Guile symbols and invoke the scm_shell() function from the Guile library. This latter will render the program nearly identical to the stock guile(1) program.

7.5.4.2 shell-process: emit Bourne shell results

This will produce a main() procedure that parses the command line options and emits to stdout Bourne shell commands that puts the option state into environment variables. This can be used within a shell script as follows:

unset OPTION_CT

eval "‘opt_parser \"$@\"‘"

test ${OPTION_CT} -gt 0 && shift ${OPTION_CT}

If the option parsing code detects an error or a request for usage or version, it will emit a command to exit with an appropriate exit code to stdout. This form of main will cause all messages, including requested usage and version information, to be emitted to stderr. Otherwise, a numeric value for OPTION_CT is guaranteed to be emitted, along with assignments for all the options parsed, something along the lines of the following will be written to stdout for evaluation:

OPTION_CT=4 export OPTION_CT MYPROG_SECOND=’first’

export MYPROG_SECOND MYPROG_ANOTHER=1 # 0x1 export MYPROG_ANOTHER

If the arguments are to be reordered, however, then the resulting set of operands will be emitted and OPTION_CT will be set to zero. For example, the following would be appended to the above:

set -- ’operand1’ ’operand2’ ’operand3’

OPTION_CT=0

OPTION_CT is set to zero since it is not necessary to shift off any options.

7.5.4.3 shell-parser: emit Bourne shell script

This will produce a main() procedure that emits a shell script that will parse the command line options. That script can be emitted to stdout or inserted or substituted into a pre-existing shell script file. Improbable markers are used to identify previously inserted parsing text:

# # # # # # # # # # do not modify this marker

--The program is also pretty insistent upon starting its parsing script on the second line.

7.5.4.4 main: user supplied main procedure

You must supply a value for the main-text attribute. You may also supply a value for option-code. If you do, then the optionProcess invocation will not be emitted into the code. AutoOpts will wrap the main-text inside of:

int

main( int argc, char** argv ) {

int res = <<success-exit-code>>;

{ // replaced by option-code, if that exists

int ct = optionProcess( &<<prog-name>>Options, argc, argv);

argc -= ct;

argv += ct;

}

<<main-text>>

return res;

}

so you can most conveniently set the value with a here string (see Section 2.2.7 [here-string], page 9):

code = <<- _EndOfMainProc_

<<your text goes here>>

_EndOfMainProc_;

7.5.4.5 include: code emitted from included template

You must write a template to produce your main procedure. You specify the name of the template with the tpl attribute and it will be incorporated at the point where AutoOpts is ready to emit the main() procedure.

This can be very useful if, in your working environment, you have many programs with highly similar main() procedures. All you need to do is parameterize the variations and specify which variant is needed within the main AutoOpts specification. Since you are coding the template for this, the attributes needed for this variation would be dictated by your template.

Here is an example of an include variation:

main = {

main-type = include;

tpl = "main-template.tpl";

};

7.5.4.6 invoke: code emitted from AutoGen macro

You must write a template to produce your main procedure. That template must contain a definition for the function specified with the func attribute to this main() procedure specification. This variation operates in much the same way as include (seeSection 7.5.4.5 [main include], page 102) method.

7.5.4.7 for-each: perform function on each operand

This produces a main procedure that invokes a procedure once for each operand on the command line (non-option arguments), OR once for each non-blank, non-comment stdin input line. Leading and trailing white space is trimmed from the input line and comment lines are lines that are empty or begin with a comment character, defaulting to a hash (’#’) character.

NB: The argument program attribute (see Section 7.5.1 [program attributes], page 90) must begin with the [ character, to indicate that there are command operands, but that they are optional.

For an example of the produced main procedure, in the autoopts/test build directory, type the following command and look at main.c:

make verbose TESTS=main.test