Go to the first, previous, next, last section, table of contents.


CNParseArgs -- Argument Parser

SYNOPSIS

#include <CNCL/ParseArgs.h>

TYPE

CN_PARSEARGS

BASE CLASSES

CNObject

DERIVED CLASSES

None

RELATED CLASSES

None

DESCRIPTION

CNParseArgs provides a simple argument parser mainly intended (but not limited) to parse numeric arguments given in the command line of a program.

One enumeration and two additional structures are defined in ParseArgs.h in order to allow easy use of this class:

enum BlankHandling {NO_BLANK, BLANK}; // handling of blanks after option

struct OptionDescription {
   char * option_string;    // option string to be parsed
   BlankHandling blank;
   char * default_argument; // default argument 
   char * usage;            // optional string for usage
   char * argument_string;  // contains the argument on return
};

struct CNParseArgsList {
   int number_of_args; // number of elements of args_array 
   OptionDescription * args_array; // array containing description
			           // of options 
   int mandatory_args;     // number of args that have to be given
   int positional_args;    // number of args that may be given without
			   // option but in correct positional order
   void (*usage_func)(int argc, char **argv);   // Pointer to a user
			   // supplied usage function 
};

Main features of the class are:

Default arguments:
Default arguments to be used if no argument is specified.
Usage function:
From the information given on the options to be parsed, a usage text can automatically be generated. Thus the user does not need to program any usage function. Nevertheless is it possible, to specify a user supplied usage function. This function can also use the automatic usage function.
Positional arguments:
An arbitrary number of the options can be specified to be positional. I.e. that an argument for this option can be specified without specifying the option. Those arguments are assigned consecutively to the positional options. E.g.: cnhisto -i infile -o outfile can be specified as cnhisto infile outfile if the first two arguments are specified as positional.
Blank format:
Options can either require a BLANK between option and argument or be specified as NO_BLANK in which case no blank must be specified. This is usefull e.g. to allow the specification of a printer in the usual manner with the option -P like -Php4m. It is necessary, that no such option appears as the prefix of any other option. This is checked automatically.
Option format:
Only one kind of option format is recognized, i.e. no distinction is made between long and short option. All options start with a hyphen ('-'). Nevertheless can an option be one or several characters long. A minor disadvantage resulting from this, is that several options, each one consisting of a single character, can't be collected e.g. -a -e can not be expressed as -ae.
Numeric format:
In order to specify a negative number as an argument to a BLANK option an additional hyphen ('-') has to be given in order to distingush the number from an option string. More generally, every argument starting with a hyphen, has to be specified with one additional hyphen. This does not apply to NO_BLANK options.

In order to make use of the class an array has to be defined consisting of OptionDescriptions containing the option strings to be recognized together with the necessary specifications. E.g.:

// Number of arguments to be recognized
const int arg_desc_size = 4;

OptionDescription arg_desc[arg_desc_size] = { 
   {"'option'", BLANK/NO_BLANK, "'default_argument'", "'usage'"}
   {"i", BLANK, NIL, "input file name"},
   {"o", BLANK, "result.dat", "output file name (default `result.dat'"},
   {"rho", BLANK, "0.15", "Processing time (default 0.15)"}
   {"P", NO_BLANK, "hp4m", 
    "Printer (stdout if not specified, default hp4m)"}
};

const int mandatory = 1;
const int positional = 2;

// Forward declartion of `user_function' to allow specification in
// initialization of `args'
static void user_function(int argc, char **argv);

CNParseArgsList args = {
    arg_desc_size, arg_desc, mandatory, positional, user_function
};

In the example above, the program is designed to take four arguments, the first two being positional, the first one also mandatory, and the fourth one must be specified without blank. Valid invocations of the program include:

prog infile -Php4w
prog infile outfile -P 
prog -o outfile infile

In order to create an object of class CNParseArgs an object of struct CNParseArgsList has to be defined as shown above. The pointer to the user supplied function (*usage_func) may be given as NIL. Then the default usage function is called if neccessary. This default function is accessible to the user as the static member function static void CNParseArgs::usage_screen(char * name, CNParseArgsList &args).

In the main function of the program the object args of type CNParseArgsList is passed in the call of the constructor of CNParseArgs:

