Our policy is to have a simple function to parse the command line arguments
passed from Tcl. This should massage the arguments into a format usable by a
separate (from Tcl) C or Fortran function which does the actual work. This
clearly separates out the Tcl interface from the algorithms. The parsing will
be done in the function registered with the Tcl interpreter. In our example
this is tcl_composition
.
The latest Tcl/Tk release provides functions for easing the parsing of command
line arguments. In the future we may switch to using this scheme, but at
present we use (and document) our own methods. A quick overview of this is
that we declare a structure to hold the argument results, a structure to
define the available command line parameters, and then call the
parse_args
or gap_parse_args
function. Note that it is entirely
up to the author of the package code for the arguments should be processed.
Firstly we need to include the `cli_arg.h' file. Secondly declare a
structure containing the argument results. The structure does not need to be
referenced outside of this file and so need not be in a public header file.
Next we need a structure of type cli_args[]
to specify the mapping of
command line argument strings to argument result addresses. The
cli_args
structure is defined as follows.
typedef struct { char *command; /* What to recognise, including the '-' symbol */ int type; /* ARG_??? */ int value; /* Set if this argument takes an argument */ char *def; /* NULL if non optional argument */ int offset; /* Offset into the 'result' structure */ } cli_args;
Command is a text string holding the option name, such as "-file".
The last entry in the argument array should have a command of
NULL
.
Value is either 0 or 1 to indicate whether an extra argument is required after the command line option. A value of 1 indicates that an extra argument is needed.
Type specifies the type of this extra argument. It can be one of
ARG_INT
, ARG_STR
, ARG_ARR
, ARG_FLOAT
and (for Gap4
only) ARG_IO
to represent types of int
, char *
,
char []
, float
and GapIO *
. An option with no extra
argument must have the type of ARG_INT
as in this case the stored value
will be 0 or 1 to indicate whether the option was specified.
Of the above types, ARG_ARR
requires a better description. Options of
this type are character arrays where the option argument is copied into the
array. The value field for this type only specifies the length of the
array. Finally the offsetofa
macro instead of the offsetof
macro
(see below) must be used for the offset structure field. This type will
possibly be removed in the future in favour of keeping ARG_STR
. For
ARG_STR
the result is a character pointer which is set to the option
argument. This requires no bounds checking and can use the standard
offsetof
macro.
Def specifies the default value for this option. If the option takes no
extra argument or if it takes an extra argument and no default is suitable,
then NULL
should be used. Otherwise def
is a text string, even
in the case of ARG_INT
in which case it will be converted to integer if
needed.
Offset specifies the location within the results structure to store the
result. The offsetof
macro can be used to find this location. An
exception to this is the ARG_ARR
type where the offsetofa
macro needs to be used instead (with the same syntax).
For our composition package we will have the following two structures.
typedef struct { GapIO *io; char *ident; } test_args; test_args args; cli_args a[] = { {"-io", ARG_IO, 1, NULL, offsetof(test_args, io)}, {"-contigs", ARG_STR, 1, NULL, offsetof(test_args, ident)}, {NULL, 0, 0, NULL, 0} };
So we have two command line options, -io and -contigs, both of which take
extra arguments. These are stored in args.io
and args.ident
respectively. The last line indicates the end of the argument list.
Once we've defined the structures we can actually process the process the
arguments This is done using either parse_args
or
gap_parse_args
. The latter of these two is for Gap4 only and is the
only one which understands the ARG_IO
type. The functions take four
arguments which are the address of the cli_args[]
array, the address
of the result structure, and the argc
and argv
variables. The
functions returns -1 for an error and 0 for success.
if (-1 == gap_parse_args(a, &args, argc, argv)) { return TCL_ERROR; }