NNARGS(3)

NAME
nnargs - command line parsing package nnargs, nnargs_part, nnargs_from_file, fill_argv, nnargs_print_table, nnargs_print_flags, nnargs_get_flags, nnargs_get_part_flags, nnargs_get_int_list, nnargs_get_double_list, nnargs_get_float_list, nnargs_get_string_list, nnargs_get_int_alloc_list, nnargs_get_double_alloc_list, nnargs_get_float_alloc_list, nnargs_get_string_alloc_list, nnargs_combine_argtabs, nnargs_free_argtab

SYNOPSIS
#include <stdio.h>
#include <nnlib.h>

int nnargs(argc, argv, tabp, tabsize)
int argc, tabsize;
char **argv;
ARG *tabp;

int nnargs_part(argc, argv, tabp, tabsize)
int argc, tabsize;
char **argv;
ARG *tabp;

int nnargs_from_file(dfile, dname, tabp, tabsize)
FILE *dfile;
char *dname;
ARG *tabp;
int tabsize;

int fill_argv(argv, fp, fname)
char **argv;
FILE *fp;
char *fname;

void nnargs_print_table(tabp, tabsize, fp)
ARG *tabp;
int tabsize;
FILE *fp;

char *nnargs_get_flags(tabp, tabsize)
ARG *tabp;
int tabsize;

char *nnargs_get_part_flags(tabp, tabsize)
ARG *tabp;
int tabsize;

void nnargs_print_flags(tabp, tabsize, fp)
ARG *tabp;
int tabsize;
FILE *fp;

int nnargs_get_double_list(string, array, length)
char *string;
double *array;
int length;

int nnargs_get_float_list(string, array, length)
char *string;
float *array;
int length;

int nnargs_get_int_list(string, array, length)
char *string;
int *array, length;

int nnargs_get_string_list(string, array, length)
char *string, **array;
int length;

double * nnargs_get_double_alloc_list(string)
char *string;

float *nnargs_get_float_alloc_list(string)
char *string;

int *nnargs_get_int_alloc_list(string)
char *string;

char **nnargs_get_alloc_string_list(string)
char *string;

void nnargs_combine_argtabs(first_tab, first_size,
second_tab, second_size, new_tab, new_size)
ARG *first_tab, *second_tab, **new_tab;
int first_size, second_size, *new_size;

void nnargs_free_argtab(tabp, size)
ARG *tabp;
int size;

DESCRIPTION
nnargs is a package which allows programs to define, interpret, and produce labeled argument lists. There are three issues in using nnargs: How to define arguments used by the program; How to enter arguments on the command line; How to parse an argument list given to a program.