int main(int argc, char **argv) {
    CNParseArgs parse_args(argc, argv, args);
}

The constructor of the object parse_args parses the array argv and (if the syntax is correct) the address of each argument string given in argv is written into args.args_array[..].argument_string of the corresponding option.

If an option is not specified at all, the value NIL is assigned to the corresponding [..].argument_string.

To allow easy access to the argument_strings, the operator `[..]' is overloaded in the class and returns the value of args.args_array[..].argument_string .

If an option is given, but no argument, the corresponding [..].argument_string holds the address of the string default_argument specified in arg_desc, i.e. it is set to the specified default.

In this way it is possible, to distinguish whether an option has or has not been specified, e.g.:

    if (args.args_array[3].argument_string == NIL){
        // option -P not specified 
        // print to stdout
    } else {
        // print to device given in args.args_array[3].argument_string
        // this will be the default `hp4m' if only -P was specified
        // without an argument.
    }

The member function void CNParseArgs::override_nil(int first_arg, int last_arg = 0) can be used to assign the default string also if an option has not been specified at all, i.e. if it contains NIL, e.g. in the above case:

    parse_args.override_nil(0,2);

Thus the arguments of the first three options in the above example are assigned their default values if they are not specified. If last_arg equals `0', only the argument string of option first_arg is overriden with the default value (provided that it contained NIL before!).

As shown in the example above, a default string can not be specified for a mandatory option and must instead be initialized with NIL. This is checked by the constructor.

Syntax Rules

If an option is not specified at all, NIL is returned. If an option is given, but no argument, the default is returned. Thus it is possible to distinguish an option not specified from one specified but without an argument.

If args.args_array[i].blank equals BLANK the argument has to be separated from the option string by white space characters. If it equals NO_BLANK the option must be followed immediately by the argument without any separating character. Such an option must not occur as the prefix of any other argument in the list. This is checked by the program. If the same option string is specified more than once the result is undefined.

A - as the first character of an argument has to be given as --. This is necessary to allow the specification of negative numbers as arguments. The pointer which is returned in args.args_array[i].argument_string is pointing to the second -. Thus the argument can directly be parsed semantically!

The first mandatory_args arguments of args.args_array have to be specified, otherwise the program exits (as long as usage_func is NIL) and prints a usage text created automatically from the parameters given in args. If the pointer usage_func is different from NIL, that function is called.

The number positional_args of arguments may be specified without a preceding option string.

If an argument is specified several times for the same option, the last specification is valid.

Implementation constraints

It is not possible to specify an empty string `""' for a positional argument without specifying the option.

Depending on which number of `mandatory_args' and `positional_args' is smaller this number of the first arguments is as well mandatory as positional. It is not possible to specify the positional and mandatory property separately for these arguments.

Constructors

CNParseArgs();
Not yet implemented
CNParseArgs(CNParam *);
Not yet implemented
CNParseArgs (int argc, char **argv, CNParseArgsList &args)
Initializes CNParseArgs.

In addition to the member functions required by CNCL, CNParseArgs provides:

static void usage_screen(char * prog_name, CNParseArgsList &args);
This function is called as appropriate, if the element (*usage_func) in args equals NIL. It writes all possible option switches (defined by the user in the instance of OptionDescription) together with their meanings and the syntax rules to standard output. The user may also call this function from his own program as it is defined in the public part of the class.
void override_nil(int first_arg, int last_arg = 0);
Those argument strings contained in the instance of CNParseArgsList that contain the value NIL are set to the default string. This is done starting with element first_arg and ending with element last_arg. If last_arg equals 0 only element first_arg is processed.
char * operator[](int index);
Returns the pointer to the argument string number `index'.

The following template is also defined in ParseArgs.h to allow an easy parsing of numerical arguments.

template <class T> void assign_from_string(const char *string, T &input) {
// Reads input from `string' and assigns the value to the referent of 
// `input'. The string stream object is only created as a temporary
// and will be destructed as the statement is finished.
  istrstream(string, strlen(string)) >> input;
}

Example of use:

    double rho
    assign_from_string(args.args_array[2].argument_string, rho);

or equivalently:

    assign_from_string(parse_args[2], rho);


Go to the first, previous, next, last section, table of contents.