scanargs(argc, argv, format [, pointer]... )
int argc;
char *argv[];
char *format;
Scanargs expects as its parameters an argument count argc, a pointer to an argument list argv (see exec(2) ), a control string format, described below, and a set of pointer arguments indicating where the converted output should be stored.
The control string contains specifications, which are used to direct interpretation of argument sequences. It contains the necessary information to describe an acceptable syntax for the argument list, and the expected meaning of each argument.
If the scanning fails it will print a cryptic message telling why it failed, and generate a usage message from the control string.
The control string is composed of two parts:
Name: The first characters in the string are assumed to be the calling name of the program being executed. This is used for generation of usage messages, but is otherwise ignored. If this field is a % sign, it is replaced with the contents of argv[0] in the message.
Conversions: Following the name, an optional list of conversion specifications is given, with separating spaces. The structure of a conversion specification:
label_key_conversion
consists of a label which is a string of non-space characters describing the acceptable argument, a key which may be either of
The conversion character indicates the interpretation of the argument; the corresponding pointer parameter must be of a restricted type.
The following conversion characters are supported:
The - may be followed immediately by more label_key_conversion specifications. These should not be separated by blanks and should not contain any - specifications. They will be processed only if the flag argument is scanned. This allows optional specification of parameters corresponding to a flag (e.g. -f file ). Corresponding arguments on the command line must appear between the flag which introduces them and the next flag in the command line.
A string or numeric conversion character may be preceded by a `*' or a `,' to indicate that a list of such arguments is expected. If `,' is used, then the AT&T proposed argument standard is followed, and a single string is expected, with the individual list elements separated by commas or spaces. Two commas in a row will produce a null entry (0 if numeric, zero-length string if string conversion), but multiple spaces, and spaces following a comma, are taken as a single separator. If `*' is specified, then multiple arguments are parsed to produce the list. A format specifier with a `*' or a `,' takes two arguments. The first is an int pointer, the number of items in the list is returned here. The second is a pointer to pointer to the correct data type for the format specifier. A pointer to the list of arguments is returned here.
The scanner will process the control string from left to right, and where there are multiple conversions of the same type, they will be assigned one to one with their order of occurrence in the argument list. Where the order of the arguments is not ambiguous in the control string, they may occur in any order in the argument list. (ie. A decimal number will not be confused with a flag, but may be confused with an octal number or another decimal number. So if an octal and a decimal number are to be arguments, their order will determine their conversion, while a decimal number and a flag as arguments may occur in any order and still be converted correctly.)
An argument list that does not match the requirements of the control string will cause the printing of a short message telling why, and a message telling what the correct usage is. This usage is gleaned from the control string, and the labels are used directly. The labels should be both terse and descriptive! Spaces, tabs, and newlines in the format string will be reproduced in the usage message, and can be used for effective prettyprinting. A single tab (following a newline) will indent the line directly under the command name in the usage message.
The scanargs function returns 1 when the argument list matched
the requirements of the control string, and returns 0 if there was a failure.
Parameters for any conversions not matched are left untouched.
For example, the call
int i; double x; char *name;
scanargs(argc, argv, "% decimal%d floating%F file%s", &i, &x, &name );
in a C program executed by the shell command
% program 10 3.5397 inputfile
will assign to i the value 10, x the value 3.5397, and name will point to the string "inputfile".
If the program was executed by the shell command
% program 3.4 .7 inputfile
the following would be printed on the standard error:
extra arguments not processed
usage : program [decimal] [floating] [file]
because 3.4 matches the type of 'floating' and .7 matches the type of 'file', leaving inputfile unmatched.
Finally, executing the command
% program 10
This call could be used for the diff(1) command
int blanks; int flags; char *file1; char *file2;
scanargs(argc, argv, "diff b%- efh%- file1!s file2!s", &blanks, &flags, &file1, &file2 );
and would only allow one of either -e, -f, or -h to be chosen optionally, with -b as an independent option. File1 and file2 are both required. The usage message for this version of diff would be
usage : diff [-b] -{efh} file1 file2
This call could be used for a simplified version of the sed(1) command
int efile; int noprint; char *script;
char *file1; char *file2;
scanargs(argc, argv, "sed n%- f%-editfile!s script%s file%s", &noprint, &efile, &file1, &script, &file2 );
If the -f option is specified, then a file name must be given as the next string argument. The usage message for this version of sed would be
usage : sed [-n] [-f editfile] [script] file
Further notes on putting together a format string:
It is possible for conditional
arguments to be confused with arguments which stand alone. For this reason,
it is recommended that all flags (and associated conditional arguments)
be specified first in the scanargs format string. This ordering is not
necessary for the command line arguments, however. The only case which
could still cause confusion if these rules are followed is illustrated
below:
format string: "prog d%-num%d othernum%d"
command line: prog -d 9
prog 9 -d
or prog -d -- 9
Note that if the format string in the above example were
"prog othernum%d d%-num%d"
prog -d 9would match othernum with 9, leaving nothing to match num.