ARGUMENT TABLE
    Below is an example argument table illustrating the use of each nnargs type. Each "row" in the table has the following entries:
    {name, type, pointer to variable, help text, low value, high value}

    name
        The string the user will use for setting the value of the variable. The string must have no spaces in it.

    type
        The type of the argument. The available nnargs types and their corresponding C types:
            INT    int
            FLOAT    float
            DOUBLE    double
            STRING    char *
            BOOLEAN or FLAG    int
            CHAR    char
            INT_LIST    int *
            INT_ALLOC_LIST    int *
            FLOAT_LIST    float *
            FLOAT_ALLOC_LIST    float *
            DOUBLE_LIST    double *
            DOUBLE_ALLOC_LIST    double *
            STRING_LIST    char **
            STRING_ALLOC_LIST    char **

    pointer to variable
        A pointer to the static or global variable where the value of each argument is stored. This pointer must be of type (int *).

    help text
        A string which explains the use of each argument and the values it can hold

    low value, high value
        For types INT, FLOAT, and DOUBLE, the lowest and highest values the argument can hold. Attempts to set the variable to values outside the allowed range result in a fatal error. For types STRING_LIST, INT_LIST, FLOAT_LIST, and DOUBLE_LIST, low value is the maximum number of entries in the list. These two fields are optional.

    EXAMPLE:
        static int d = 12, y = 1992;
        static char *m = "August";
        static char *names[6] =
            {"2", "Stephanie", "Kukolich"};
        static char **cousins = NULL;
        static char initial = 'D';
        static int powers[128] = {3, 2, 4, 8};
        static int *fibonacci = NULL;
        static float weight = 8.1;
        static float lengths[3] = {2.0, 20.125, 8.2};
        static float *quantities = NULL;
        static double pi = 3.14159265358;
        static double constants[6] =
            {5, 0, 1, 2, 0.414728, 6.022e23};
        static double *more_constants = NULL;
        static int male = 0;
        static ARG argtab[] =
        {{"year", INT, &y, "birth year"},
         {"day", INT, &d, "day of month of birth", 1, 31},
         {"month", STRING, (int *)&m, "name of birth month"},
         {"name", STRING_LIST, (int *)names, "full name", 5},
         {"cousins", STRING_ALLOC_LIST, (int *)&cousins, "first names of cousins"},
         {"initial", CHAR, (int *)&initial,
        "initial of favorite toy name"},
         {"powers", INT_LIST, powers, "127 powers of two, or some other number", 127},
         {"fibonacci", INT_ALLOC_LIST, (int *)&fibonacci, "as many fibonacci numbers as you want"},
         {"weight", FLOAT, (int *)&weight, "birth weight"},
         {"lengths", FLOAT_LIST, (int *)lengths,
            "length, head circumference, in inches", 2},
         {"quantities", FLOAT_ALLOC_LIST, (int *)&quantities, "ounces eaten per meal"},
         {"male", BOOLEAN, &male, "default: female"},
         {"pi", DOUBLE, (int *)&pi,
        "favorite estimate of pi", 3, 4},
         {"constants", DOUBLE_LIST, (int *)constants,
        "up to 4 of your favorite constants", 4},
         {"more_constants", DOUBLE_ALLOC_LIST, (int *)&more_constants,
         "as many more favorite constants as you want"}, };
        #define TABSIZE (sizeof(argtab)/sizeof(ARG))
        main(argc, argv)
        int argc;
        char **argv;
        {
            int i,j;
            argc = nnargs(argc, argv, argtab, TABSIZE);
            /* the arguments in argtab have now been set to
            the values specified on the command line */

            if(male) printf("He is");
            else printf("She is");
            i = atoi(name[0]);
            j = 1;
            while(j <= i) printf(" %s",names[j++]);
            printf(", born on %s %d, %d.", m, d, y);
        }
The macro TABSIZE is used in many of the calls to the nnargs functions.

Some notes on argument values:
    Integer strings are interpreted as decimal, octal, or hexadecimal. If the first two characters are 0x, the number is interpreted as hexadecimal. The letters [a-f] can be upper or lower case. If the first character is a 0 but the second is not x, the number is interpreted as octal. Otherwise the number is interpreted as decimal. The minus sign comes first for negative integers of all three types.

    The static arrays used for storage by the LIST types are somewhat unusual. The first entry is the number of entries in the list. For a STRING_LIST, that number is a string which shows that number. It must be translated by atoi() to be used by the program. The remaining entries are the list itself. Thus, there are N+1 entries in a list array. The length, N, is in A[0]. The list is in A[1]-A[N].

    The ALLOC_LIST types differ from the older LIST types in one significant way. Where the LIST types store data in static arrays which are created at compile time, the ALLOC_LIST types store data in dynamically allocated arrays. To the user, the difference is transparent. To the programmer, the ALLOC_LIST types can store arbitrarily long lists where the maximum list length is hard-coded for the LIST types. It is more important, however, that the programmer check the actual length of the allocated arrays and be careful not to overrun the ends. This care was not always necessary with the static arrays.

VIEWING ARGUMENTS AND DEFAULT VALUES
    To see the contents of the argument table above, the user would type
    sample --
    or
    sample -help
    All of the available arguments and their default values would be shown. These default values are the values of the variables at the time that arguments are interpreted.

