Annotation of researchv10dc/cmd/worm/scsi/tcl/tclCmdIZ.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * tclCmdIZ.c --
        !             3:  *
        !             4:  *     This file contains the top-level command routines for most of
        !             5:  *     the Tcl built-in commands whose names begin with the letters
        !             6:  *     I to Z.
        !             7:  *
        !             8:  * Copyright 1987 Regents of the University of California
        !             9:  * Permission to use, copy, modify, and distribute this
        !            10:  * software and its documentation for any purpose and without
        !            11:  * fee is hereby granted, provided that the above copyright
        !            12:  * notice appear in all copies.  The University of California
        !            13:  * makes no representations about the suitability of this
        !            14:  * software for any purpose.  It is provided "as is" without
        !            15:  * express or implied warranty.
        !            16:  */
        !            17: 
        !            18: #ifndef lint
        !            19: static char rcsid[] = "$Header: /sprite/src/lib/tcl/RCS/tclCmdIZ.c,v 1.36 90/04/18 17:09:07 ouster Exp $ SPRITE (Berkeley)";
        !            20: #pragma ref rcsid
        !            21: #endif not lint
        !            22: 
        !            23: #define        _POSIX_SOURCE
        !            24: 
        !            25: #include <ctype.h>
        !            26: #include <errno.h>
        !            27: #include <stdio.h>
        !            28: #include <stdlib.h>
        !            29: #include <string.h>
        !            30: #include <sys/types.h>
        !            31: #include <fcntl.h>
        !            32: #include <sys/stat.h>
        !            33: #include <sys/times.h>
        !            34: #include "tclInt.h"
        !            35: 
        !            36: /*
        !            37:  *----------------------------------------------------------------------
        !            38:  *
        !            39:  * Tcl_IfCmd --
        !            40:  *
        !            41:  *     This procedure is invoked to process the "if" Tcl command.
        !            42:  *     See the user documentation for details on what it does.
        !            43:  *
        !            44:  * Results:
        !            45:  *     A standard Tcl result.
        !            46:  *
        !            47:  * Side effects:
        !            48:  *     See the user documentation.
        !            49:  *
        !            50:  *----------------------------------------------------------------------
        !            51:  */
        !            52: 
        !            53:        /* ARGSUSED */
        !            54: int
        !            55: Tcl_IfCmd(dummy, interp, argc, argv)
        !            56:     ClientData dummy;                  /* Not used. */
        !            57:     Tcl_Interp *interp;                        /* Current interpreter. */
        !            58:     int argc;                          /* Number of arguments. */
        !            59:     char **argv;                       /* Argument strings. */
        !            60: {
        !            61: #pragma ref dummy
        !            62:     char *condition, *ifPart, *elsePart, *cmd, *name;
        !            63:     int result, value;
        !            64: 
        !            65:     name = argv[0];
        !            66:     if (argc < 3) {
        !            67:        ifSyntax:
        !            68:        sprintf(interp->result, "wrong # args:  should be \"%.50s bool [then] command [[else] command]\"",
        !            69:                name);
        !            70:        return TCL_ERROR;
        !            71:     }
        !            72:     condition = argv[1];
        !            73:     argc -= 2;
        !            74:     argv += 2;
        !            75:     if ((**argv == 't') && (strncmp(*argv, "then", strlen(*argv)) == 0)) {
        !            76:        argc--;
        !            77:        argv++;
        !            78:     }
        !            79:     if (argc < 1) {
        !            80:        goto ifSyntax;
        !            81:     }
        !            82:     ifPart = *argv;
        !            83:     argv++;
        !            84:     argc--;
        !            85:     if (argc == 0) {
        !            86:        elsePart = "";
        !            87:     } else {
        !            88:        if ((**argv == 'e') && (strncmp(*argv, "else", strlen(*argv)) == 0)) {
        !            89:            argc--;
        !            90:            argv++;
        !            91:        }
        !            92:        if (argc != 1) {
        !            93:            goto ifSyntax;
        !            94:        }
        !            95:        elsePart = *argv;
        !            96:     }
        !            97: 
        !            98:     cmd = ifPart;
        !            99:     result = Tcl_Expr(interp, condition, &value);
        !           100:     if (result != TCL_OK) {
        !           101:        return result;
        !           102:     }
        !           103:     if (value == 0) {
        !           104:        cmd = elsePart;
        !           105:     }
        !           106:     result = Tcl_Eval(interp, cmd, 0, (char **) NULL);
        !           107:     if (result == TCL_ERROR) {
        !           108:        char msg[60];
        !           109:        sprintf(msg, " (\"if\" body line %d)", interp->errorLine);
        !           110:        Tcl_AddErrorInfo(interp, msg);
        !           111:     }
        !           112:     return result;
        !           113: }
        !           114: 
        !           115: /*
        !           116:  *----------------------------------------------------------------------
        !           117:  *
        !           118:  * Tcl_IndexCmd --
        !           119:  *
        !           120:  *     This procedure is invoked to process the "index" Tcl command.
        !           121:  *     See the user documentation for details on what it does.
        !           122:  *
        !           123:  * Results:
        !           124:  *     A standard Tcl result.
        !           125:  *
        !           126:  * Side effects:
        !           127:  *     See the user documentation.
        !           128:  *
        !           129:  *----------------------------------------------------------------------
        !           130:  */
        !           131: 
        !           132:     /* ARGSUSED */
        !           133: int
        !           134: Tcl_IndexCmd(dummy, interp, argc, argv)
        !           135:     ClientData dummy;                  /* Not used. */
        !           136:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           137:     int argc;                          /* Number of arguments. */
        !           138:     char **argv;                       /* Argument strings. */
        !           139: {
        !           140: #pragma ref dummy
        !           141:     char *p, *element;
        !           142:     int index, size, parenthesized, result;
        !           143: 
        !           144:     if (argc < 3) {
        !           145:        indexSyntax:
        !           146:        sprintf(interp->result,
        !           147:                "wrong # args:  should be \"%.50s value index [chars]\"",
        !           148:                argv[0]);
        !           149:        return TCL_ERROR;
        !           150:     }
        !           151:     p = argv[1];
        !           152:     index = atoi(argv[2]);
        !           153:     if (!isdigit(*argv[2]) || (index < 0)) {
        !           154:        sprintf(interp->result, "bad index \"%.50s\"", argv[2]);
        !           155:        return TCL_ERROR;
        !           156:     }
        !           157:     if (argc == 3) {
        !           158:        for ( ; index >= 0; index--) {
        !           159:            result = TclFindElement(interp, p, &element, &p, &size,
        !           160:                    &parenthesized);
        !           161:            if (result != TCL_OK) {
        !           162:                return result;
        !           163:            }
        !           164:        }
        !           165:        if (size >= TCL_RESULT_SIZE) {
        !           166:            interp->result = (char *) malloc((unsigned) size+1);
        !           167:            interp->dynamic = 1;
        !           168:        }
        !           169:        if (parenthesized) {
        !           170:            bcopy(element, interp->result, size);
        !           171:            interp->result[size] = 0;
        !           172:        } else {
        !           173:            TclCopyAndCollapse(size, element, interp->result);
        !           174:        }
        !           175:     } else if (argc == 4) {
        !           176:        if (strncmp(argv[3], "chars", strlen(argv[3])) != 0) {
        !           177:            sprintf(interp->result, "bad argument \"%s\":  must be \"chars\"",
        !           178:                    argv[3]);
        !           179:            return TCL_ERROR;
        !           180:        }
        !           181:        size = strlen(p);
        !           182:        if (index < size) {
        !           183:            interp->result[0] = p[index];
        !           184:            interp->result[1] = 0;
        !           185:        }
        !           186:     } else {
        !           187:        goto indexSyntax;
        !           188:     }
        !           189:     return TCL_OK;
        !           190: }
        !           191: 
        !           192: /*
        !           193:  *----------------------------------------------------------------------
        !           194:  *
        !           195:  * Tcl_InfoCmd --
        !           196:  *
        !           197:  *     This procedure is invoked to process the "info" Tcl command.
        !           198:  *     See the user documentation for details on what it does.
        !           199:  *
        !           200:  * Results:
        !           201:  *     A standard Tcl result.
        !           202:  *
        !           203:  * Side effects:
        !           204:  *     See the user documentation.
        !           205:  *
        !           206:  *----------------------------------------------------------------------
        !           207:  */
        !           208: 
        !           209:        /* ARGSUSED */
        !           210: int
        !           211: Tcl_InfoCmd(dummy, interp, argc, argv)
        !           212:     ClientData dummy;                  /* Not used. */
        !           213:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           214:     int argc;                          /* Number of arguments. */
        !           215:     char **argv;                       /* Argument strings. */
        !           216: {
        !           217: #pragma ref dummy
        !           218:     register Interp *iPtr = (Interp *) interp;
        !           219:     Proc *procPtr;
        !           220:     Var *varPtr;
        !           221:     Command *cmdPtr;
        !           222:     int length;
        !           223:     char c;
        !           224: 
        !           225:     /*
        !           226:      * When collecting a list of things (e.g. args or vars) "flag" tells
        !           227:      * what kind of thing is being collected, according to the definitions
        !           228:      * below.
        !           229:      */
        !           230: 
        !           231:     int flag;
        !           232: #   define VARS 0
        !           233: #   define LOCALS 1
        !           234: #   define PROCS 2
        !           235: #   define CMDS 3
        !           236: 
        !           237: #   define ARG_SIZE 20
        !           238:     char *argSpace[ARG_SIZE];
        !           239:     int argSize;
        !           240:     char *pattern;
        !           241: 
        !           242:     if (argc < 2) {
        !           243:        sprintf(iPtr->result,
        !           244:                "too few args:  should be \"%.50s option [arg arg ...]\"",
        !           245:                argv[0]);
        !           246:        return TCL_ERROR;
        !           247:     }
        !           248:     c = argv[1][0];
        !           249:     length = strlen(argv[1]);
        !           250:     if ((c == 'a') && (strncmp(argv[1], "args", length)) == 0) {
        !           251:        if (argc != 3) {
        !           252:            sprintf(iPtr->result,
        !           253:                    "wrong # args: should be \"%.50s args procname\"",
        !           254:                    argv[0]);
        !           255:            return TCL_ERROR;
        !           256:        }
        !           257:        procPtr = TclFindProc(iPtr, argv[2]);
        !           258:        if (procPtr == NULL) {
        !           259:            infoNoSuchProc:
        !           260:            sprintf(iPtr->result,
        !           261:                    "info requested on \"%s\", which isn't a procedure",
        !           262:                    argv[2]);
        !           263:            return TCL_ERROR;
        !           264:        }
        !           265:        flag = VARS;
        !           266:        varPtr = procPtr->argPtr;
        !           267:        argc = 0;                       /* Prevent pattern matching. */
        !           268:     } else if ((c == 'b') && (strncmp(argv[1], "body", length)) == 0) {
        !           269:        if (argc != 3) {
        !           270:            sprintf(iPtr->result,
        !           271:                    "wrong # args: should be \"%.50s body procname\"",
        !           272:                    argv[0]);
        !           273:            return TCL_ERROR;
        !           274:        }
        !           275:        procPtr = TclFindProc(iPtr, argv[2]);
        !           276:        if (procPtr == NULL) {
        !           277:            goto infoNoSuchProc;
        !           278:        }
        !           279:        iPtr->result = procPtr->command;
        !           280:        return TCL_OK;
        !           281:     } else if ((c == 'c') && (strncmp(argv[1], "cmdcount", length) == 0)
        !           282:            && (length >= 2)) {
        !           283:        if (argc != 2) {
        !           284:            sprintf(iPtr->result,
        !           285:                    "wrong # args: should be \"%.50s cmdcount\"",
        !           286:                    argv[0]);
        !           287:            return TCL_ERROR;
        !           288:        }
        !           289:        sprintf(iPtr->result, "%d", iPtr->cmdCount);
        !           290:        return TCL_OK;
        !           291:     } else if ((c == 'c') && (strncmp(argv[1], "commands", length) == 0)
        !           292:            && (length >= 2)){
        !           293:        if (argc > 3) {
        !           294:            sprintf(iPtr->result,
        !           295:                    "wrong # args: should be \"%.50s commands [pattern]\"",
        !           296:                    argv[0]);
        !           297:            return TCL_ERROR;
        !           298:        }
        !           299:        flag = CMDS;
        !           300:        cmdPtr = iPtr->commandPtr;
        !           301:     } else if ((c == 'd') && (strncmp(argv[1], "default", length)) == 0) {
        !           302:        if (argc != 5) {
        !           303:            sprintf(iPtr->result, "wrong # args: should be \"%.50s default procname arg varname\"",
        !           304:                    argv[0]);
        !           305:            return TCL_ERROR;
        !           306:        }
        !           307:        procPtr = TclFindProc(iPtr, argv[2]);
        !           308:        if (procPtr == NULL) {
        !           309:            goto infoNoSuchProc;
        !           310:        }
        !           311:        for (varPtr = procPtr->argPtr; ; varPtr = varPtr->nextPtr) {
        !           312:            if (varPtr == NULL) {
        !           313:                sprintf(iPtr->result,
        !           314:                        "procedure \"%s\" doesn't have an argument \"%s\"",
        !           315:                        argv[2], argv[3]);
        !           316:                return TCL_ERROR;
        !           317:            }
        !           318:            if (strcmp(argv[3], varPtr->name) == 0) {
        !           319:                if (varPtr->value != NULL) {
        !           320:                    Tcl_SetVar((Tcl_Interp *) iPtr, argv[4], varPtr->value, 0);
        !           321:                    iPtr->result = "1";
        !           322:                } else {
        !           323:                    Tcl_SetVar((Tcl_Interp *) iPtr, argv[4], "", 0);
        !           324:                    iPtr->result = "0";
        !           325:                }
        !           326:                return TCL_OK;
        !           327:            }
        !           328:        }
        !           329:     } else if ((c == 'e') && (strncmp(argv[1], "exists", length) == 0)) {
        !           330:        char *p;
        !           331:        if (argc != 3) {
        !           332:            sprintf(iPtr->result,
        !           333:                    "wrong # args: should be \"%.50s exists varName\"",
        !           334:                    argv[0]);
        !           335:            return TCL_ERROR;
        !           336:        }
        !           337:        p = Tcl_GetVar((Tcl_Interp *) iPtr, argv[2], 0);
        !           338:        if (p != NULL) {
        !           339:            iPtr->result[0] = '1';
        !           340:        } else {
        !           341:            iPtr->result[0] = '0';
        !           342:        }
        !           343:        iPtr->result[1] = 0;
        !           344:        return TCL_OK;
        !           345:     } else if ((c == 'g') && (strncmp(argv[1], "globals", length) == 0)) {
        !           346:        if (argc > 3) {
        !           347:            sprintf(iPtr->result,
        !           348:                    "wrong # args: should be \"%.50s globals [pattern]\"",
        !           349:                    argv[0]);
        !           350:            return TCL_ERROR;
        !           351:        }
        !           352:        flag = VARS;
        !           353:        varPtr = iPtr->globalPtr;
        !           354:     } else if ((c == 'l') && (strncmp(argv[1], "locals", length) == 0)
        !           355:             && (length >= 2)) {
        !           356:        if (argc > 3) {
        !           357:            sprintf(iPtr->result,
        !           358:                    "wrong # args: should be \"%.50s locals [pattern]\"",
        !           359:                    argv[0]);
        !           360:            return TCL_ERROR;
        !           361:        }
        !           362:        flag = LOCALS;
        !           363:        if (iPtr->varFramePtr == NULL) {
        !           364:            varPtr = NULL;
        !           365:        } else {
        !           366:            varPtr = iPtr->varFramePtr->varPtr;
        !           367:        }
        !           368:     } else if ((c == 'l') && (strncmp(argv[1], "level", length) == 0)
        !           369:            && (length >= 2)) {
        !           370:        if (argc == 2) {
        !           371:            if (iPtr->varFramePtr == NULL) {
        !           372:                iPtr->result = "0";
        !           373:            } else {
        !           374:                sprintf(iPtr->result, "%d", iPtr->varFramePtr->level);
        !           375:            }
        !           376:            return TCL_OK;
        !           377:        } else if (argc == 3) {
        !           378:            int level;
        !           379:            char *end;
        !           380:            CallFrame *framePtr;
        !           381: 
        !           382:            level = strtol(argv[2], &end, 10);
        !           383:            if ((end == argv[2]) || (*end != '\0')) {
        !           384:                levelError:
        !           385:                sprintf(iPtr->result, "bad level \"%.50s\"", argv[1]);
        !           386:                return TCL_ERROR;
        !           387:            }
        !           388:            if (level <= 0) {
        !           389:                if (iPtr->varFramePtr == NULL) {
        !           390:                    goto levelError;
        !           391:                }
        !           392:                level += iPtr->varFramePtr->level;
        !           393:            }
        !           394:            if (level == 0) {
        !           395:                return TCL_OK;
        !           396:            }
        !           397:            for (framePtr = iPtr->varFramePtr; framePtr != NULL;
        !           398:                    framePtr = framePtr->callerVarPtr) {
        !           399:                if (framePtr->level == level) {
        !           400:                    break;
        !           401:                }
        !           402:            }
        !           403:            if (framePtr == NULL) {
        !           404:                goto levelError;
        !           405:            }
        !           406:            iPtr->result = Tcl_Merge(framePtr->argc, framePtr->argv);
        !           407:            iPtr->dynamic = 1;
        !           408:            return TCL_OK;
        !           409:        }
        !           410:        sprintf(iPtr->result,
        !           411:                "wrong # args: should be \"%.50s level [number]\"",
        !           412:                argv[0]);
        !           413:        return TCL_ERROR;
        !           414:     } else if ((c == 'p') && (strncmp(argv[1], "procs", length)) == 0) {
        !           415:        if (argc > 3) {
        !           416:            sprintf(iPtr->result,
        !           417:                    "wrong # args: should be \"%.50s procs [pattern]\"",
        !           418:                    argv[0]);
        !           419:            return TCL_ERROR;
        !           420:        }
        !           421:        flag = PROCS;
        !           422:        cmdPtr = iPtr->commandPtr;
        !           423:     } else if ((c == 't') && (strncmp(argv[1], "tclversion", length) == 0)) {
        !           424: 
        !           425:        /*
        !           426:         * Note:  TCL_VERSION below is expected to be set with a "-D"
        !           427:         * switch in the Makefile.
        !           428:         */
        !           429: 
        !           430:        strcpy(iPtr->result, TCL_VERSION);
        !           431:        return TCL_OK;
        !           432:     } else if ((c == 'v') && (strncmp(argv[1], "vars", length)) == 0) {
        !           433:        if (argc > 3) {
        !           434:            sprintf(iPtr->result,
        !           435:                    "wrong # args: should be \"%.50s vars [pattern]\"",
        !           436:                    argv[0]);
        !           437:            return TCL_ERROR;
        !           438:        }
        !           439:        flag = VARS;
        !           440:        if (iPtr->varFramePtr == NULL) {
        !           441:            varPtr = iPtr->globalPtr;
        !           442:        } else {
        !           443:            varPtr = iPtr->varFramePtr->varPtr;
        !           444:        }
        !           445:     } else {
        !           446:        sprintf(iPtr->result, "bad \"%.50s\" option \"%.50s\": must be args, body, commands, cmdcount, default, exists, globals, level, locals, procs, tclversion, or vars",
        !           447:                argv[0], argv[1]);
        !           448:        return TCL_ERROR;
        !           449:     }
        !           450: 
        !           451:     /*
        !           452:      * At this point we have to assemble a list of something or other.
        !           453:      * Collect them in an expandable argv-argc array.
        !           454:      */
        !           455: 
        !           456:     if (argc == 3) {
        !           457:        pattern = argv[2];
        !           458:     } else {
        !           459:        pattern = NULL;
        !           460:     }
        !           461:     argv = argSpace;
        !           462:     argSize = ARG_SIZE;
        !           463:     argc = 0;
        !           464:     while (1) {
        !           465:        /*
        !           466:         * Increase the size of the argument array if necessary to
        !           467:         * accommodate another string.
        !           468:         */
        !           469: 
        !           470:        if (argc == argSize) {
        !           471:            char **newArgs;
        !           472: 
        !           473:            argSize *= 2;
        !           474:            newArgs = (char **) malloc((unsigned) argSize*sizeof(char *));
        !           475:            bcopy((char *) argv, (char *) newArgs, argc*sizeof(char *));
        !           476:            if (argv != argSpace) {
        !           477:                free((char *) argv);
        !           478:            }
        !           479:            argv = newArgs;
        !           480:        }
        !           481: 
        !           482:        if ((flag == PROCS) || (flag == CMDS)) {
        !           483:            if (flag == PROCS) {
        !           484:                for ( ; cmdPtr != NULL; cmdPtr = cmdPtr->nextPtr) {
        !           485:                    if (TclIsProc(cmdPtr)) {
        !           486:                        break;
        !           487:                    }
        !           488:                }
        !           489:            }
        !           490:            if (cmdPtr == NULL) {
        !           491:                break;
        !           492:            }
        !           493:            argv[argc] = cmdPtr->name;
        !           494:            cmdPtr = cmdPtr->nextPtr;
        !           495:        } else {
        !           496:            if (flag == LOCALS) {
        !           497:                for ( ; varPtr != NULL; varPtr = varPtr->nextPtr) {
        !           498:                    if (!(varPtr->flags & VAR_GLOBAL)) {
        !           499:                        break;
        !           500:                    }
        !           501:                }
        !           502:            }
        !           503:            if (varPtr == NULL) {
        !           504:                break;
        !           505:            }
        !           506:            argv[argc] = varPtr->name;
        !           507:            varPtr = varPtr->nextPtr;
        !           508:        }
        !           509:        if ((pattern == NULL)  || Tcl_StringMatch(argv[argc], pattern)) {
        !           510:            argc++;
        !           511:        }
        !           512:     }
        !           513: 
        !           514:     iPtr->result = Tcl_Merge(argc, argv);
        !           515:     iPtr->dynamic = 1;
        !           516:     if (argv != argSpace) {
        !           517:        free((char *) argv);
        !           518:     }
        !           519:     return TCL_OK;
        !           520: }
        !           521: 
        !           522: /*
        !           523:  *----------------------------------------------------------------------
        !           524:  *
        !           525:  * Tcl_LengthCmd --
        !           526:  *
        !           527:  *     This procedure is invoked to process the "length" Tcl command.
        !           528:  *     See the user documentation for details on what it does.
        !           529:  *
        !           530:  * Results:
        !           531:  *     A standard Tcl result.
        !           532:  *
        !           533:  * Side effects:
        !           534:  *     See the user documentation.
        !           535:  *
        !           536:  *----------------------------------------------------------------------
        !           537:  */
        !           538: 
        !           539:        /* ARGSUSED */
        !           540: int
        !           541: Tcl_LengthCmd(dummy, interp, argc, argv)
        !           542:     ClientData dummy;                  /* Not used. */
        !           543:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           544:     int argc;                          /* Number of arguments. */
        !           545:     char **argv;                       /* Argument strings. */
        !           546: {
        !           547: #pragma ref dummy
        !           548:     int count;
        !           549:     char *p;
        !           550: 
        !           551:     if (argc < 2) {
        !           552:        lengthSyntax:
        !           553:        sprintf(interp->result,
        !           554:                "wrong # args: should be \"%.50s value [chars]\"", argv[0]);
        !           555:        return TCL_ERROR;
        !           556:     }
        !           557:     p = argv[1];
        !           558:     if (argc == 2) {
        !           559:        char *element;
        !           560:        int result;
        !           561: 
        !           562:        for (count = 0; *p != 0 ; count++) {
        !           563:            result = TclFindElement(interp, p, &element, &p, (int *) NULL,
        !           564:                    (int *) NULL);
        !           565:            if (result != TCL_OK) {
        !           566:                return result;
        !           567:            }
        !           568:            if (*element == 0) {
        !           569:                break;
        !           570:            }
        !           571:        }
        !           572:     } else if ((argc == 3)
        !           573:            && (strncmp(argv[2], "chars", strlen(argv[2])) == 0)) {
        !           574:        count = strlen(p);
        !           575:     } else {
        !           576:        goto lengthSyntax;
        !           577:     }
        !           578:     sprintf(interp->result, "%d", count);
        !           579:     return TCL_OK;
        !           580: }
        !           581: 
        !           582: /*
        !           583:  *----------------------------------------------------------------------
        !           584:  *
        !           585:  * Tcl_ListCmd --
        !           586:  *
        !           587:  *     This procedure is invoked to process the "list" Tcl command.
        !           588:  *     See the user documentation for details on what it does.
        !           589:  *
        !           590:  * Results:
        !           591:  *     A standard Tcl result.
        !           592:  *
        !           593:  * Side effects:
        !           594:  *     See the user documentation.
        !           595:  *
        !           596:  *----------------------------------------------------------------------
        !           597:  */
        !           598: 
        !           599:        /* ARGSUSED */
        !           600: int
        !           601: Tcl_ListCmd(dummy, interp, argc, argv)
        !           602:     ClientData dummy;                  /* Not used. */
        !           603:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           604:     int argc;                          /* Number of arguments. */
        !           605:     char **argv;                       /* Argument strings. */
        !           606: {
        !           607: #pragma ref dummy
        !           608:     if (argc < 2) {
        !           609:        sprintf(interp->result,
        !           610:                "not enough args:  should be \"%.50s arg [arg ...]\"",
        !           611:                argv[0]);
        !           612:        return TCL_ERROR;
        !           613:     }
        !           614:     interp->result = Tcl_Merge(argc-1, argv+1);
        !           615:     interp->dynamic = 1;
        !           616:     return TCL_OK;
        !           617: }
        !           618: 
        !           619: /*
        !           620:  *----------------------------------------------------------------------
        !           621:  *
        !           622:  * Tcl_PrintCmd --
        !           623:  *
        !           624:  *     This procedure is invoked to process the "print" Tcl command.
        !           625:  *     See the user documentation for details on what it does.
        !           626:  *
        !           627:  * Results:
        !           628:  *     A standard Tcl result.
        !           629:  *
        !           630:  * Side effects:
        !           631:  *     See the user documentation.
        !           632:  *
        !           633:  *----------------------------------------------------------------------
        !           634:  */
        !           635: 
        !           636:        /* ARGSUSED */
        !           637: int
        !           638: Tcl_PrintCmd(notUsed, interp, argc, argv)
        !           639:     ClientData notUsed;                        /* Not used. */
        !           640:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           641:     int argc;                          /* Number of arguments. */
        !           642:     char **argv;                       /* Argument strings. */
        !           643: {
        !           644: #pragma ref notUsed
        !           645:     FILE *f;
        !           646:     int result;
        !           647: 
        !           648:     if ((argc < 2) || (argc > 4)) {
        !           649:        sprintf(interp->result,
        !           650:                "wrong # args: should be \"%.50s string [file [append]]\"",
        !           651:                argv[0]);
        !           652:        return TCL_ERROR;
        !           653:     }
        !           654: 
        !           655:     if (argc == 2) {
        !           656:        f = stdout;
        !           657:     } else {
        !           658:        if (argc == 4) {
        !           659:            if (strncmp(argv[3], "append", strlen(argv[3])) != 0) {
        !           660:                sprintf(interp->result,
        !           661:                        "bad option \"%.50s\":  must be \"append\"",
        !           662:                        argv[3]);
        !           663:                return TCL_ERROR;
        !           664:            }
        !           665:            f = fopen(argv[2], "a");
        !           666:        } else {
        !           667:            f = fopen(argv[2], "w");
        !           668:        }
        !           669:        if (f == NULL) {
        !           670:            sprintf(interp->result, "couldn't open \"%.50s\": %.80s",
        !           671:                    argv[2], strerror(errno));
        !           672:            return TCL_ERROR;
        !           673:        }
        !           674:     }
        !           675:     fputs(argv[1], f);
        !           676:     if (argc == 2) {
        !           677:        result = fflush(stdout);
        !           678:     } else {
        !           679:        result = fclose(f);
        !           680:     }
        !           681:     if (result == EOF) {
        !           682:        sprintf(interp->result, "I/O error while writing: %.50s",
        !           683:                strerror(errno));
        !           684:        return TCL_ERROR;
        !           685:     }
        !           686:     return TCL_OK;
        !           687: }
        !           688: 
        !           689: /*
        !           690:  *----------------------------------------------------------------------
        !           691:  *
        !           692:  * Tcl_RangeCmd --
        !           693:  *
        !           694:  *     This procedure is invoked to process the "range" Tcl command.
        !           695:  *     See the user documentation for details on what it does.
        !           696:  *
        !           697:  * Results:
        !           698:  *     A standard Tcl result.
        !           699:  *
        !           700:  * Side effects:
        !           701:  *     See the user documentation.
        !           702:  *
        !           703:  *----------------------------------------------------------------------
        !           704:  */
        !           705: 
        !           706:        /* ARGSUSED */
        !           707: int
        !           708: Tcl_RangeCmd(notUsed, interp, argc, argv)
        !           709:     ClientData notUsed;                        /* Not used. */
        !           710:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           711:     int argc;                          /* Number of arguments. */
        !           712:     char **argv;                       /* Argument strings. */
        !           713: {
        !           714: #pragma ref notUsed
        !           715:     int first, last, result;
        !           716:     char *begin, *end, c, *dummy;
        !           717:     int count;
        !           718: 
        !           719:     if (argc < 4) {
        !           720:        rangeSyntax:
        !           721:        sprintf(interp->result, "wrong #/type of args: should be \"%.50s value first last [chars]\"",
        !           722:                argv[0]);
        !           723:        return TCL_ERROR;
        !           724:     }
        !           725:     first = atoi(argv[2]);
        !           726:     if (!isdigit(*argv[2]) || (first < 0)) {
        !           727:        sprintf(interp->result, "bad range specifier \"%.50s\"", argv[2]);
        !           728:        return TCL_ERROR;
        !           729:     }
        !           730:     if ((*argv[3] == 'e') && (strncmp(argv[3], "end", strlen(argv[3])) == 0)) {
        !           731:        last = -1;
        !           732:     } else {
        !           733:        last = atoi(argv[3]);
        !           734:        if (!isdigit(*argv[3]) || (last < 0)) {
        !           735:            sprintf(interp->result, "bad range specifier \"%.50s\"", argv[3]);
        !           736:            return TCL_ERROR;
        !           737:        }
        !           738:     }
        !           739: 
        !           740:     if (argc == 5) {
        !           741:        count = strlen(argv[4]);
        !           742:        if ((count == 0) || (strncmp(argv[4], "chars", count) != 0)) {
        !           743:            goto rangeSyntax;
        !           744:        }
        !           745: 
        !           746:        /*
        !           747:         * Extract a range of characters.
        !           748:         */
        !           749: 
        !           750:        count = strlen(argv[1]);
        !           751:        if (first >= count) {
        !           752:            interp->result = "";
        !           753:            return TCL_OK;
        !           754:        }
        !           755:        begin = argv[1] + first;
        !           756:        if ((last == -1) || (last >= count)) {
        !           757:            last = count;
        !           758:        } else if (last < first) {
        !           759:            interp->result = "";
        !           760:            return TCL_OK;
        !           761:        }
        !           762:        end = argv[1] + last + 1;
        !           763:     } else {
        !           764:        if (argc != 4) {
        !           765:            goto rangeSyntax;
        !           766:        }
        !           767: 
        !           768:        /*
        !           769:         * Extract a range of fields.
        !           770:         */
        !           771: 
        !           772:        for (count = 0, begin = argv[1]; count < first; count++) {
        !           773:            result = TclFindElement(interp, begin, &dummy, &begin, (int *) NULL,
        !           774:                    (int *) NULL);
        !           775:            if (result != TCL_OK) {
        !           776:                return result;
        !           777:            }
        !           778:            if (*begin == 0) {
        !           779:                break;
        !           780:            }
        !           781:        }
        !           782:        if (last == -1) {
        !           783:            Tcl_Return(interp, begin, TCL_VOLATILE);
        !           784:            return TCL_OK;
        !           785:        }
        !           786:        if (last < first) {
        !           787:            interp->result = "";
        !           788:            return TCL_OK;
        !           789:        }
        !           790:        for (count = first, end = begin; (count <= last) && (*end != 0);
        !           791:                count++) {
        !           792:            result = TclFindElement(interp, end, &dummy, &end, (int *) NULL,
        !           793:                    (int *) NULL);
        !           794:            if (result != TCL_OK) {
        !           795:                return result;
        !           796:            }
        !           797:        }
        !           798: 
        !           799:        /*
        !           800:         * Chop off trailing spaces.
        !           801:         */
        !           802: 
        !           803:        while (isspace(end[-1])) {
        !           804:            end--;
        !           805:        }
        !           806:     }
        !           807:     c = *end;
        !           808:     *end = 0;
        !           809:     Tcl_Return(interp, begin, TCL_VOLATILE);
        !           810:     *end = c;
        !           811:     return TCL_OK;
        !           812: }
        !           813: 
        !           814: /*
        !           815:  *----------------------------------------------------------------------
        !           816:  *
        !           817:  * Tcl_RenameCmd --
        !           818:  *
        !           819:  *     This procedure is invoked to process the "rename" Tcl command.
        !           820:  *     See the user documentation for details on what it does.
        !           821:  *
        !           822:  * Results:
        !           823:  *     A standard Tcl result.
        !           824:  *
        !           825:  * Side effects:
        !           826:  *     See the user documentation.
        !           827:  *
        !           828:  *----------------------------------------------------------------------
        !           829:  */
        !           830: 
        !           831:        /* ARGSUSED */
        !           832: int
        !           833: Tcl_RenameCmd(dummy, interp, argc, argv)
        !           834:     ClientData dummy;                  /* Not used. */
        !           835:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           836:     int argc;                          /* Number of arguments. */
        !           837:     char **argv;                       /* Argument strings. */
        !           838: {
        !           839: #pragma ref dummy
        !           840:     register Command *oldPtr, *newPtr;
        !           841:     Interp *iPtr = (Interp *) interp;
        !           842: 
        !           843:     if (argc != 3) {
        !           844:        sprintf(interp->result,
        !           845:                "wrong # args: should be \"%.50s oldName newName\"",
        !           846:                argv[0]);
        !           847:        return TCL_ERROR;
        !           848:     }
        !           849:     if (argv[2][0] == '\0') {
        !           850:        Tcl_DeleteCommand(interp, argv[1]);
        !           851:        return TCL_OK;
        !           852:     }
        !           853:     newPtr = TclFindCmd(iPtr, argv[2], 0);
        !           854:     if (newPtr != NULL) {
        !           855:        sprintf(interp->result, "can't rename to \"%.50s\": already exists",
        !           856:                argv[2]);
        !           857:        return TCL_ERROR;
        !           858:     }
        !           859:     oldPtr = TclFindCmd(iPtr, argv[1], 0);
        !           860:     if (oldPtr == NULL) {
        !           861:        sprintf(interp->result,
        !           862:                "can't rename \"%.50s\":  command doesn't exist",
        !           863:                argv[1]);
        !           864:        return TCL_ERROR;
        !           865:     }
        !           866:     iPtr->commandPtr = oldPtr->nextPtr;
        !           867:     newPtr = (Command *) malloc(CMD_SIZE(strlen(argv[2])));
        !           868:     newPtr->proc = oldPtr->proc;
        !           869:     newPtr->clientData = oldPtr->clientData;
        !           870:     newPtr->deleteProc = oldPtr->deleteProc;
        !           871:     newPtr->nextPtr = iPtr->commandPtr;
        !           872:     iPtr->commandPtr = newPtr;
        !           873:     strcpy(newPtr->name, argv[2]);
        !           874:     free((char *) oldPtr);
        !           875:     return TCL_OK;
        !           876: }
        !           877: 
        !           878: /*
        !           879:  *----------------------------------------------------------------------
        !           880:  *
        !           881:  * Tcl_ReturnCmd --
        !           882:  *
        !           883:  *     This procedure is invoked to process the "return" Tcl command.
        !           884:  *     See the user documentation for details on what it does.
        !           885:  *
        !           886:  * Results:
        !           887:  *     A standard Tcl result.
        !           888:  *
        !           889:  * Side effects:
        !           890:  *     See the user documentation.
        !           891:  *
        !           892:  *----------------------------------------------------------------------
        !           893:  */
        !           894: 
        !           895:        /* ARGSUSED */
        !           896: int
        !           897: Tcl_ReturnCmd(dummy, interp, argc, argv)
        !           898:     ClientData dummy;                  /* Not used. */
        !           899:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           900:     int argc;                          /* Number of arguments. */
        !           901:     char **argv;                       /* Argument strings. */
        !           902: {
        !           903: #pragma ref dummy
        !           904:     if (argc > 2) {
        !           905:        sprintf(interp->result, "too many args: should be \"%.50s [value]\"",
        !           906:                argv[0]);
        !           907:        return TCL_ERROR;
        !           908:     }
        !           909:     if (argc == 2) {
        !           910:        Tcl_Return(interp, argv[1], TCL_VOLATILE);
        !           911:     }
        !           912:     return TCL_RETURN;
        !           913: }
        !           914: 
        !           915: /*
        !           916:  *----------------------------------------------------------------------
        !           917:  *
        !           918:  * Tcl_ScanCmd --
        !           919:  *
        !           920:  *     This procedure is invoked to process the "scan" Tcl command.
        !           921:  *     See the user documentation for details on what it does.
        !           922:  *
        !           923:  * Results:
        !           924:  *     A standard Tcl result.
        !           925:  *
        !           926:  * Side effects:
        !           927:  *     See the user documentation.
        !           928:  *
        !           929:  *----------------------------------------------------------------------
        !           930:  */
        !           931: 
        !           932:        /* ARGSUSED */
        !           933: int
        !           934: Tcl_ScanCmd(dummy, interp, argc, argv)
        !           935:     ClientData dummy;                  /* Not used. */
        !           936:     Tcl_Interp *interp;                        /* Current interpreter. */
        !           937:     int argc;                          /* Number of arguments. */
        !           938:     char **argv;                       /* Argument strings. */
        !           939: {
        !           940: #pragma ref dummy
        !           941:     int arg1Length;                    /* Number of bytes in argument to be
        !           942:                                         * scanned.  This gives an upper limit
        !           943:                                         * on string field sizes. */
        !           944: #   define MAX_FIELDS 20
        !           945:     typedef struct {
        !           946:        char fmt;                       /* Format for field. */
        !           947:        int size;                       /* How many bytes to allow for
        !           948:                                         * field. */
        !           949:        char *location;                 /* Where field will be stored. */
        !           950:     } Field;
        !           951:     Field fields[MAX_FIELDS];          /* Info about all the fields in the
        !           952:                                         * format string. */
        !           953:     register Field *curField;
        !           954:     int numFields = 0;                 /* Number of fields actually
        !           955:                                         * specified. */
        !           956:     int suppress;                      /* Current field is assignment-
        !           957:                                         * suppressed. */
        !           958:     int totalSize = 0;                 /* Number of bytes needed to store
        !           959:                                         * all results combined. */
        !           960:     char *results;                     /* Where scanned output goes.  */
        !           961:     int numScanned;                    /* sscanf's result. */
        !           962:     register char *fmt;
        !           963:     int i;
        !           964: 
        !           965:     if (argc < 3) {
        !           966:        sprintf(interp->result,
        !           967:                "too few args: should be \"%.50s string format varName ...\"",
        !           968:                argv[0]);
        !           969:        return TCL_ERROR;
        !           970:     }
        !           971: 
        !           972:     /*
        !           973:      * This procedure operates in four stages:
        !           974:      * 1. Scan the format string, collecting information about each field.
        !           975:      * 2. Allocate an array to hold all of the scanned fields.
        !           976:      * 3. Call sscanf to do all the dirty work, and have it store the
        !           977:      *    parsed fields in the array.
        !           978:      * 4. Pick off the fields from the array and assign them to variables.
        !           979:      */
        !           980: 
        !           981:     arg1Length = (strlen(argv[1]) + 4) & ~03;
        !           982:     for (fmt = argv[2]; *fmt != 0; fmt++) {
        !           983:        if (*fmt != '%') {
        !           984:            continue;
        !           985:        }
        !           986:        fmt++;
        !           987:        if (*fmt == '*') {
        !           988:            suppress = 1;
        !           989:            fmt++;
        !           990:        } else {
        !           991:            suppress = 0;
        !           992:        }
        !           993:        while (isdigit(*fmt)) {
        !           994:            fmt++;
        !           995:        }
        !           996:        if (suppress) {
        !           997:            continue;
        !           998:        }
        !           999:        if (numFields == MAX_FIELDS) {
        !          1000:            sprintf(interp->result,
        !          1001:                    "can't have more than %d fields in \"%.50s\"", MAX_FIELDS,
        !          1002:                    argv[0]);
        !          1003:            return TCL_ERROR;
        !          1004:        }
        !          1005:        curField = &fields[numFields];
        !          1006:        numFields++;
        !          1007:        switch (*fmt) {
        !          1008:            case 'D':
        !          1009:            case 'O':
        !          1010:            case 'X':
        !          1011:            case 'd':
        !          1012:            case 'o':
        !          1013:            case 'x':
        !          1014:                curField->fmt = 'd';
        !          1015:                curField->size = sizeof(int);
        !          1016:                break;
        !          1017: 
        !          1018:            case 's':
        !          1019:                curField->fmt = 's';
        !          1020:                curField->size = arg1Length;
        !          1021:                break;
        !          1022: 
        !          1023:            case 'c':
        !          1024:                curField->fmt = 'c';
        !          1025:                curField->size = sizeof(int);
        !          1026:                break;
        !          1027: 
        !          1028:            case 'E':
        !          1029:            case 'F':
        !          1030:                curField->fmt = 'F';
        !          1031:                curField->size = 8;
        !          1032:                break;
        !          1033: 
        !          1034:            case 'e':
        !          1035:            case 'f':
        !          1036:                curField->fmt = 'f';
        !          1037:                curField->size = 4;
        !          1038:                break;
        !          1039: 
        !          1040:            case '[':
        !          1041:                curField->fmt = 's';
        !          1042:                curField->size = arg1Length;
        !          1043:                do {
        !          1044:                    fmt++;
        !          1045:                } while (*fmt != ']');
        !          1046:                break;
        !          1047: 
        !          1048:            default:
        !          1049:                sprintf(interp->result, "bad scan conversion character \"%c\"",
        !          1050:                        *fmt);
        !          1051:                return TCL_ERROR;
        !          1052:        }
        !          1053:        totalSize += curField->size;
        !          1054:     }
        !          1055: 
        !          1056:     if (numFields != (argc-3)) {
        !          1057:        interp->result =
        !          1058:                "different numbers of variable names and field specifiers";
        !          1059:        return TCL_ERROR;
        !          1060:     }
        !          1061: 
        !          1062:     /*
        !          1063:      * Step 2:
        !          1064:      */
        !          1065: 
        !          1066:     results = (char *) malloc((unsigned) totalSize);
        !          1067:     for (i = 0, totalSize = 0, curField = fields;
        !          1068:            i < numFields; i++, curField++) {
        !          1069:        curField->location = results + totalSize;
        !          1070:        totalSize += curField->size;
        !          1071:     }
        !          1072: 
        !          1073:     /*
        !          1074:      * Step 3:
        !          1075:      */
        !          1076: 
        !          1077:     numScanned = sscanf(argv[1], argv[2],
        !          1078:            fields[0].location, fields[1].location, fields[2].location,
        !          1079:            fields[3].location, fields[4].location);
        !          1080: 
        !          1081:     /*
        !          1082:      * Step 4:
        !          1083:      */
        !          1084: 
        !          1085:     if (numScanned < numFields) {
        !          1086:        numFields = numScanned;
        !          1087:     }
        !          1088:     for (i = 0, curField = fields; i < numFields; i++, curField++) {
        !          1089:        switch (curField->fmt) {
        !          1090:            char string[30];
        !          1091: 
        !          1092:            case 'd':
        !          1093:                sprintf(string, "%d", *((int *) curField->location));
        !          1094:                Tcl_SetVar(interp, argv[i+3], string, 0);
        !          1095:                break;
        !          1096: 
        !          1097:            case 'c':
        !          1098:                sprintf(string, "%d", *((char *) curField->location) & 0xff);
        !          1099:                Tcl_SetVar(interp, argv[i+3], string, 0);
        !          1100:                break;
        !          1101: 
        !          1102:            case 's':
        !          1103:                Tcl_SetVar(interp, argv[i+3], curField->location, 0);
        !          1104:                break;
        !          1105: 
        !          1106:            case 'F':
        !          1107:                sprintf(string, "%g", *((double *) curField->location));
        !          1108:                Tcl_SetVar(interp, argv[i+3], string, 0);
        !          1109:                break;
        !          1110: 
        !          1111:            case 'f':
        !          1112:                sprintf(string, "%g", *((float *) curField->location));
        !          1113:                Tcl_SetVar(interp, argv[i+3], string, 0);
        !          1114:                break;
        !          1115:        }
        !          1116:     }
        !          1117:     free(results);
        !          1118:     sprintf(interp->result, "%d", numScanned);
        !          1119:     return TCL_OK;
        !          1120: }
        !          1121: 
        !          1122: /*
        !          1123:  *----------------------------------------------------------------------
        !          1124:  *
        !          1125:  * Tcl_SourceCmd --
        !          1126:  *
        !          1127:  *     This procedure is invoked to process the "source" Tcl command.
        !          1128:  *     See the user documentation for details on what it does.
        !          1129:  *
        !          1130:  * Results:
        !          1131:  *     A standard Tcl result.
        !          1132:  *
        !          1133:  * Side effects:
        !          1134:  *     See the user documentation.
        !          1135:  *
        !          1136:  *----------------------------------------------------------------------
        !          1137:  */
        !          1138: 
        !          1139:        /* ARGSUSED */
        !          1140: int
        !          1141: Tcl_SourceCmd(dummy, interp, argc, argv)
        !          1142:     ClientData dummy;                  /* Not used. */
        !          1143:     Tcl_Interp *interp;                        /* Current interpreter. */
        !          1144:     int argc;                          /* Number of arguments. */
        !          1145:     char **argv;                       /* Argument strings. */
        !          1146: {
        !          1147: #pragma ref dummy
        !          1148:     int fileId, result;
        !          1149:     struct stat statBuf;
        !          1150:     char *cmdBuffer, *end;
        !          1151:     char *fileName;
        !          1152: 
        !          1153:     if (argc != 2) {
        !          1154:        sprintf(interp->result, "wrong # args: should be \"%.50s fileName\"",
        !          1155:                argv[0]);
        !          1156:        return TCL_ERROR;
        !          1157:     }
        !          1158:     fileName = Tcl_TildeSubst(interp, argv[1]);
        !          1159:     if (fileName == NULL) {
        !          1160:        return TCL_ERROR;
        !          1161:     }
        !          1162:     fileId = open(fileName, O_RDONLY, 0);
        !          1163:     if (fileId < 0) {
        !          1164:        sprintf(interp->result, "couldn't read file \"%.50s\"", argv[1]);
        !          1165:        return TCL_ERROR;
        !          1166:     }
        !          1167:     if (fstat(fileId, &statBuf) == -1) {
        !          1168:        sprintf(interp->result, "couldn't stat file \"%.50s\"", argv[1]);
        !          1169:        close(fileId);
        !          1170:        return TCL_ERROR;
        !          1171:     }
        !          1172:     cmdBuffer = (char *) malloc((unsigned) statBuf.st_size+1);
        !          1173:     if (read(fileId, cmdBuffer, (int) statBuf.st_size) != statBuf.st_size) {
        !          1174:        sprintf(interp->result, "error in reading file \"%.50s\"", argv[1]);
        !          1175:        close(fileId);
        !          1176:        return TCL_ERROR;
        !          1177:     }
        !          1178:     close(fileId);
        !          1179:     cmdBuffer[statBuf.st_size] = 0;
        !          1180:     result = Tcl_Eval(interp, cmdBuffer, 0, &end);
        !          1181:     if (result == TCL_RETURN) {
        !          1182:        result = TCL_OK;
        !          1183:     }
        !          1184:     if (result == TCL_ERROR) {
        !          1185:        char msg[100];
        !          1186: 
        !          1187:        /*
        !          1188:         * Record information telling where the error occurred.
        !          1189:         */
        !          1190: 
        !          1191:        sprintf(msg, " (file \"%.50s\" line %d)", argv[1], interp->errorLine);
        !          1192:        Tcl_AddErrorInfo(interp, msg);
        !          1193:     }
        !          1194:     free(cmdBuffer);
        !          1195:     return result;
        !          1196: }
        !          1197: 
        !          1198: /*
        !          1199:  *----------------------------------------------------------------------
        !          1200:  *
        !          1201:  * Tcl_StringCmd --
        !          1202:  *
        !          1203:  *     This procedure is invoked to process the "string" Tcl command.
        !          1204:  *     See the user documentation for details on what it does.
        !          1205:  *
        !          1206:  * Results:
        !          1207:  *     A standard Tcl result.
        !          1208:  *
        !          1209:  * Side effects:
        !          1210:  *     See the user documentation.
        !          1211:  *
        !          1212:  *----------------------------------------------------------------------
        !          1213:  */
        !          1214: 
        !          1215:        /* ARGSUSED */
        !          1216: int
        !          1217: Tcl_StringCmd(dummy, interp, argc, argv)
        !          1218:     ClientData dummy;                  /* Not used. */
        !          1219:     Tcl_Interp *interp;                        /* Current interpreter. */
        !          1220:     int argc;                          /* Number of arguments. */
        !          1221:     char **argv;                       /* Argument strings. */
        !          1222: {
        !          1223: #pragma ref dummy
        !          1224:     int length;
        !          1225:     register char *p, c;
        !          1226:     int match;
        !          1227:     int first;
        !          1228: 
        !          1229:     if (argc != 4) {
        !          1230:        sprintf(interp->result,
        !          1231:                "wrong # args: should be \"%.50s option a b\"",
        !          1232:                argv[0]);
        !          1233:        return TCL_ERROR;
        !          1234:     }
        !          1235:     length = strlen(argv[1]);
        !          1236:     if (strncmp(argv[1], "compare", length) == 0) {
        !          1237:        match = strcmp(argv[2], argv[3]);
        !          1238:        if (match > 0) {
        !          1239:            interp->result = "1";
        !          1240:        } else if (match < 0) {
        !          1241:            interp->result = "-1";
        !          1242:        } else {
        !          1243:            interp->result = "0";
        !          1244:        }
        !          1245:        return TCL_OK;
        !          1246:     }
        !          1247:     if (strncmp(argv[1], "first", length) == 0) {
        !          1248:        first = 1;
        !          1249:     } else if (strncmp(argv[1], "last", length) == 0) {
        !          1250:        first = 0;
        !          1251:     } else if (strncmp(argv[1], "match", length) == 0) {
        !          1252:        if (Tcl_StringMatch(argv[3], argv[2]) != 0) {
        !          1253:            interp->result = "1";
        !          1254:        } else {
        !          1255:            interp->result = "0";
        !          1256:        }
        !          1257:        return TCL_OK;
        !          1258:     } else {
        !          1259:        sprintf(interp->result,
        !          1260:                "bad \"%.50s\" option \"%.50s\": must be compare, first, or last",
        !          1261:                argv[0], argv[1]);
        !          1262:        return TCL_ERROR;
        !          1263:     }
        !          1264:     match = -1;
        !          1265:     c = *argv[2];
        !          1266:     length = strlen(argv[2]);
        !          1267:     for (p = argv[3]; *p != 0; p++) {
        !          1268:        if (*p != c) {
        !          1269:            continue;
        !          1270:        }
        !          1271:        if (strncmp(argv[2], p, length) == 0) {
        !          1272:            match = p-argv[3];
        !          1273:            if (first) {
        !          1274:                break;
        !          1275:            }
        !          1276:        }
        !          1277:     }
        !          1278:     sprintf(interp->result, "%d", match);
        !          1279:     return TCL_OK;
        !          1280: }
        !          1281: 
        !          1282: /*
        !          1283:  *----------------------------------------------------------------------
        !          1284:  *
        !          1285:  * Tcl_TimeCmd --
        !          1286:  *
        !          1287:  *     This procedure is invoked to process the "time" Tcl command.
        !          1288:  *     See the user documentation for details on what it does.
        !          1289:  *
        !          1290:  * Results:
        !          1291:  *     A standard Tcl result.
        !          1292:  *
        !          1293:  * Side effects:
        !          1294:  *     See the user documentation.
        !          1295:  *
        !          1296:  *----------------------------------------------------------------------
        !          1297:  */
        !          1298: 
        !          1299:        /* ARGSUSED */
        !          1300: int
        !          1301: Tcl_TimeCmd(dummy, interp, argc, argv)
        !          1302:     ClientData dummy;                  /* Not used. */
        !          1303:     Tcl_Interp *interp;                        /* Current interpreter. */
        !          1304:     int argc;                          /* Number of arguments. */
        !          1305:     char **argv;                       /* Argument strings. */
        !          1306: {
        !          1307: #pragma ref dummy
        !          1308:     int count, i, result;
        !          1309:     struct tms start, stop;
        !          1310:     int micros;
        !          1311:     double timePer;
        !          1312: 
        !          1313:     if (argc == 2) {
        !          1314:        count = 1;
        !          1315:     } else if (argc == 3) {
        !          1316:        if (sscanf(argv[2], "%d", &count) != 1) {
        !          1317:            sprintf(interp->result, "bad count \"%.50s\" given to \"%.50s\"",
        !          1318:                    argv[2], argv[0]);
        !          1319:            return TCL_ERROR;
        !          1320:        }
        !          1321:     } else {
        !          1322:        sprintf(interp->result,
        !          1323:                "wrong # args: should be \"%.50s command [count]\"",
        !          1324:                argv[0]);
        !          1325:        return TCL_ERROR;
        !          1326:     }
        !          1327:     times(&start);
        !          1328:     for (i = count ; i > 0; i--) {
        !          1329:        result = Tcl_Eval(interp, argv[1], 0, (char **) NULL);
        !          1330:        if (result != TCL_OK) {
        !          1331:            if (result == TCL_ERROR) {
        !          1332:                char msg[60];
        !          1333:                sprintf(msg, " (\"time\" body line %d)", interp->errorLine);
        !          1334:                Tcl_AddErrorInfo(interp, msg);
        !          1335:            }
        !          1336:            return result;
        !          1337:        }
        !          1338:     }
        !          1339:     times(&stop);
        !          1340:     micros = (stop.tms_utime - start.tms_utime)*1000000;
        !          1341:     timePer = micros;
        !          1342:     Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !          1343:     sprintf(interp->result, "%.0f microseconds per iteration", timePer/count);
        !          1344:     return TCL_OK;
        !          1345: }

unix.superglobalmegacorp.com

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