Annotation of micropolis/src/tk/tkargv.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * tkArgv.c --
        !             3:  *
        !             4:  *     This file contains a procedure that handles table-based
        !             5:  *     argv-argc parsing.
        !             6:  *
        !             7:  * Copyright 1990 Regents of the University of California
        !             8:  * Permission to use, copy, modify, and distribute this
        !             9:  * software and its documentation for any purpose and without
        !            10:  * fee is hereby granted, provided that the above copyright
        !            11:  * notice appear in all copies.  The University of California
        !            12:  * makes no representations about the suitability of this
        !            13:  * software for any purpose.  It is provided "as is" without
        !            14:  * express or implied warranty.
        !            15:  */
        !            16: 
        !            17: #ifndef lint
        !            18: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkArgv.c,v 1.12 92/08/07 08:39:48 ouster Exp $ SPRITE (Berkeley)";
        !            19: #endif
        !            20: 
        !            21: #include "tkconfig.h"
        !            22: #include "tk.h"
        !            23: 
        !            24: /*
        !            25:  * Default table of argument descriptors.  These are normally available
        !            26:  * in every application.
        !            27:  */
        !            28: 
        !            29: static Tk_ArgvInfo defaultTable[] = {
        !            30:     {"-help",  TK_ARGV_HELP,   (char *) NULL,  (char *) NULL,
        !            31:        "Print summary of command-line options and abort"},
        !            32:     {NULL,     TK_ARGV_END,    (char *) NULL,  (char *) NULL,
        !            33:        (char *) NULL}
        !            34: };
        !            35: 
        !            36: /*
        !            37:  * Forward declarations for procedures defined in this file:
        !            38:  */
        !            39: 
        !            40: static void    PrintUsage _ANSI_ARGS_((Tcl_Interp *interp,
        !            41:                    Tk_ArgvInfo *argTable, int flags));
        !            42: 
        !            43: /*
        !            44:  *----------------------------------------------------------------------
        !            45:  *
        !            46:  * Tk_ParseArgv --
        !            47:  *
        !            48:  *     Process an argv array according to a table of expected
        !            49:  *     command-line options.  See the manual page for more details.
        !            50:  *
        !            51:  * Results:
        !            52:  *     The return value is a standard Tcl return value.  If an
        !            53:  *     error occurs then an error message is left in interp->result.
        !            54:  *     Under normal conditions, both *argcPtr and *argv are modified
        !            55:  *     to return the arguments that couldn't be processed here (they
        !            56:  *     didn't match the option table, or followed an TK_ARGV_REST
        !            57:  *     argument).
        !            58:  *
        !            59:  * Side effects:
        !            60:  *     Variables may be modified, resources may be entered for tkwin,
        !            61:  *     or procedures may be called.  It all depends on the arguments
        !            62:  *     and their entries in argTable.  See the user documentation
        !            63:  *     for details.
        !            64:  *
        !            65:  *----------------------------------------------------------------------
        !            66:  */
        !            67: 
        !            68: int
        !            69: Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags)
        !            70:     Tcl_Interp *interp;                /* Place to store error message. */
        !            71:     Tk_Window tkwin;           /* Window to use for setting Tk options.
        !            72:                                 * NULL means ignore Tk option specs. */
        !            73:     int *argcPtr;              /* Number of arguments in argv.  Modified
        !            74:                                 * to hold # args left in argv at end. */
        !            75:     char **argv;               /* Array of arguments.  Modified to hold
        !            76:                                 * those that couldn't be processed here. */
        !            77:     Tk_ArgvInfo *argTable;     /* Array of option descriptions */
        !            78:     int flags;                 /* Or'ed combination of various flag bits,
        !            79:                                 * such as TK_ARGV_NO_DEFAULTS. */
        !            80: {
        !            81:     register Tk_ArgvInfo *infoPtr;
        !            82:                                /* Pointer to the current entry in the
        !            83:                                 * table of argument descriptions. */
        !            84:     Tk_ArgvInfo *matchPtr;     /* Descriptor that matches current argument. */
        !            85:     char *curArg;              /* Current argument */
        !            86:     register char c;           /* Second character of current arg (used for
        !            87:                                 * quick check for matching;  use 2nd char.
        !            88:                                 * because first char. will almost always
        !            89:                                 * be '-'). */
        !            90:     int srcIndex;              /* Location from which to read next argument
        !            91:                                 * from argv. */
        !            92:     int dstIndex;              /* Index into argv to which next unused
        !            93:                                 * argument should be copied (never greater
        !            94:                                 * than srcIndex). */
        !            95:     int argc;                  /* # arguments in argv still to process. */
        !            96:     int length;                        /* Number of characters in current argument. */
        !            97:     int i;
        !            98: 
        !            99:     if (flags & TK_ARGV_DONT_SKIP_FIRST_ARG) {
        !           100:        srcIndex = dstIndex = 0;
        !           101:        argc = *argcPtr;
        !           102:     } else {
        !           103:        srcIndex = dstIndex = 1;
        !           104:        argc = *argcPtr-1;
        !           105:     }
        !           106: 
        !           107:     while (argc > 0) {
        !           108:        curArg = argv[srcIndex];
        !           109:        srcIndex++;
        !           110:        argc--;
        !           111:        c = curArg[1];
        !           112:        length = strlen(curArg);
        !           113: 
        !           114:        /*
        !           115:         * Loop throught the argument descriptors searching for one with
        !           116:         * the matching key string.  If found, leave a pointer to it in
        !           117:         * matchPtr.
        !           118:         */
        !           119: 
        !           120:        matchPtr = NULL;
        !           121:        for (i = 0; i < 2; i++) {
        !           122:            if (i == 0) {
        !           123:                infoPtr = argTable;
        !           124:            } else {
        !           125:                infoPtr = defaultTable;
        !           126:            }
        !           127:            for (; infoPtr->type != TK_ARGV_END; infoPtr++) {
        !           128:                 if (infoPtr->key == NULL) {
        !           129:                     continue;
        !           130:                 }
        !           131:                 if ((infoPtr->key[1] != c)
        !           132:                         || (strncmp(infoPtr->key, curArg, length) != 0)) {
        !           133:                     continue;
        !           134:                 }
        !           135:                 if ((tkwin == NULL)
        !           136:                         && ((infoPtr->type == TK_ARGV_CONST_OPTION)
        !           137:                         || (infoPtr->type == TK_ARGV_OPTION_VALUE)
        !           138:                         || (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) {
        !           139:                     continue;
        !           140:                 }
        !           141:                 if (infoPtr->key[length] == 0) {
        !           142:                     matchPtr = infoPtr;
        !           143:                     goto gotMatch;
        !           144:                 }
        !           145:                 if (flags & TK_ARGV_NO_ABBREV) {
        !           146:                     continue;
        !           147:                 }
        !           148:                 if (matchPtr != NULL) {
        !           149:                     Tcl_AppendResult(interp, "ambiguous option \"", curArg,
        !           150:                             "\"", (char *) NULL);
        !           151:                     return TCL_ERROR;
        !           152:                 }
        !           153:                 matchPtr = infoPtr;
        !           154:            }
        !           155:        }
        !           156:        if (matchPtr == NULL) {
        !           157: 
        !           158:            /*
        !           159:             * Unrecognized argument.  Just copy it down, unless the caller
        !           160:             * prefers an error to be registered.
        !           161:             */
        !           162: 
        !           163:            if (flags & TK_ARGV_NO_LEFTOVERS) {
        !           164:                Tcl_AppendResult(interp, "unrecognized argument \"",
        !           165:                        curArg, "\"", (char *) NULL);
        !           166:                return TCL_ERROR;
        !           167:            }
        !           168:            argv[dstIndex] = curArg;
        !           169:            dstIndex++;
        !           170:            continue;
        !           171:        }
        !           172: 
        !           173:        /*
        !           174:         * Take the appropriate action based on the option type
        !           175:         */
        !           176: 
        !           177:        gotMatch:
        !           178:        infoPtr = matchPtr;
        !           179:        switch (infoPtr->type) {
        !           180:            case TK_ARGV_CONSTANT:
        !           181:                *((int *) infoPtr->dst) = (int) infoPtr->src;
        !           182:                break;
        !           183:            case TK_ARGV_INT:
        !           184:                if (argc == 0) {
        !           185:                    goto missingArg;
        !           186:                } else {
        !           187:                    char *endPtr;
        !           188: 
        !           189:                    *((int *) infoPtr->dst) =
        !           190:                            strtol(argv[srcIndex], &endPtr, 0);
        !           191:                    if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
        !           192:                        Tcl_AppendResult(interp, "expected integer argument ",
        !           193:                                "for \"", infoPtr->key, "\" but got \"",
        !           194:                                argv[srcIndex], "\"", (char *) NULL);
        !           195:                        return TCL_ERROR;
        !           196:                    }
        !           197:                    srcIndex++;
        !           198:                    argc--;
        !           199:                }
        !           200:                break;
        !           201:            case TK_ARGV_STRING:
        !           202:                if (argc == 0) {
        !           203:                    goto missingArg;
        !           204:                } else {
        !           205:                    *((char **)infoPtr->dst) = argv[srcIndex];
        !           206:                    srcIndex++;
        !           207:                    argc--;
        !           208:                }
        !           209:                break;
        !           210:            case TK_ARGV_UID:
        !           211:                if (argc == 0) {
        !           212:                    goto missingArg;
        !           213:                } else {
        !           214:                    *((Tk_Uid *)infoPtr->dst) = Tk_GetUid(argv[srcIndex]);
        !           215:                    srcIndex++;
        !           216:                    argc--;
        !           217:                }
        !           218:                break;
        !           219:            case TK_ARGV_REST:
        !           220:                *((int *) infoPtr->dst) = dstIndex;
        !           221:                goto argsDone;
        !           222:            case TK_ARGV_FLOAT:
        !           223:                if (argc == 0) {
        !           224:                    goto missingArg;
        !           225:                } else {
        !           226:                    char *endPtr;
        !           227: 
        !           228:                    *((double *) infoPtr->dst) =
        !           229:                            strtod(argv[srcIndex], &endPtr);
        !           230:                    if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
        !           231:                        Tcl_AppendResult(interp, "expected floating-point ",
        !           232:                                "argument for \"", infoPtr->key,
        !           233:                                "\" but got \"", argv[srcIndex], "\"",
        !           234:                                (char *) NULL);
        !           235:                        return TCL_ERROR;
        !           236:                    }
        !           237:                    srcIndex++;
        !           238:                    argc--;
        !           239:                }
        !           240:                break;
        !           241:            case TK_ARGV_FUNC: {
        !           242:                int (*handlerProc)();
        !           243: 
        !           244:                handlerProc = (int (*)())infoPtr->src;
        !           245:                
        !           246:                if ((*handlerProc)(infoPtr->dst, infoPtr->key,
        !           247:                        argv[srcIndex])) {
        !           248:                    srcIndex += 1;
        !           249:                    argc -= 1;
        !           250:                }
        !           251:                break;
        !           252:            }
        !           253:            case TK_ARGV_GENFUNC: {
        !           254:                int         (*handlerProc)();
        !           255: 
        !           256:                handlerProc = (int (*)())infoPtr->src;
        !           257: 
        !           258:                argc = (*handlerProc)(infoPtr->dst, interp, infoPtr->key,
        !           259:                        argc, argv+srcIndex);
        !           260:                if (argc < 0) {
        !           261:                    return TCL_ERROR;
        !           262:                }
        !           263:                break;
        !           264:            }
        !           265:            case TK_ARGV_HELP:
        !           266:                PrintUsage (interp, argTable, flags);
        !           267:                return TCL_ERROR;
        !           268:            case TK_ARGV_CONST_OPTION:
        !           269:                Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src,
        !           270:                        TK_INTERACTIVE_PRIO);
        !           271:                break;
        !           272:            case TK_ARGV_OPTION_VALUE:
        !           273:                if (argc < 1) {
        !           274:                    goto missingArg;
        !           275:                }
        !           276:                Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex],
        !           277:                        TK_INTERACTIVE_PRIO);
        !           278:                srcIndex++;
        !           279:                argc--;
        !           280:                break;
        !           281:            case TK_ARGV_OPTION_NAME_VALUE:
        !           282:                if (argc < 2) {
        !           283:                    Tcl_AppendResult(interp, "\"", curArg,
        !           284:                            "\" option requires two following arguments",
        !           285:                            (char *) NULL);
        !           286:                    return TCL_ERROR;
        !           287:                }
        !           288:                Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1],
        !           289:                        TK_INTERACTIVE_PRIO);
        !           290:                srcIndex += 2;
        !           291:                argc -= 2;
        !           292:                break;
        !           293:            default:
        !           294:                sprintf(interp->result, "bad argument type %d in Tk_ArgvInfo",
        !           295:                        infoPtr->type);
        !           296:                return TCL_ERROR;
        !           297:        }
        !           298:     }
        !           299: 
        !           300:     /*
        !           301:      * If we broke out of the loop because of an OPT_REST argument,
        !           302:      * copy the remaining arguments down.
        !           303:      */
        !           304: 
        !           305:     argsDone:
        !           306:     while (argc) {
        !           307:        argv[dstIndex] = argv[srcIndex];
        !           308:        srcIndex++;
        !           309:        dstIndex++;
        !           310:        argc--;
        !           311:     }
        !           312:     argv[dstIndex] = (char *) NULL;
        !           313:     *argcPtr = dstIndex;
        !           314:     return TCL_OK;
        !           315: 
        !           316:     missingArg:
        !           317:     Tcl_AppendResult(interp, "\"", curArg,
        !           318:            "\" option requires an additional argument", (char *) NULL);
        !           319:     return TCL_ERROR;
        !           320: }
        !           321: 
        !           322: /*
        !           323:  *----------------------------------------------------------------------
        !           324:  *
        !           325:  * PrintUsage --
        !           326:  *
        !           327:  *     Generate a help string describing command-line options.
        !           328:  *
        !           329:  * Results:
        !           330:  *     Interp->result will be modified to hold a help string
        !           331:  *     describing all the options in argTable, plus all those
        !           332:  *     in the default table unless TK_ARGV_NO_DEFAULTS is
        !           333:  *     specified in flags.
        !           334:  *
        !           335:  * Side effects:
        !           336:  *     None.
        !           337:  *
        !           338:  *----------------------------------------------------------------------
        !           339:  */
        !           340: 
        !           341: static void
        !           342: PrintUsage(interp, argTable, flags)
        !           343:     Tcl_Interp *interp;                /* Place information in this interp's
        !           344:                                 * result area. */
        !           345:     Tk_ArgvInfo *argTable;     /* Array of command-specific argument
        !           346:                                 * descriptions. */
        !           347:     int flags;                 /* If the TK_ARGV_NO_DEFAULTS bit is set
        !           348:                                 * in this word, then don't generate
        !           349:                                 * information for default options. */
        !           350: {
        !           351:     register Tk_ArgvInfo *infoPtr;
        !           352:     int width, i, numSpaces;
        !           353: #define NUM_SPACES 20
        !           354:     static char spaces[] = "                    ";
        !           355:     char tmp[30];
        !           356: 
        !           357:     /*
        !           358:      * First, compute the width of the widest option key, so that we
        !           359:      * can make everything line up.
        !           360:      */
        !           361: 
        !           362:     width = 4;
        !           363:     for (i = 0; i < 2; i++) {
        !           364:        for (infoPtr = i ? defaultTable : argTable;
        !           365:                infoPtr->type != TK_ARGV_END; infoPtr++) {
        !           366:            int length;
        !           367:            if (infoPtr->key == NULL) {
        !           368:                continue;
        !           369:            }
        !           370:            length = strlen(infoPtr->key);
        !           371:            if (length > width) {
        !           372:                width = length;
        !           373:            }
        !           374:        }
        !           375:     }
        !           376: 
        !           377:     Tcl_AppendResult(interp, "Command-specific options:", (char *) NULL);
        !           378:     for (i = 0; ; i++) {
        !           379:        for (infoPtr = i ? defaultTable : argTable;
        !           380:                infoPtr->type != TK_ARGV_END; infoPtr++) {
        !           381:            if ((infoPtr->type == TK_ARGV_HELP) && (infoPtr->key == NULL)) {
        !           382:                Tcl_AppendResult(interp, "\n", infoPtr->help, (char *) NULL);
        !           383:                continue;
        !           384:            }
        !           385:            Tcl_AppendResult(interp, "\n ", infoPtr->key, ":", (char *) NULL);
        !           386:            numSpaces = width + 1 - strlen(infoPtr->key);
        !           387:            while (numSpaces > 0) {
        !           388:                if (numSpaces >= NUM_SPACES) {
        !           389:                    Tcl_AppendResult(interp, spaces, (char *) NULL);
        !           390:                } else {
        !           391:                    Tcl_AppendResult(interp, spaces+NUM_SPACES-numSpaces,
        !           392:                            (char *) NULL);
        !           393:                }
        !           394:                numSpaces -= NUM_SPACES;
        !           395:            }
        !           396:            Tcl_AppendResult(interp, infoPtr->help, (char *) NULL);
        !           397:            switch (infoPtr->type) {
        !           398:                case TK_ARGV_INT: {
        !           399:                    sprintf(tmp, "%d", *((int *) infoPtr->dst));
        !           400:                    Tcl_AppendResult(interp, "\n\t\tDefault value: ",
        !           401:                            tmp, (char *) NULL);
        !           402:                    break;
        !           403:                }
        !           404:                case TK_ARGV_FLOAT: {
        !           405:                    sprintf(tmp, "%lg", *((double *) infoPtr->dst));
        !           406:                    Tcl_AppendResult(interp, "\n\t\tDefault value: ",
        !           407:                            tmp, (char *) NULL);
        !           408:                    break;
        !           409:                }
        !           410:                case TK_ARGV_STRING: {
        !           411:                    char *string;
        !           412: 
        !           413:                    string = *((char **) infoPtr->dst);
        !           414:                    if (string != NULL) {
        !           415:                        Tcl_AppendResult(interp, "\n\t\tDefault value: \"",
        !           416:                                string, "\"", (char *) NULL);
        !           417:                    }
        !           418:                    break;
        !           419:                }
        !           420:                default: {
        !           421:                    break;
        !           422:                }
        !           423:            }
        !           424:        }
        !           425: 
        !           426:        if ((flags & TK_ARGV_NO_DEFAULTS) || (i > 0)) {
        !           427:            break;
        !           428:        }
        !           429:        Tcl_AppendResult(interp, "\nGeneric options for all commands:",
        !           430:                (char *) NULL);
        !           431:     }
        !           432: }

unix.superglobalmegacorp.com

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