Annotation of researchv10no/cmd/f2c/parse_args.c, revision 1.1

1.1     ! root        1: /****************************************************************
        !             2: Copyright 1990 by AT&T Bell Laboratories and Bellcore.
        !             3: 
        !             4: Permission to use, copy, modify, and distribute this software
        !             5: and its documentation for any purpose and without fee is hereby
        !             6: granted, provided that the above copyright notice appear in all
        !             7: copies and that both that the copyright notice and this
        !             8: permission notice and warranty disclaimer appear in supporting
        !             9: documentation, and that the names of AT&T Bell Laboratories or
        !            10: Bellcore or any of their entities not be used in advertising or
        !            11: publicity pertaining to distribution of the software without
        !            12: specific, written prior permission.
        !            13: 
        !            14: AT&T and Bellcore disclaim all warranties with regard to this
        !            15: software, including all implied warranties of merchantability
        !            16: and fitness.  In no event shall AT&T or Bellcore be liable for
        !            17: any special, indirect or consequential damages or any damages
        !            18: whatsoever resulting from loss of use, data or profits, whether
        !            19: in an action of contract, negligence or other tortious action,
        !            20: arising out of or in connection with the use or performance of
        !            21: this software.
        !            22: ****************************************************************/
        !            23: 
        !            24: /* parse_args
        !            25: 
        !            26:        This function will parse command line input into appropriate data
        !            27:    structures, output error messages when appropriate and provide some
        !            28:    minimal type conversion.
        !            29: 
        !            30:        Input to the function consists of the standard   argc,argv
        !            31:    values, and a table which directs the parser.  Each table entry has the
        !            32:    following components:
        !            33: 
        !            34:        prefix -- the (optional) switch character string, e.g. "-" "/" "="
        !            35:        switch -- the command string, e.g. "o" "data" "file" "F"
        !            36:        flags -- control flags, e.g.   CASE_INSENSITIVE, REQUIRED_PREFIX
        !            37:        arg_count -- number of arguments this command requires, e.g. 0 for
        !            38:                     booleans, 1 for filenames, INFINITY for input files
        !            39:        result_type -- how to interpret the switch arguments, e.g. STRING,
        !            40:                       CHAR, FILE, OLD_FILE, NEW_FILE
        !            41:        result_ptr -- pointer to storage for the result, be it a table or
        !            42:                      a string or whatever
        !            43:        table_size -- if the arguments fill a table, the maximum number of
        !            44:                      entries; if there are no arguments, the value to
        !            45:                      load into the result storage
        !            46: 
        !            47:        Although the table can be used to hold a list of filenames, only
        !            48:    scalar values (e.g. pointers) can be stored in the table.  No vector
        !            49:    processing will be done, only pointers to string storage will be moved.
        !            50: 
        !            51:        An example entry, which could be used to parse input filenames, is:
        !            52: 
        !            53:        "-", "o", 0, oo, OLD_FILE, infilenames, INFILE_TABLE_SIZE
        !            54: 
        !            55: */
        !            56: 
        !            57: #include <stdio.h>
        !            58: #ifndef NULL
        !            59: /* ANSI C */
        !            60: #include <stddef.h>
        !            61: #endif
        !            62: #include "parse.h"
        !            63: #include <math.h>           /* For atof */
        !            64: #include <ctype.h>
        !            65: 
        !            66: #define MAX_INPUT_SIZE 1000
        !            67: 
        !            68: #define arg_prefix(x) ((x).prefix)
        !            69: #define arg_string(x) ((x).string)
        !            70: #define arg_flags(x) ((x).flags)
        !            71: #define arg_count(x) ((x).count)
        !            72: #define arg_result_type(x) ((x).result_type)
        !            73: #define arg_result_ptr(x) ((x).result_ptr)
        !            74: #define arg_table_size(x) ((x).table_size)
        !            75: 
        !            76: #ifndef TRUE
        !            77: #define TRUE 1
        !            78: #endif
        !            79: #ifndef FALSE
        !            80: #define FALSE 0
        !            81: #endif
        !            82: typedef int boolean;
        !            83: 
        !            84: 
        !            85: char *lower_string (/* char [], char * */);
        !            86: 
        !            87: static char *this_program = "";
        !            88: 
        !            89: extern long atol();
        !            90: static int arg_parse (/* char *, arg_info * */);
        !            91: 
        !            92: 
        !            93: boolean parse_args (argc, argv, table, entries, others, other_count)
        !            94: int argc;
        !            95: char *argv[];
        !            96: arg_info table[];
        !            97: int entries;
        !            98: char *others[];
        !            99: int other_count;
        !           100: {
        !           101:     boolean arg_verify (/* argv, table, entries */);
        !           102:     void init_store (/* table, entries */);
        !           103: 
        !           104:     boolean result;
        !           105: 
        !           106:     if (argv)
        !           107:        this_program = argv[0];
        !           108: 
        !           109: /* Check the validity of the table and its parameters */
        !           110: 
        !           111:     result = arg_verify (argv, table, entries);
        !           112: 
        !           113: /* Initialize the storage values */
        !           114: 
        !           115:     init_store (table, entries);
        !           116: 
        !           117:     if (result) {
        !           118:        boolean use_prefix = TRUE;
        !           119:        char *argv0;
        !           120: 
        !           121:        argc--;
        !           122:        argv0 = *++argv;
        !           123:        while (argc) {
        !           124:            int index, length;
        !           125: 
        !           126:            index = match_table (*argv, table, entries, use_prefix, &length);
        !           127:            if (index < 0) {
        !           128: 
        !           129: /* The argument doesn't match anything in the table */
        !           130: 
        !           131:                if (others) {
        !           132: 
        !           133:                    if (*argv > argv0)
        !           134:                        *--*argv = '-'; /* complain at invalid flag */
        !           135: 
        !           136:                    if (other_count > 0) {
        !           137:                        *others++ = *argv;
        !           138:                        other_count--;
        !           139:                    } else {
        !           140:                        fprintf (stderr, "%s:  too many parameters: ",
        !           141:                                this_program);
        !           142:                        fprintf (stderr, "'%s' ignored\n", *argv);
        !           143:                    } /* else */
        !           144:                } /* if (others) */
        !           145:                argv0 = *++argv;
        !           146:                argc--;
        !           147:            } else {
        !           148: 
        !           149: /* A match was found */
        !           150: 
        !           151:                if (length >= strlen (*argv)) {
        !           152:                    argc--;
        !           153:                    argv0 = *++argv;
        !           154:                    use_prefix = TRUE;
        !           155:                } else {
        !           156:                    (*argv) += length;
        !           157:                    use_prefix = FALSE;
        !           158:                } /* else */
        !           159: 
        !           160: /* Parse any necessary arguments */
        !           161: 
        !           162:                if (arg_count (table[index]) != P_NO_ARGS) {
        !           163: 
        !           164: /* Now   length   will be used to store the number of parsed characters */
        !           165: 
        !           166:                    length = arg_parse(*argv, &table[index]);
        !           167:                    if (*argv == NULL)
        !           168:                        argc = 0;
        !           169:                    else if (length >= strlen (*argv)) {
        !           170:                        argc--;
        !           171:                        argv0 = *++argv;
        !           172:                        use_prefix = TRUE;
        !           173:                    } else {
        !           174:                        (*argv) += length;
        !           175:                        use_prefix = FALSE;
        !           176:                    } /* else */
        !           177:                } /* if (argv_count != P_NO_ARGS) */
        !           178:                  else
        !           179:                    *arg_result_ptr(table[index]) =
        !           180:                            arg_table_size(table[index]);
        !           181:            } /* else */
        !           182:        } /* while (argc) */
        !           183:     } /* if (result) */
        !           184: 
        !           185:     return result;
        !           186: } /* parse_args */
        !           187: 
        !           188: 
        !           189: boolean arg_verify (argv, table, entries)
        !           190: char *argv[];
        !           191: arg_info table[];
        !           192: int entries;
        !           193: {
        !           194:     int i;
        !           195:     char *this_program = "";
        !           196: 
        !           197:     if (argv)
        !           198:        this_program = argv[0];
        !           199: 
        !           200:     for (i = 0; i < entries; i++) {
        !           201:        arg_info *arg = &table[i];
        !           202: 
        !           203: /* Check the argument flags */
        !           204: 
        !           205:        if (arg_flags (*arg) & ~(P_CASE_INSENSITIVE | P_REQUIRED_PREFIX)) {
        !           206:            fprintf (stderr, "%s [arg_verify]:  too many ", this_program);
        !           207:            fprintf (stderr, "flags in entry %d:  '%x' (hex)\n", i,
        !           208:                    arg_flags (*arg));
        !           209:        } /* if */
        !           210: 
        !           211: /* Check the argument count */
        !           212: 
        !           213:        { int count = arg_count (*arg);
        !           214: 
        !           215:            if (count != P_NO_ARGS && count != P_ONE_ARG && count !=
        !           216:                    P_INFINITE_ARGS) {
        !           217:                fprintf (stderr, "%s [arg_verify]:  invalid ", this_program);
        !           218:                fprintf (stderr, "argument count in entry %d:  '%d'\n", i,
        !           219:                        count);
        !           220:            } /* if count != P_NO_ARGS ... */
        !           221: 
        !           222: /* Check the result field; want to be able to store results */
        !           223: 
        !           224:              else
        !           225:                if (arg_result_ptr (*arg) == (int *) NULL) {
        !           226:                    fprintf (stderr, "%s [arg_verify]:  ", this_program);
        !           227:                    fprintf (stderr, "no argument storage given for ");
        !           228:                    fprintf (stderr, "entry %d\n", i);
        !           229:                } /* if arg_result_ptr */
        !           230:        }
        !           231: 
        !           232: /* Check the argument type */
        !           233: 
        !           234:        { int type = arg_result_type (*arg);
        !           235: 
        !           236:            if (type < P_STRING || type > P_DOUBLE)
        !           237:                    fprintf(stderr,
        !           238:                        "%s [arg_verify]:  bad arg type in entry %d:  '%d'\n",
        !           239:                        this_program, i, type);
        !           240:        }
        !           241: 
        !           242: /* Check table size */
        !           243: 
        !           244:        { int size = arg_table_size (*arg);
        !           245: 
        !           246:            if (arg_count (*arg) == P_INFINITE_ARGS && size < 1) {
        !           247:                fprintf (stderr, "%s [arg_verify]:  bad ", this_program);
        !           248:                fprintf (stderr, "table size in entry %d:  '%d'\n", i,
        !           249:                        size);
        !           250:            } /* if (arg_count == P_INFINITE_ARGS && size < 1) */
        !           251:        }
        !           252: 
        !           253:     } /* for i = 0 */
        !           254: 
        !           255:     return TRUE;
        !           256: } /* arg_verify */
        !           257: 
        !           258: 
        !           259: /* match_table -- returns the index of the best entry matching the input,
        !           260:    -1 if no match.  The best match is the one of longest length which
        !           261:    appears lowest in the table.  The length of the match will be returned
        !           262:    in   length   ONLY IF a match was found.   */
        !           263: 
        !           264: int match_table (norm_input, table, entries, use_prefix, length)
        !           265: register char *norm_input;
        !           266: arg_info table[];
        !           267: int entries;
        !           268: boolean use_prefix;
        !           269: int *length;
        !           270: {
        !           271:     extern int match (/* char *, char *, arg_info *, boolean */);
        !           272: 
        !           273:     char low_input[MAX_INPUT_SIZE];
        !           274:     register int i;
        !           275:     int best_index = -1, best_length = 0;
        !           276: 
        !           277: /* FUNCTION BODY */
        !           278: 
        !           279:     (void) lower_string (low_input, norm_input);
        !           280: 
        !           281:     for (i = 0; i < entries; i++) {
        !           282:        int this_length = match (norm_input, low_input, &table[i], use_prefix);
        !           283: 
        !           284:        if (this_length > best_length) {
        !           285:            best_index = i;
        !           286:            best_length = this_length;
        !           287:        } /* if (this_length > best_length) */
        !           288:     } /* for (i = 0) */
        !           289: 
        !           290:     if (best_index > -1 && length != (int *) NULL)
        !           291:        *length = best_length;
        !           292: 
        !           293:     return best_index;
        !           294: } /* match_table */
        !           295: 
        !           296: 
        !           297: /* match -- takes an input string and table entry, and returns the length
        !           298:    of the longer match.
        !           299: 
        !           300:        0 ==> input doesn't match
        !           301: 
        !           302:    For example:
        !           303: 
        !           304:        INPUT   PREFIX  STRING  RESULT
        !           305: ----------------------------------------------------------------------
        !           306:        "abcd"  "-"     "d"     0
        !           307:        "-d"    "-"     "d"     2    (i.e. "-d")
        !           308:        "dout"  "-"     "d"     1    (i.e. "d")
        !           309:        "-d"    ""      "-d"    2    (i.e. "-d")
        !           310:        "dd"    "d"     "d"     2       <= here's the weird one
        !           311: */
        !           312: 
        !           313: int match (norm_input, low_input, entry, use_prefix)
        !           314: char *norm_input, *low_input;
        !           315: arg_info *entry;
        !           316: boolean use_prefix;
        !           317: {
        !           318:     char *norm_prefix = arg_prefix (*entry);
        !           319:     char *norm_string = arg_string (*entry);
        !           320:     boolean prefix_match = FALSE, string_match = FALSE;
        !           321:     int result = 0;
        !           322: 
        !           323: /* Buffers for the lowercased versions of the strings being compared.
        !           324:    These are used when the switch is to be case insensitive */
        !           325: 
        !           326:     static char low_prefix[MAX_INPUT_SIZE];
        !           327:     static char low_string[MAX_INPUT_SIZE];
        !           328:     int prefix_length = strlen (norm_prefix);
        !           329:     int string_length = strlen (norm_string);
        !           330: 
        !           331: /* Pointers for the required strings (lowered or nonlowered) */
        !           332: 
        !           333:     register char *input, *prefix, *string;
        !           334: 
        !           335: /* FUNCTION BODY */
        !           336: 
        !           337: /* Use the appropriate strings to handle case sensitivity */
        !           338: 
        !           339:     if (arg_flags (*entry) & P_CASE_INSENSITIVE) {
        !           340:        input = low_input;
        !           341:        prefix = lower_string (low_prefix, norm_prefix);
        !           342:        string = lower_string (low_string, norm_string);
        !           343:     } else {
        !           344:        input = norm_input;
        !           345:        prefix = norm_prefix;
        !           346:        string = norm_string;
        !           347:     } /* else */
        !           348: 
        !           349: /* First, check the string formed by concatenating the prefix onto the
        !           350:    switch string, but only when the prefix is not being ignored */
        !           351: 
        !           352:     if (use_prefix && prefix != NULL && *prefix != '\0')
        !           353:         prefix_match = (strncmp (input, prefix, prefix_length) == 0) &&
        !           354:                (strncmp (input + prefix_length, string, string_length) == 0);
        !           355: 
        !           356: /* Next, check just the switch string, if that's allowed */
        !           357: 
        !           358:     if (!use_prefix && (arg_flags (*entry) & P_REQUIRED_PREFIX) == 0)
        !           359:        string_match = strncmp (input, string, string_length) == 0;
        !           360: 
        !           361:     if (prefix_match)
        !           362:        result = prefix_length + string_length;
        !           363:     else if (string_match)
        !           364:        result = string_length;
        !           365: 
        !           366:     return result;
        !           367: } /* match */
        !           368: 
        !           369: 
        !           370: char *lower_string (dest, src)
        !           371: char *dest, *src;
        !           372: {
        !           373:     char *result = dest;
        !           374:     register int c;
        !           375: 
        !           376:     if (dest == NULL || src == NULL)
        !           377:        result = NULL;
        !           378:     else
        !           379:        while (*dest++ = (c = *src++) >= 'A' && c <= 'Z' ? tolower(c) : c);
        !           380: 
        !           381:     return result;
        !           382: } /* lower_string */
        !           383: 
        !           384: 
        !           385: /* arg_parse -- returns the number of characters parsed for this entry */
        !           386: 
        !           387: static int arg_parse (str, entry)
        !           388: char *str;
        !           389: arg_info *entry;
        !           390: {
        !           391:     int length = 0;
        !           392: 
        !           393:     if (arg_count (*entry) == P_ONE_ARG) {
        !           394:        char **store = (char **) arg_result_ptr (*entry);
        !           395: 
        !           396:        length = put_one_arg (arg_result_type (*entry), str, store,
        !           397:                arg_prefix (*entry), arg_string (*entry));
        !           398: 
        !           399:     } /* if (arg_count == P_ONE_ARG) */
        !           400:       else { /* Must be a table of arguments */
        !           401:        char **store = (char **) arg_result_ptr (*entry);
        !           402: 
        !           403:        if (store) {
        !           404:            while (*store)
        !           405:                store++;
        !           406: 
        !           407:            length = put_one_arg (arg_result_type (*entry), str, store++,
        !           408:                    arg_prefix (*entry), arg_string (*entry));
        !           409: 
        !           410:            *store = (char *) NULL;
        !           411:        } /* if (store) */
        !           412:     } /* else */
        !           413: 
        !           414:     return length;
        !           415: } /* arg_parse */
        !           416: 
        !           417: 
        !           418: int put_one_arg (type, str, store, prefix, string)
        !           419: int type;
        !           420: char *str;
        !           421: char **store;
        !           422: char *prefix, *string;
        !           423: {
        !           424:     int length = 0;
        !           425:     long L;
        !           426: 
        !           427:     if (store) {
        !           428:        switch (type) {
        !           429:            case P_STRING:
        !           430:            case P_FILE:
        !           431:            case P_OLD_FILE:
        !           432:            case P_NEW_FILE:
        !           433:                *store = str;
        !           434:                if (str == NULL)
        !           435:                    fprintf (stderr, "%s: Missing argument after '%s%s'\n",
        !           436:                            this_program, prefix, string);
        !           437:                length = str ? strlen (str) : 0;
        !           438:                break;
        !           439:            case P_CHAR:
        !           440:                *((char *) store) = *str;
        !           441:                length = 1;
        !           442:                break;
        !           443:            case P_SHORT:
        !           444:                L = atol(str);
        !           445:                *(short *)store = (short) L;
        !           446:                if (L != *(short *)store)
        !           447:                    fprintf(stderr,
        !           448:        "%s%s parameter '%ld' is not a SHORT INT (truncating to %d)\n",
        !           449:                            prefix, string, L, *(short *)store);
        !           450:                length = strlen (str);
        !           451:                break;
        !           452:            case P_INT:
        !           453:                L = atol(str);
        !           454:                *(int *)store = (int)L;
        !           455:                if (L != *(int *)store)
        !           456:                    fprintf(stderr,
        !           457:        "%s%s parameter '%ld' is not an INT (truncating to %d)\n",
        !           458:                            prefix, string, L, *(int *)store);
        !           459:                length = strlen (str);
        !           460:                break;
        !           461:            case P_LONG:
        !           462:                *(long *)store = atol(str);
        !           463:                length = strlen (str);
        !           464:                break;
        !           465:            case P_FLOAT:
        !           466:                *((float *) store) = (float) atof (str);
        !           467:                length = strlen (str);
        !           468:                break;
        !           469:            case P_DOUBLE:
        !           470:                *((double *) store) = (double) atof (str);
        !           471:                length = strlen (str);
        !           472:                break;
        !           473:            default:
        !           474:                fprintf (stderr, "put_one_arg:  bad type '%d'\n",
        !           475:                        type);
        !           476:                break;
        !           477:        } /* switch */
        !           478:     } /* if (store) */
        !           479: 
        !           480:     return length;
        !           481: } /* put_one_arg */
        !           482: 
        !           483: 
        !           484: void init_store (table, entries)
        !           485: arg_info *table;
        !           486: int entries;
        !           487: {
        !           488:     int index;
        !           489: 
        !           490:     for (index = 0; index < entries; index++)
        !           491:        if (arg_count (table[index]) == P_INFINITE_ARGS) {
        !           492:            char **place = (char **) arg_result_ptr (table[index]);
        !           493: 
        !           494:            if (place)
        !           495:                *place = (char *) NULL;
        !           496:        } /* if arg_count == P_INFINITE_ARGS */
        !           497: 
        !           498: } /* init_store */
        !           499: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.