# Copyright (c) 1990-1992 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#
=head1 NAME
Tk_ParseArgv - process command-line options
=for category C Programming
=head1 SYNOPSIS
B<#include E<lt>tk.hE<gt>>
int
B<Tk_ParseArgv>(I<interp, tkwin, argcPtr, argv, argTable, flags>)
=head1 ARGUMENTS
=over 4
=item Tcl_Interp *interp (in)
Interpreter to use for returning error messages.
=item Tk_Window tkwin (in)
Window to use when arguments specify Tk options. If NULL, then
no Tk options will be processed.
=item int argcPtr (in/out)
Pointer to number of arguments in argv; gets modified to hold
number of unprocessed arguments that remain after the call.
=item char **argv (in/out)
Command line arguments passed to main program. Modified to
hold unprocessed arguments that remain after the call.
=item Tk_ArgvInfo *argTable (in)
Array of argument descriptors, terminated by element with
type TK_ARGV_END.
=item int flags (in)
If non-zero, then it specifies one or more flags that control the
parsing of arguments. Different flags may be OR'ed together.
The flags currently defined are TK_ARGV_DONT_SKIP_FIRST_ARG,
TK_ARGV_NO_ABBREV, TK_ARGV_NO_LEFTOVERS, and TK_ARGV_NO_DEFAULTS.
=back
=head1 DESCRIPTION
B<Tk_ParseArgv> processes an array of command-line arguments according
to a table describing the kinds of arguments that are expected.
Each of the arguments in I<argv> is processed in turn: if it matches
one of the entries in I<argTable>, the argument is processed
according to that entry and discarded. The arguments that do not
match anything in I<argTable> are copied down to the beginning
of I<argv> (retaining their original order) and returned to
the caller. At the end of the call
B<Tk_ParseArgv> sets I<*argcPtr> to hold the number of
arguments that are left in I<argv>, and I<argv[*argcPtr]>
will hold the value NULL. Normally, B<Tk_ParseArgv>
assumes that I<argv[0]> is a command name, so it is treated like
an argument that doesn't match I<argTable> and returned to the
caller; however, if the TK_ARGV_DONT_SKIP_FIRST_ARG bit is set in
I<flags> then I<argv[0]> will be processed just like the other
elements of I<argv>.
B<Tk_ParseArgv> normally returns the value TCL_OK. If an error
occurs while parsing the arguments, then TCL_ERROR is returned and
B<Tk_ParseArgv> will leave an error message in I<interp-E<gt>result>
in the standard Tcl fashion. In
the event of an error return, I<*argvPtr> will not have been
modified, but I<argv> could have been partially modified. The
possible causes of errors are explained below.
The I<argTable> array specifies the kinds of arguments that are
expected; each of its entries has the following structure:
typedef struct {
char *key;
int type;
char *src;
char *dst;
char *help;
} Tk_ArgvInfo;
The I<key> field is a string such as ``-display'' or ``-bg''
that is compared with the values in I<argv>. I<Type>
indicates how to process an argument that matches I<key>
(more on this below). I<Src> and I<dst> are additional
values used in processing the argument. Their exact usage
depends on I<type>, but typically I<src> indicates
a value and I<dst> indicates where to store the
value. The B<char *> declarations for I<src> and I<dst>
are placeholders: the actual types may be different. Lastly,
I<help> is a string giving a brief description
of this option; this string is printed when users ask for help
about command-line options.
When processing an argument in I<argv>, B<Tk_ParseArgv>
compares the argument to each of the I<key>'s in I<argTable>.
B<Tk_ParseArgv> selects the first specifier whose I<key> matches
the argument exactly, if such a specifier exists. Otherwise
B<Tk_ParseArgv> selects a specifier for which the argument
is a unique abbreviation. If the argument is a unique abbreviation
for more than one specifier, then an error is returned. If there
is no matching entry in I<argTable>, then the argument is
skipped and returned to the caller.
Once a matching argument specifier is found, B<Tk_ParseArgv>
processes the argument according to the I<type> field of the
specifier. The argument that matched I<key> is called ``the matching
argument'' in the descriptions below. As part of the processing,
B<Tk_ParseArgv> may also use the next argument in I<argv>
after the matching argument, which is called ``the following
argument''. The legal values for I<type>, and the processing
that they cause, are as follows:
=over 4
=item B<TK_ARGV_END>
Marks the end of the table. The last entry in I<argTable>
must have this type; all of its other fields are ignored and it
will never match any arguments.
=item B<TK_ARGV_CONSTANT>
I<Src> is treated as an integer and I<dst> is treated
as a pointer to an integer. I<Src> is stored at I<*dst>.
The matching argument is discarded.
=item B<TK_ARGV_INT>
The following argument must contain an
integer string in the format accepted by B<strtol> (e.g. ``0''
and ``0x'' prefixes may be used to specify octal or hexadecimal
numbers, respectively). I<Dst> is treated as a pointer to an
integer; the following argument is converted to an integer value
and stored at I<*dst>. I<Src> is ignored. The matching
and following arguments are discarded from I<argv>.
=item B<TK_ARGV_FLOAT>
The following argument must contain a floating-point number in
the format accepted by B<strtol>.
I<Dst> is treated as the address of an double-precision
floating point value; the following argument is converted to a
double-precision value and stored at I<*dst>. The matching
and following arguments are discarded from I<argv>.
=item B<TK_ARGV_STRING>
In this form, I<dst> is treated as a pointer to a (char *);
B<Tk_ParseArgv> stores at I<*dst> a pointer to the following
argument, and discards the matching and following arguments from
I<argv>. I<Src> is ignored.
=item B<TK_ARGV_UID>
This form is similar to TK_ARGV_STRING, except that the argument
is turned into a Tk_Uid by calling B<Tk_GetUid>.
I<Dst> is treated as a pointer to a
Tk_Uid; B<Tk_ParseArgv> stores at I<*dst> the Tk_Uid
corresponding to the following
argument, and discards the matching and following arguments from
I<argv>. I<Src> is ignored.
=item B<TK_ARGV_CONST_OPTION>
This form causes a Tk option to be set (as if the B<option>
command had been invoked). The I<src> field is treated as a
pointer to a string giving the value of an option, and I<dst>
is treated as a pointer to the name of the option. The matching
argument is discarded. If I<tkwin> is NULL, then argument
specifiers of this type are ignored (as if they did not exist).
=item B<TK_ARGV_OPTION_VALUE>
This form is similar to TK_ARGV_CONST_OPTION, except that the
value of the option is taken from the following argument instead
of from I<src>. I<Dst> is used as the name of the option.
I<Src> is ignored. The matching and following arguments
are discarded. If I<tkwin> is NULL, then argument
specifiers of this type are ignored (as if they did not exist).
=item B<TK_ARGV_OPTION_NAME_VALUE>
In this case the following argument is taken as the name of a Tk
option and the argument after that is taken as the value for that
option. Both I<src> and I<dst> are ignored. All three
arguments are discarded from I<argv>. If I<tkwin> is NULL,
then argument
specifiers of this type are ignored (as if they did not exist).
=item B<TK_ARGV_HELP>
When this kind of option is encountered, B<Tk_ParseArgv> uses the
I<help> fields of I<argTable> to format a message describing
all the valid arguments. The message is placed in I<interp-E<gt>result>
and B<Tk_ParseArgv> returns TCL_ERROR. When this happens, the
caller normally prints the help message and aborts. If the I<key>
field of a TK_ARGV_HELP specifier is NULL, then the specifier will
never match any arguments; in this case the specifier simply provides
extra documentation, which will be included when some other
TK_ARGV_HELP entry causes help information to be returned.
=item B<TK_ARGV_REST>
This option is used by programs or commands that allow the last
several of their options to be the name and/or options for some
other program. If a B<TK_ARGV_REST> argument is found, then
B<Tk_ParseArgv> doesn't process any
of the remaining arguments; it returns them all at
the beginning of I<argv> (along with any other unprocessed arguments).
In addition, B<Tk_ParseArgv> treats I<dst> as the address of an
integer value, and stores at I<*dst> the index of the first of the
B<TK_ARGV_REST> options in the returned I<argv>. This allows the
program to distinguish the B<TK_ARGV_REST> options from other
unprocessed options that preceded the B<TK_ARGV_REST>.
=item B<TK_ARGV_FUNC>
For this kind of argument, I<src> is treated as the address of
a procedure, which is invoked to process the following argument.
The procedure should have the following structure:
=over 4
int
func(dst, key, nextArg)
char *dst;
char *key;
char *nextArg;
{
}
The I<dst> and I<key> parameters will contain the
corresponding fields from the I<argTable> entry, and
I<nextArg> will point to the following argument from I<argv>
(or NULL if there aren't any more arguments left in I<argv>).
If I<func> uses I<nextArg> (so that
B<Tk_ParseArgv> should discard it), then it should return 1. Otherwise it
should return 0 and B<TkParseArgv> will process the following
argument in the normal fashion. In either event the matching argument
is discarded.
=back
=item B<TK_ARGV_GENFUNC>
This form provides a more general procedural escape. It treats
I<src> as the address of a procedure, and passes that procedure
all of the remaining arguments. The procedure should have the following
form:
=over 4
int
genfunc(dst, interp, key, argc, argv)
char *dst;
Tcl_Interp *interp;
char *key;
int argc;
char **argv;
{
}
The I<dst> and I<key> parameters will contain the
corresponding fields from the I<argTable> entry. I<Interp>
will be the same as the I<interp> argument to B<Tcl_ParseArgv>.
I<Argc> and I<argv> refer to all of the options after the
matching one. I<Genfunc> should behave in a fashion similar
to B<Tk_ParseArgv>: parse as many of the remaining arguments as it can,
then return any that are left by compacting them to the beginning of
I<argv> (starting at I<argv>[0]). I<Genfunc>
should return a count of how many arguments are left in I<argv>;
B<Tk_ParseArgv> will process them. If I<genfunc> encounters
an error then it should leave an error message in I<interp-E<gt>result>,
in the usual Tcl fashion, and return -1; when this happens
B<Tk_ParseArgv> will abort its processing and return TCL_ERROR.
=back
=back
=head1 FLAGS
=over 4
=item B<TK_ARGV_DONT_SKIP_FIRST_ARG>
B<Tk_ParseArgv> normally treats I<argv[0]> as a program
or command name, and returns it to the caller just as if it
hadn't matched I<argTable>. If this flag is given, then
I<argv[0]> is not given special treatment.
=item B<TK_ARGV_NO_ABBREV>
Normally, B<Tk_ParseArgv> accepts unique abbreviations for
I<key> values in I<argTable>. If this flag is given then
only exact matches will be acceptable.
=item B<TK_ARGV_NO_LEFTOVERS>
Normally, B<Tk_ParseArgv> returns unrecognized arguments to the
caller. If this bit is set in I<flags> then B<Tk_ParseArgv>
will return an error if it encounters any argument that doesn't
match I<argTable>. The only exception to this rule is I<argv[0]>,
which will be returned to the caller with no errors as
long as TK_ARGV_DONT_SKIP_FIRST_ARG isn't specified.
=item B<TK_ARGV_NO_DEFAULTS>
Normally, B<Tk_ParseArgv> searches an internal table of
standard argument specifiers in addition to I<argTable>. If
this bit is set in I<flags>, then B<Tk_ParseArgv> will
use only I<argTable> and not its default table.
=back
=head1 EXAMPLE
Here is an example definition of an I<argTable> and
some sample command lines that use the options. Note the effect
on I<argc> and I<argv>; arguments processed by B<Tk_ParseArgv>
are eliminated from I<argv>, and I<argc>
is updated to reflect reduced number of arguments.
/*
* Define and set default values for globals.
*/
int debugFlag = 0;
int numReps = 100;
char defaultFileName[] = "out";
char *fileName = defaultFileName;
Boolean exec = FALSE;
/*
* Define option descriptions.
*/
Tk_ArgvInfo argTable[] = {
{"-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag,
"Turn on debugging printfs"},
{"-N", TK_ARGV_INT, (char *) NULL, (char *) &numReps,
"Number of repetitions"},
{"-of", TK_ARGV_STRING, (char *) NULL, (char *) &fileName,
"Name of file for output"},
{"x", TK_ARGV_REST, (char *) NULL, (char *) &exec,
"File to exec, followed by any arguments (must be last argument)."},
{(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
(char *) NULL}
};
main(argc, argv)
int argc;
char *argv[];
{
...
if (Tk_ParseArgv(interp, tkwin, &argc, argv, argTable, 0) != TCL_OK) {
fprintf(stderr, "%s\n", interp->result);
exit(1);
}
/*
* Remainder of the program.
*/
}
Note that default values can be assigned to variables named in
I<argTable>: the variables will only be overwritten if the
particular arguments are present in I<argv>.
Here are some example command lines and their effects.
prog -N 200 infile # just sets the numReps variable to 200
prog -of out200 infile # sets fileName to reference "out200"
prog -XN 10 infile # sets the debug flag, also sets numReps
In all of the above examples, I<argc> will be set by B<Tk_ParseArgv> to 2,
I<argv>[0] will be ``prog'', I<argv>[1] will be ``infile'',
and I<argv>[2] will be NULL.
=head1 KEYWORDS
arguments, command line, options