ENTERING ARGUMENTS FROM COMMAND LINE
    A call to the sample program might look like this:

    sample -name Amos-William-Meeks -initial R \
    -day 1 -phone 617:648:8225 -weight 7.5 \
    -lengths 18,8.2 -male

    He is Amos William Meeks, born on August 1, 1992

    Because the month, year, pi, and constants flags are not given, the default values for the variables m, y, pi, and constant are used. If a flag is used which is not in the argument table, a fatal error will result. The argument table will be printed, as well as the name of the rejected argument.

    List arguments
        For all lists, the argument following the name must be a comma or colon delimited list. For a string list, a dash is also allowed as a list delimiter.

INTERPRETING ARGUMENTS

SUB-ROUTINES

    int nnargs()
        Interprets an argument list stored in argv. The interpreted flags and arguments are stripped from argv and argc is decremented accordingly. The allowable arguments are given in tabp. The length of the argument table is tabsize. If an argument is given which is not in tabp a fatal error will occur. The new value for argc is returned.

    int nnargs_part()
        Parses those arguments in argv which belong to the argument table tabp. This routine is the same as nnargs(), with one exception. Arguments which are not included in the argument table do not cause a fatal error. nnargs_part() allows the user to enter arguments from several argument tables on the same command line. It is recommended that nnargs() be used to parse the arguments on the last table, so that the user can be warned if an argument was on none of the tables used.

    int nnargs_from_file()
        Reads a "command" from the file dfile and interprets the flags present in the same way nnargs() does. The "command" is formatted as it would be in a shell script, a command name followed by flags. If the "command" takes up more than one line, each line but the last one should have as its last character a backslash, "\". The first line with no backslash is taken to be the last line of the "command".

    int fill_argv()
        This command reads a "command" from a file and stores the strings in the command in the array argv. The "command" can take up more than one line provided that each line but the last has as its last character a backslach, "\". The first line with no backslash is taken to be the last line of the "command". fill_argv() returns the number of strings found on the "command" line.

    void nnargs_print_table()
        This command prints to the file fp all arguments in the table tabp and their current settings. The format is the same as that shown when <program> -- or <program> -help is typed. The name of each argument, the type, descriptive text, and the value are all printed. For integer, float, or double arguments, upper and lower limits for the value are printed if one or both are non-zero. Finally, if the argument is one of the list types and there is a specified maximum length, that is given.

    char *nnargs_get_flags()
        Returns a string which contains all flags in the table tabp. The flags are set to the values of their arguments. This string can be printed to a shell script as a call to the program which use this argument table.

    char *nnargs_get_part_flags()
        Returns a string which contains all flags in the table tabp. Just as with nnargs_get_flags, the flags are set to the values of their arguments. The last character on the last line is a backslash (\) which allows the user to include flags from more than one argument table in a single "command" string.

    void nnargs_print_flags()
        Prints to the file fp the setting of all the arguments in the table tabp, including unset BOOLEAN flags. There are no backslashes (\) at the ends of lines, so the string written to the file cannot be used for interpretation by the shell or by nnargs_from_file().

    int nnargs_get_double_list()
    int nnargs_get_float_list()
    int nnargs_get_int_list()
    int nnargs_get_string_list()
        Interprets string as a list of the appropriate type. Fills array with the values in the list. length is the maximum number of entries which can be places in array.

    double * nnargs_get_double_alloc_list()
    float * nnargs_get_float_alloc_list()
    int * nnargs_get_int_alloc_list()
    char ** nnargs_get_string_alloc_list()
        Interprets string as a list of the appropriate type. Allocates an array large enough to hold the list represented by the string and then fills the allocated array with the values in the list. For a string list, new strings are allocated and the values found in string are copied into the newly allocated strings. The allocate array is then returned.

    void nnargs_combine_argtabs()
        Allocates an argument table which has first_size + second_size entries in it. The arguments in first_tab and second_tab are copied into this new table. The pointer to the new table is stored in new_tab and the size is stored in new_size .

    void free_argtab()
        Free an allocated argument table.

SEE ALSO
errors(3)

HISTORY
First written 9 February 1993
Modified 23 June 1994, added allocated lists and combine_argtabs

BUGS
If the command line has a negative number which is not asscociated with a flag, and that number does not start with a digit [0..9], the number will be interpreted as a flag and may cause a fatal error.