Annotation of micropolis/src/tcl/tclcmdil.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * tclCmdIL.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 through L.  It contains only commands in the generic core
                      7:  *     (i.e. those that don't depend much upon UNIX facilities).
                      8:  *
                      9:  * Copyright 1987-1991 Regents of the University of California
                     10:  * Permission to use, copy, modify, and distribute this
                     11:  * software and its documentation for any purpose and without
                     12:  * fee is hereby granted, provided that the above copyright
                     13:  * notice appear in all copies.  The University of California
                     14:  * makes no representations about the suitability of this
                     15:  * software for any purpose.  It is provided "as is" without
                     16:  * express or implied warranty.
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclCmdIL.c,v 1.84 91/12/06 10:42:36 ouster Exp $ SPRITE (Berkeley)";
                     21: #endif
                     22: 
                     23: #include "tclint.h"
                     24: 
                     25: /*
                     26:  * Global absolute file name:
                     27:  */
                     28: 
                     29: char *TCL_Library = TCL_LIBRARY;
                     30: 
                     31: /*
                     32:  * Forward declarations for procedures defined in this file:
                     33:  */
                     34: 
                     35: static int             SortCompareProc _ANSI_ARGS_((CONST VOID *first,
                     36:                            CONST VOID *second));
                     37: 
                     38: /*
                     39:  *----------------------------------------------------------------------
                     40:  *
                     41:  * Tcl_IfCmd --
                     42:  *
                     43:  *     This procedure is invoked to process the "if" Tcl command.
                     44:  *     See the user documentation for details on what it does.
                     45:  *
                     46:  * Results:
                     47:  *     A standard Tcl result.
                     48:  *
                     49:  * Side effects:
                     50:  *     See the user documentation.
                     51:  *
                     52:  *----------------------------------------------------------------------
                     53:  */
                     54: 
                     55:        /* ARGSUSED */
                     56: int
                     57: Tcl_IfCmd(dummy, interp, argc, argv)
                     58:     ClientData dummy;                  /* Not used. */
                     59:     Tcl_Interp *interp;                        /* Current interpreter. */
                     60:     int argc;                          /* Number of arguments. */
                     61:     char **argv;                       /* Argument strings. */
                     62: {
                     63:     char *condition, *ifPart, *elsePart, *cmd, *name;
                     64:     char *clause;
                     65:     int result, value;
                     66: 
                     67:     name = argv[0];
                     68:     if (argc < 3) {
                     69:        ifSyntax:
                     70:        Tcl_AppendResult(interp, "wrong # args: should be \"", name,
                     71:                " bool ?then? command ?else? ?command?\"", (char *) NULL);
                     72:        return TCL_ERROR;
                     73:     }
                     74:     condition = argv[1];
                     75:     argc -= 2;
                     76:     argv += 2;
                     77:     if ((**argv == 't') && (strncmp(*argv, "then", strlen(*argv)) == 0)) {
                     78:        argc--;
                     79:        argv++;
                     80:     }
                     81:     if (argc < 1) {
                     82:        goto ifSyntax;
                     83:     }
                     84:     ifPart = *argv;
                     85:     argv++;
                     86:     argc--;
                     87:     if (argc == 0) {
                     88:        elsePart = "";
                     89:     } else {
                     90:        if ((**argv == 'e') && (strncmp(*argv, "else", strlen(*argv)) == 0)) {
                     91:            argc--;
                     92:            argv++;
                     93:        }
                     94:        if (argc != 1) {
                     95:            goto ifSyntax;
                     96:        }
                     97:        elsePart = *argv;
                     98:     }
                     99: 
                    100:     cmd = ifPart;
                    101:     clause = "\"then\" clause";
                    102:     result = Tcl_ExprBoolean(interp, condition, &value);
                    103:     if (result != TCL_OK) {
                    104:        if (result == TCL_ERROR) {
                    105:            char msg[60];
                    106:            sprintf(msg, "\n    (\"if\" test line %d)", interp->errorLine);
                    107:            Tcl_AddErrorInfo(interp, msg);
                    108:        }
                    109:        return result;
                    110:     }
                    111:     if (value == 0) {
                    112:        cmd = elsePart;
                    113:        clause = "\"else\" clause";
                    114:     }
                    115:     if (*cmd == 0) {
                    116:        return TCL_OK;
                    117:     }
                    118:     result = Tcl_Eval(interp, cmd, 0, (char **) NULL);
                    119:     if (result == TCL_ERROR) {
                    120:        char msg[60];
                    121:        sprintf(msg, "\n    (%s line %d)", clause, interp->errorLine);
                    122:        Tcl_AddErrorInfo(interp, msg);
                    123:     }
                    124:     return result;
                    125: }
                    126: 
                    127: /*
                    128:  *----------------------------------------------------------------------
                    129:  *
                    130:  * Tcl_IncrCmd --
                    131:  *
                    132:  *     This procedure is invoked to process the "incr" Tcl command.
                    133:  *     See the user documentation for details on what it does.
                    134:  *
                    135:  * Results:
                    136:  *     A standard Tcl result.
                    137:  *
                    138:  * Side effects:
                    139:  *     See the user documentation.
                    140:  *
                    141:  *----------------------------------------------------------------------
                    142:  */
                    143: 
                    144:     /* ARGSUSED */
                    145: int
                    146: Tcl_IncrCmd(dummy, interp, argc, argv)
                    147:     ClientData dummy;                  /* Not used. */
                    148:     Tcl_Interp *interp;                        /* Current interpreter. */
                    149:     int argc;                          /* Number of arguments. */
                    150:     char **argv;                       /* Argument strings. */
                    151: {
                    152:     int value;
                    153:     char *oldString, *result;
                    154:     char newString[30];
                    155: 
                    156:     if ((argc != 2) && (argc != 3)) {
                    157:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    158:                " varName ?increment?\"", (char *) NULL);
                    159:        return TCL_ERROR;
                    160:     }
                    161: 
                    162:     oldString = Tcl_GetVar(interp, argv[1], TCL_LEAVE_ERR_MSG);
                    163:     if (oldString == NULL) {
                    164:        return TCL_ERROR;
                    165:     }
                    166:     if (Tcl_GetInt(interp, oldString, &value) != TCL_OK) {
                    167:        Tcl_AddErrorInfo(interp,
                    168:                "\n    (reading value of variable to increment)");
                    169:        return TCL_ERROR;
                    170:     }
                    171:     if (argc == 2) {
                    172:        value += 1;
                    173:     } else {
                    174:        int increment;
                    175: 
                    176:        if (Tcl_GetInt(interp, argv[2], &increment) != TCL_OK) {
                    177:            Tcl_AddErrorInfo(interp,
                    178:                    "\n    (reading increment)");
                    179:            return TCL_ERROR;
                    180:        }
                    181:        value += increment;
                    182:     }
                    183:     sprintf(newString, "%d", value);
                    184:     result = Tcl_SetVar(interp, argv[1], newString, TCL_LEAVE_ERR_MSG);
                    185:     if (result == NULL) {
                    186:        return TCL_ERROR;
                    187:     }
                    188:     interp->result = result;
                    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:     register Interp *iPtr = (Interp *) interp;
                    218:     int length;
                    219:     char c;
                    220:     Arg *argPtr;
                    221:     Proc *procPtr;
                    222:     Var *varPtr;
                    223:     Command *cmdPtr;
                    224:     Tcl_HashEntry *hPtr;
                    225:     Tcl_HashSearch search;
                    226: 
                    227:     if (argc < 2) {
                    228:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    229:                " option ?arg arg ...?\"", (char *) NULL);
                    230:        return TCL_ERROR;
                    231:     }
                    232:     c = argv[1][0];
                    233:     length = strlen(argv[1]);
                    234:     if ((c == 'a') && (strncmp(argv[1], "args", length)) == 0) {
                    235:        if (argc != 3) {
                    236:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    237:                    argv[0], " args procname\"", (char *) NULL);
                    238:            return TCL_ERROR;
                    239:        }
                    240:        procPtr = TclFindProc(iPtr, argv[2]);
                    241:        if (procPtr == NULL) {
                    242:            infoNoSuchProc:
                    243:            Tcl_AppendResult(interp, "\"", argv[2],
                    244:                    "\" isn't a procedure", (char *) NULL);
                    245:            return TCL_ERROR;
                    246:        }
                    247:        for (argPtr = procPtr->argPtr; argPtr != NULL;
                    248:                argPtr = argPtr->nextPtr) {
                    249:            Tcl_AppendElement(interp, argPtr->name, 0);
                    250:        }
                    251:        return TCL_OK;
                    252:     } else if ((c == 'b') && (strncmp(argv[1], "body", length)) == 0) {
                    253:        if (argc != 3) {
                    254:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    255:                    " body procname\"", (char *) NULL);
                    256:            return TCL_ERROR;
                    257:        }
                    258:        procPtr = TclFindProc(iPtr, argv[2]);
                    259:        if (procPtr == NULL) {
                    260:            goto infoNoSuchProc;
                    261:        }
                    262:        iPtr->result = procPtr->command;
                    263:        return TCL_OK;
                    264:     } else if ((c == 'c') && (strncmp(argv[1], "cmdcount", length) == 0)
                    265:            && (length >= 2)) {
                    266:        if (argc != 2) {
                    267:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    268:                    " cmdcount\"", (char *) NULL);
                    269:            return TCL_ERROR;
                    270:        }
                    271:        sprintf(iPtr->result, "%d", iPtr->cmdCount);
                    272:        return TCL_OK;
                    273:     } else if ((c == 'c') && (strncmp(argv[1], "commands", length) == 0)
                    274:            && (length >= 2)){
                    275:        if (argc > 3) {
                    276:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    277:                    " commands [pattern]\"", (char *) NULL);
                    278:            return TCL_ERROR;
                    279:        }
                    280:        for (hPtr = Tcl_FirstHashEntry(&iPtr->commandTable, &search);
                    281:                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
                    282:            char *name = Tcl_GetHashKey(&iPtr->commandTable, hPtr);
                    283:            if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
                    284:                continue;
                    285:            }
                    286:            Tcl_AppendElement(interp, name, 0);
                    287:        }
                    288:        return TCL_OK;
                    289:     } else if ((c == 'd') && (strncmp(argv[1], "default", length)) == 0) {
                    290:        if (argc != 5) {
                    291:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    292:                    argv[0], " default procname arg varname\"",
                    293:                    (char *) NULL);
                    294:            return TCL_ERROR;
                    295:        }
                    296:        procPtr = TclFindProc(iPtr, argv[2]);
                    297:        if (procPtr == NULL) {
                    298:            goto infoNoSuchProc;
                    299:        }
                    300:        for (argPtr = procPtr->argPtr; ; argPtr = argPtr->nextPtr) {
                    301:            if (argPtr == NULL) {
                    302:                Tcl_AppendResult(interp, "procedure \"", argv[2],
                    303:                        "\" doesn't have an argument \"", argv[3],
                    304:                        "\"", (char *) NULL);
                    305:                return TCL_ERROR;
                    306:            }
                    307:            if (strcmp(argv[3], argPtr->name) == 0) {
                    308:                if (argPtr->defValue != NULL) {
                    309:                    if (Tcl_SetVar((Tcl_Interp *) iPtr, argv[4],
                    310:                            argPtr->defValue, 0) == NULL) {
                    311:                        defStoreError:
                    312:                        Tcl_AppendResult(interp,
                    313:                                "couldn't store default value in variable \"",
                    314:                                argv[4], "\"", (char *) NULL);
                    315:                        return TCL_ERROR;
                    316:                    }
                    317:                    iPtr->result = "1";
                    318:                } else {
                    319:                    if (Tcl_SetVar((Tcl_Interp *) iPtr, argv[4], "", 0)
                    320:                            == NULL) {
                    321:                        goto defStoreError;
                    322:                    }
                    323:                    iPtr->result = "0";
                    324:                }
                    325:                return TCL_OK;
                    326:            }
                    327:        }
                    328:     } else if ((c == 'e') && (strncmp(argv[1], "exists", length) == 0)) {
                    329:        char *p;
                    330:        if (argc != 3) {
                    331:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    332:                    " exists varName\"", (char *) NULL);
                    333:            return TCL_ERROR;
                    334:        }
                    335:        p = Tcl_GetVar((Tcl_Interp *) iPtr, argv[2], 0);
                    336: 
                    337:        /*
                    338:         * The code below handles the special case where the name is for
                    339:         * an array:  Tcl_GetVar will reject this since you can't read
                    340:         * an array variable without an index.
                    341:         */
                    342: 
                    343:        if (p == NULL) {
                    344:            Tcl_HashEntry *hPtr;
                    345:            Var *varPtr;
                    346: 
                    347:            if (strchr(argv[2], '(') != NULL) {
                    348:                noVar:
                    349:                iPtr->result = "0";
                    350:                return TCL_OK;
                    351:            }
                    352:            if (iPtr->varFramePtr == NULL) {
                    353:                hPtr = Tcl_FindHashEntry(&iPtr->globalTable, argv[2]);
                    354:            } else {
                    355:                hPtr = Tcl_FindHashEntry(&iPtr->varFramePtr->varTable, argv[2]);
                    356:            }
                    357:            if (hPtr == NULL) {
                    358:                goto noVar;
                    359:            }
                    360:            varPtr = (Var *) Tcl_GetHashValue(hPtr);
                    361:            if (varPtr->flags & VAR_UPVAR) {
                    362:                varPtr = (Var *) Tcl_GetHashValue(varPtr->value.upvarPtr);
                    363:            }
                    364:            if (!(varPtr->flags & VAR_ARRAY)) {
                    365:                goto noVar;
                    366:            }
                    367:        }
                    368:        iPtr->result = "1";
                    369:        return TCL_OK;
                    370:     } else if ((c == 'g') && (strncmp(argv[1], "globals", length) == 0)) {
                    371:        char *name;
                    372: 
                    373:        if (argc > 3) {
                    374:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    375:                    " globals [pattern]\"", (char *) NULL);
                    376:            return TCL_ERROR;
                    377:        }
                    378:        for (hPtr = Tcl_FirstHashEntry(&iPtr->globalTable, &search);
                    379:                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
                    380:            varPtr = (Var *) Tcl_GetHashValue(hPtr);
                    381:            if (varPtr->flags & VAR_UNDEFINED) {
                    382:                continue;
                    383:            }
                    384:            name = Tcl_GetHashKey(&iPtr->globalTable, hPtr);
                    385:            if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
                    386:                continue;
                    387:            }
                    388:            Tcl_AppendElement(interp, name, 0);
                    389:        }
                    390:        return TCL_OK;
                    391:     } else if ((c == 'l') && (strncmp(argv[1], "level", length) == 0)
                    392:            && (length >= 2)) {
                    393:        if (argc == 2) {
                    394:            if (iPtr->varFramePtr == NULL) {
                    395:                iPtr->result = "0";
                    396:            } else {
                    397:                sprintf(iPtr->result, "%d", iPtr->varFramePtr->level);
                    398:            }
                    399:            return TCL_OK;
                    400:        } else if (argc == 3) {
                    401:            int level;
                    402:            CallFrame *framePtr;
                    403: 
                    404:            if (Tcl_GetInt(interp, argv[2], &level) != TCL_OK) {
                    405:                return TCL_ERROR;
                    406:            }
                    407:            if (level <= 0) {
                    408:                if (iPtr->varFramePtr == NULL) {
                    409:                    levelError:
                    410:                    Tcl_AppendResult(interp, "bad level \"", argv[2],
                    411:                            "\"", (char *) NULL);
                    412:                    return TCL_ERROR;
                    413:                }
                    414:                level += iPtr->varFramePtr->level;
                    415:            }
                    416:            for (framePtr = iPtr->varFramePtr; framePtr != NULL;
                    417:                    framePtr = framePtr->callerVarPtr) {
                    418:                if (framePtr->level == level) {
                    419:                    break;
                    420:                }
                    421:            }
                    422:            if (framePtr == NULL) {
                    423:                goto levelError;
                    424:            }
                    425:            iPtr->result = Tcl_Merge(framePtr->argc, framePtr->argv);
                    426:            iPtr->freeProc = (Tcl_FreeProc *) free;
                    427:            return TCL_OK;
                    428:        }
                    429:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    430:                " level [number]\"", (char *) NULL);
                    431:        return TCL_ERROR;
                    432:     } else if ((c == 'l') && (strncmp(argv[1], "library", length) == 0)
                    433:            && (length >= 2)) {
                    434:        if (argc != 2) {
                    435:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    436:                    " library\"", (char *) NULL);
                    437:            return TCL_ERROR;
                    438:        }
                    439: #ifdef TCL_LIBRARY
                    440:        interp->result = TCL_Library;
                    441:        return TCL_OK;
                    442: #else
                    443:        interp->result = "there is no Tcl library at this installation";
                    444:        return TCL_ERROR;
                    445: #endif
                    446:     } else if ((c == 'l') && (strncmp(argv[1], "locals", length) == 0)
                    447:            && (length >= 2)) {
                    448:        char *name;
                    449: 
                    450:        if (argc > 3) {
                    451:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    452:                    " locals [pattern]\"", (char *) NULL);
                    453:            return TCL_ERROR;
                    454:        }
                    455:        if (iPtr->varFramePtr == NULL) {
                    456:            return TCL_OK;
                    457:        }
                    458:        for (hPtr = Tcl_FirstHashEntry(&iPtr->varFramePtr->varTable, &search);
                    459:                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
                    460:            varPtr = (Var *) Tcl_GetHashValue(hPtr);
                    461:            if (varPtr->flags & (VAR_UNDEFINED|VAR_UPVAR)) {
                    462:                continue;
                    463:            }
                    464:            name = Tcl_GetHashKey(&iPtr->varFramePtr->varTable, hPtr);
                    465:            if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
                    466:                continue;
                    467:            }
                    468:            Tcl_AppendElement(interp, name, 0);
                    469:        }
                    470:        return TCL_OK;
                    471:     } else if ((c == 'p') && (strncmp(argv[1], "procs", length)) == 0) {
                    472:        if (argc > 3) {
                    473:            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    474:                    " procs [pattern]\"", (char *) NULL);
                    475:            return TCL_ERROR;
                    476:        }
                    477:        for (hPtr = Tcl_FirstHashEntry(&iPtr->commandTable, &search);
                    478:                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
                    479:            char *name = Tcl_GetHashKey(&iPtr->commandTable, hPtr);
                    480: 
                    481:            cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
                    482:            if (!TclIsProc(cmdPtr)) {
                    483:                continue;
                    484:            }
                    485:            if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
                    486:                continue;
                    487:            }
                    488:            Tcl_AppendElement(interp, name, 0);
                    489:        }
                    490:        return TCL_OK;
                    491:     } else if ((c == 's') && (strncmp(argv[1], "script", length) == 0)) {
                    492:        if (argc != 2) {
                    493:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    494:                    argv[0], " script\"", (char *) NULL);
                    495:            return TCL_ERROR;
                    496:        }
                    497:        if (iPtr->scriptFile != NULL) {
                    498:            interp->result = iPtr->scriptFile;
                    499:        }
                    500:        return TCL_OK;
                    501:     } else if ((c == 't') && (strncmp(argv[1], "tclversion", length) == 0)) {
                    502:        if (argc != 2) {
                    503:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    504:                    argv[0], " tclversion\"", (char *) NULL);
                    505:            return TCL_ERROR;
                    506:        }
                    507: 
                    508:        /*
                    509:         * Note:  TCL_VERSION below is expected to be set with a "-D"
                    510:         * switch in the Makefile.
                    511:         */
                    512: 
                    513:        strcpy(iPtr->result, TCL_VERSION);
                    514:        return TCL_OK;
                    515:     } else if ((c == 'v') && (strncmp(argv[1], "vars", length)) == 0) {
                    516:        Tcl_HashTable *tablePtr;
                    517:        char *name;
                    518: 
                    519:        if (argc > 3) {
                    520:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    521:                    argv[0], " vars [pattern]\"", (char *) NULL);
                    522:            return TCL_ERROR;
                    523:        }
                    524:        if (iPtr->varFramePtr == NULL) {
                    525:            tablePtr = &iPtr->globalTable;
                    526:        } else {
                    527:            tablePtr = &iPtr->varFramePtr->varTable;
                    528:        }
                    529:        for (hPtr = Tcl_FirstHashEntry(tablePtr, &search);
                    530:                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
                    531:            varPtr = (Var *) Tcl_GetHashValue(hPtr);
                    532:            if (varPtr->flags & VAR_UNDEFINED) {
                    533:                continue;
                    534:            }
                    535:            name = Tcl_GetHashKey(tablePtr, hPtr);
                    536:            if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
                    537:                continue;
                    538:            }
                    539:            Tcl_AppendElement(interp, name, 0);
                    540:        }
                    541:        return TCL_OK;
                    542:     } else {
                    543:        Tcl_AppendResult(interp, "bad option \"", argv[1],
                    544:                "\": should be args, body, commands, cmdcount, default, ",
                    545:                "exists, globals, level, library, locals, procs, ",
                    546:                "script, tclversion, or vars",
                    547:                (char *) NULL);
                    548:        return TCL_ERROR;
                    549:     }
                    550: }
                    551: 
                    552: /*
                    553:  *----------------------------------------------------------------------
                    554:  *
                    555:  * Tcl_JoinCmd --
                    556:  *
                    557:  *     This procedure is invoked to process the "join" Tcl command.
                    558:  *     See the user documentation for details on what it does.
                    559:  *
                    560:  * Results:
                    561:  *     A standard Tcl result.
                    562:  *
                    563:  * Side effects:
                    564:  *     See the user documentation.
                    565:  *
                    566:  *----------------------------------------------------------------------
                    567:  */
                    568: 
                    569:        /* ARGSUSED */
                    570: int
                    571: Tcl_JoinCmd(dummy, interp, argc, argv)
                    572:     ClientData dummy;                  /* Not used. */
                    573:     Tcl_Interp *interp;                        /* Current interpreter. */
                    574:     int argc;                          /* Number of arguments. */
                    575:     char **argv;                       /* Argument strings. */
                    576: {
                    577:     char *joinString;
                    578:     char **listArgv;
                    579:     int listArgc, i;
                    580: 
                    581:     if (argc == 2) {
                    582:        joinString = " ";
                    583:     } else if (argc == 3) {
                    584:        joinString = argv[2];
                    585:     } else {
                    586:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    587:                " list ?joinString?\"", (char *) NULL);
                    588:        return TCL_ERROR;
                    589:     }
                    590: 
                    591:     if (Tcl_SplitList(interp, argv[1], &listArgc, &listArgv) != TCL_OK) {
                    592:        return TCL_ERROR;
                    593:     }
                    594:     for (i = 0; i < listArgc; i++) {
                    595:        if (i == 0) {
                    596:            Tcl_AppendResult(interp, listArgv[0], (char *) NULL);
                    597:        } else  {
                    598:            Tcl_AppendResult(interp, joinString, listArgv[i], (char *) NULL);
                    599:        }
                    600:     }
                    601:     ckfree((char *) listArgv);
                    602:     return TCL_OK;
                    603: }
                    604: 
                    605: /*
                    606:  *----------------------------------------------------------------------
                    607:  *
                    608:  * Tcl_LindexCmd --
                    609:  *
                    610:  *     This procedure is invoked to process the "lindex" Tcl command.
                    611:  *     See the user documentation for details on what it does.
                    612:  *
                    613:  * Results:
                    614:  *     A standard Tcl result.
                    615:  *
                    616:  * Side effects:
                    617:  *     See the user documentation.
                    618:  *
                    619:  *----------------------------------------------------------------------
                    620:  */
                    621: 
                    622:     /* ARGSUSED */
                    623: int
                    624: Tcl_LindexCmd(dummy, interp, argc, argv)
                    625:     ClientData dummy;                  /* Not used. */
                    626:     Tcl_Interp *interp;                        /* Current interpreter. */
                    627:     int argc;                          /* Number of arguments. */
                    628:     char **argv;                       /* Argument strings. */
                    629: {
                    630:     char *p, *element;
                    631:     int index, size, parenthesized, result;
                    632: 
                    633:     if (argc != 3) {
                    634:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    635:                " list index\"", (char *) NULL);
                    636:        return TCL_ERROR;
                    637:     }
                    638:     if (Tcl_GetInt(interp, argv[2], &index) != TCL_OK) {
                    639:        return TCL_ERROR;
                    640:     }
                    641:     if (index < 0) {
                    642:        return TCL_OK;
                    643:     }
                    644:     for (p = argv[1] ; index >= 0; index--) {
                    645:        result = TclFindElement(interp, p, &element, &p, &size,
                    646:                &parenthesized);
                    647:        if (result != TCL_OK) {
                    648:            return result;
                    649:        }
                    650:     }
                    651:     if (size == 0) {
                    652:        return TCL_OK;
                    653:     }
                    654:     if (size >= TCL_RESULT_SIZE) {
                    655:        interp->result = (char *) ckalloc((unsigned) size+1);
                    656:        interp->freeProc = (Tcl_FreeProc *) free;
                    657:     }
                    658:     if (parenthesized) {
                    659:        memcpy((VOID *) interp->result, (VOID *) element, size);
                    660:        interp->result[size] = 0;
                    661:     } else {
                    662:        TclCopyAndCollapse(size, element, interp->result);
                    663:     }
                    664:     return TCL_OK;
                    665: }
                    666: 
                    667: /*
                    668:  *----------------------------------------------------------------------
                    669:  *
                    670:  * Tcl_LinsertCmd --
                    671:  *
                    672:  *     This procedure is invoked to process the "linsert" Tcl command.
                    673:  *     See the user documentation for details on what it does.
                    674:  *
                    675:  * Results:
                    676:  *     A standard Tcl result.
                    677:  *
                    678:  * Side effects:
                    679:  *     See the user documentation.
                    680:  *
                    681:  *----------------------------------------------------------------------
                    682:  */
                    683: 
                    684:        /* ARGSUSED */
                    685: int
                    686: Tcl_LinsertCmd(dummy, interp, argc, argv)
                    687:     ClientData dummy;                  /* Not used. */
                    688:     Tcl_Interp *interp;                        /* Current interpreter. */
                    689:     int argc;                          /* Number of arguments. */
                    690:     char **argv;                       /* Argument strings. */
                    691: {
                    692:     char *p, *element, savedChar;
                    693:     int i, index, count, result, size;
                    694: 
                    695:     if (argc < 4) {
                    696:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    697:                " list index element ?element ...?\"", (char *) NULL);
                    698:        return TCL_ERROR;
                    699:     }
                    700:     if (Tcl_GetInt(interp, argv[2], &index) != TCL_OK) {
                    701:        return TCL_ERROR;
                    702:     }
                    703: 
                    704:     /*
                    705:      * Skip over the first "index" elements of the list, then add
                    706:      * all of those elements to the result.
                    707:      */
                    708: 
                    709:     size = 0;
                    710:     element = argv[1];
                    711:     for (count = 0, p = argv[1]; (count < index) && (*p != 0); count++) {
                    712:        result = TclFindElement(interp, p, &element, &p, &size, (int *) NULL);
                    713:        if (result != TCL_OK) {
                    714:            return result;
                    715:        }
                    716:     }
                    717:     if (*p == 0) {
                    718:        Tcl_AppendResult(interp, argv[1], (char *) NULL);
                    719:     } else {
                    720:        char *end;
                    721: 
                    722:        end = element+size;
                    723:        if (element != argv[1]) {
                    724:            while ((*end != 0) && !isspace(*end)) {
                    725:                end++;
                    726:            }
                    727:        }
                    728:        savedChar = *end;
                    729:        *end = 0;
                    730:        Tcl_AppendResult(interp, argv[1], (char *) NULL);
                    731:        *end = savedChar;
                    732:     }
                    733: 
                    734:     /*
                    735:      * Add the new list elements.
                    736:      */
                    737: 
                    738:     for (i = 3; i < argc; i++) {
                    739:        Tcl_AppendElement(interp, argv[i], 0);
                    740:     }
                    741: 
                    742:     /*
                    743:      * Append the remainder of the original list.
                    744:      */
                    745: 
                    746:     if (*p != 0) {
                    747:        Tcl_AppendResult(interp, " ", p, (char *) NULL);
                    748:     }
                    749:     return TCL_OK;
                    750: }
                    751: 
                    752: /*
                    753:  *----------------------------------------------------------------------
                    754:  *
                    755:  * Tcl_ListCmd --
                    756:  *
                    757:  *     This procedure is invoked to process the "list" Tcl command.
                    758:  *     See the user documentation for details on what it does.
                    759:  *
                    760:  * Results:
                    761:  *     A standard Tcl result.
                    762:  *
                    763:  * Side effects:
                    764:  *     See the user documentation.
                    765:  *
                    766:  *----------------------------------------------------------------------
                    767:  */
                    768: 
                    769:        /* ARGSUSED */
                    770: int
                    771: Tcl_ListCmd(dummy, interp, argc, argv)
                    772:     ClientData dummy;                  /* Not used. */
                    773:     Tcl_Interp *interp;                        /* Current interpreter. */
                    774:     int argc;                          /* Number of arguments. */
                    775:     char **argv;                       /* Argument strings. */
                    776: {
                    777:     if (argc < 2) {
                    778:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    779:                " arg ?arg ...?\"", (char *) NULL);
                    780:        return TCL_ERROR;
                    781:     }
                    782:     interp->result = Tcl_Merge(argc-1, argv+1);
                    783:     interp->freeProc = (Tcl_FreeProc *) free;
                    784:     return TCL_OK;
                    785: }
                    786: 
                    787: /*
                    788:  *----------------------------------------------------------------------
                    789:  *
                    790:  * Tcl_LlengthCmd --
                    791:  *
                    792:  *     This procedure is invoked to process the "llength" Tcl command.
                    793:  *     See the user documentation for details on what it does.
                    794:  *
                    795:  * Results:
                    796:  *     A standard Tcl result.
                    797:  *
                    798:  * Side effects:
                    799:  *     See the user documentation.
                    800:  *
                    801:  *----------------------------------------------------------------------
                    802:  */
                    803: 
                    804:        /* ARGSUSED */
                    805: int
                    806: Tcl_LlengthCmd(dummy, interp, argc, argv)
                    807:     ClientData dummy;                  /* Not used. */
                    808:     Tcl_Interp *interp;                        /* Current interpreter. */
                    809:     int argc;                          /* Number of arguments. */
                    810:     char **argv;                       /* Argument strings. */
                    811: {
                    812:     int count, result;
                    813:     char *element, *p;
                    814: 
                    815:     if (argc != 2) {
                    816:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    817:                " list\"", (char *) NULL);
                    818:        return TCL_ERROR;
                    819:     }
                    820:     for (count = 0, p = argv[1]; *p != 0 ; count++) {
                    821:        result = TclFindElement(interp, p, &element, &p, (int *) NULL,
                    822:                (int *) NULL);
                    823:        if (result != TCL_OK) {
                    824:            return result;
                    825:        }
                    826:        if (*element == 0) {
                    827:            break;
                    828:        }
                    829:     }
                    830:     sprintf(interp->result, "%d", count);
                    831:     return TCL_OK;
                    832: }
                    833: 
                    834: /*
                    835:  *----------------------------------------------------------------------
                    836:  *
                    837:  * Tcl_LrangeCmd --
                    838:  *
                    839:  *     This procedure is invoked to process the "lrange" Tcl command.
                    840:  *     See the user documentation for details on what it does.
                    841:  *
                    842:  * Results:
                    843:  *     A standard Tcl result.
                    844:  *
                    845:  * Side effects:
                    846:  *     See the user documentation.
                    847:  *
                    848:  *----------------------------------------------------------------------
                    849:  */
                    850: 
                    851:        /* ARGSUSED */
                    852: int
                    853: Tcl_LrangeCmd(notUsed, interp, argc, argv)
                    854:     ClientData notUsed;                        /* Not used. */
                    855:     Tcl_Interp *interp;                        /* Current interpreter. */
                    856:     int argc;                          /* Number of arguments. */
                    857:     char **argv;                       /* Argument strings. */
                    858: {
                    859:     int first, last, result;
                    860:     char *begin, *end, c, *dummy;
                    861:     int count;
                    862: 
                    863:     if (argc != 4) {
                    864:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    865:                " list first last\"", (char *) NULL);
                    866:        return TCL_ERROR;
                    867:     }
                    868:     if (Tcl_GetInt(interp, argv[2], &first) != TCL_OK) {
                    869:        return TCL_ERROR;
                    870:     }
                    871:     if (first < 0) {
                    872:        first = 0;
                    873:     }
                    874:     if ((*argv[3] == 'e') && (strncmp(argv[3], "end", strlen(argv[3])) == 0)) {
                    875:        last = 1000000;
                    876:     } else {
                    877:        if (Tcl_GetInt(interp, argv[3], &last) != TCL_OK) {
                    878:            Tcl_ResetResult(interp);
                    879:            Tcl_AppendResult(interp,
                    880:                    "expected integer or \"end\" but got \"",
                    881:                    argv[3], "\"", (char *) NULL);
                    882:            return TCL_ERROR;
                    883:        }
                    884:     }
                    885:     if (first > last) {
                    886:        return TCL_OK;
                    887:     }
                    888: 
                    889:     /*
                    890:      * Extract a range of fields.
                    891:      */
                    892: 
                    893:     for (count = 0, begin = argv[1]; count < first; count++) {
                    894:        result = TclFindElement(interp, begin, &dummy, &begin, (int *) NULL,
                    895:                (int *) NULL);
                    896:        if (result != TCL_OK) {
                    897:            return result;
                    898:        }
                    899:        if (*begin == 0) {
                    900:            break;
                    901:        }
                    902:     }
                    903:     for (count = first, end = begin; (count <= last) && (*end != 0);
                    904:            count++) {
                    905:        result = TclFindElement(interp, end, &dummy, &end, (int *) NULL,
                    906:                (int *) NULL);
                    907:        if (result != TCL_OK) {
                    908:            return result;
                    909:        }
                    910:     }
                    911: 
                    912:     /*
                    913:      * Chop off trailing spaces.
                    914:      */
                    915: 
                    916:     while (isspace(end[-1])) {
                    917:        end--;
                    918:     }
                    919:     c = *end;
                    920:     *end = 0;
                    921:     Tcl_SetResult(interp, begin, TCL_VOLATILE);
                    922:     *end = c;
                    923:     return TCL_OK;
                    924: }
                    925: 
                    926: /*
                    927:  *----------------------------------------------------------------------
                    928:  *
                    929:  * Tcl_LreplaceCmd --
                    930:  *
                    931:  *     This procedure is invoked to process the "lreplace" Tcl command.
                    932:  *     See the user documentation for details on what it does.
                    933:  *
                    934:  * Results:
                    935:  *     A standard Tcl result.
                    936:  *
                    937:  * Side effects:
                    938:  *     See the user documentation.
                    939:  *
                    940:  *----------------------------------------------------------------------
                    941:  */
                    942: 
                    943:        /* ARGSUSED */
                    944: int
                    945: Tcl_LreplaceCmd(notUsed, interp, argc, argv)
                    946:     ClientData notUsed;                        /* Not used. */
                    947:     Tcl_Interp *interp;                        /* Current interpreter. */
                    948:     int argc;                          /* Number of arguments. */
                    949:     char **argv;                       /* Argument strings. */
                    950: {
                    951:     char *p1, *p2, *element, savedChar, *dummy;
                    952:     int i, first, last, count, result, size;
                    953: 
                    954:     if (argc < 4) {
                    955:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    956:                " list first last ?element element ...?\"", (char *) NULL);
                    957:        return TCL_ERROR;
                    958:     }
                    959:     if (Tcl_GetInt(interp, argv[2], &first) != TCL_OK) {
                    960:        return TCL_ERROR;
                    961:     }
                    962:     if (TclGetListIndex(interp, argv[3], &last) != TCL_OK) {
                    963:        return TCL_ERROR;
                    964:     }
                    965:     if (first < 0) {
                    966:        first = 0;
                    967:     }
                    968:     if (last < 0) {
                    969:        last = 0;
                    970:     }
                    971:     if (first > last) {
                    972:        Tcl_AppendResult(interp, "first index must not be greater than second",
                    973:                (char *) NULL);
                    974:        return TCL_ERROR;
                    975:     }
                    976: 
                    977:     /*
                    978:      * Skip over the elements of the list before "first".
                    979:      */
                    980: 
                    981:     size = 0;
                    982:     element = argv[1];
                    983:     for (count = 0, p1 = argv[1]; (count < first) && (*p1 != 0); count++) {
                    984:        result = TclFindElement(interp, p1, &element, &p1, &size,
                    985:                                (int *) NULL);
                    986:        if (result != TCL_OK) {
                    987:            return result;
                    988:        }
                    989:     }
                    990:     if (*p1 == 0) {
                    991:        Tcl_AppendResult(interp, "list doesn't contain element ",
                    992:                argv[2], (char *) NULL);
                    993:        return TCL_ERROR;
                    994:     }
                    995: 
                    996:     /*
                    997:      * Skip over the elements of the list up through "last".
                    998:      */
                    999: 
                   1000:     for (p2 = p1 ; (count <= last) && (*p2 != 0); count++) {
                   1001:        result = TclFindElement(interp, p2, &dummy, &p2, (int *) NULL,
                   1002:                (int *) NULL);
                   1003:        if (result != TCL_OK) {
                   1004:            return result;
                   1005:        }
                   1006:     }
                   1007: 
                   1008:     /*
                   1009:      * Add the elements before "first" to the result.  Be sure to
                   1010:      * include quote or brace characters that might terminate the
                   1011:      * last of these elements.
                   1012:      */
                   1013: 
                   1014:     p1 = element+size;
                   1015:     if (element != argv[1]) {
                   1016:        while ((*p1 != 0) && !isspace(*p1)) {
                   1017:            p1++;
                   1018:        }
                   1019:     }
                   1020:     savedChar = *p1;
                   1021:     *p1 = 0;
                   1022:     Tcl_AppendResult(interp, argv[1], (char *) NULL);
                   1023:     *p1 = savedChar;
                   1024: 
                   1025:     /*
                   1026:      * Add the new list elements.
                   1027:      */
                   1028: 
                   1029:     for (i = 4; i < argc; i++) {
                   1030:        Tcl_AppendElement(interp, argv[i], 0);
                   1031:     }
                   1032: 
                   1033:     /*
                   1034:      * Append the remainder of the original list.
                   1035:      */
                   1036: 
                   1037:     if (*p2 != 0) {
                   1038:        if (*interp->result == 0) {
                   1039:            Tcl_SetResult(interp, p2, TCL_VOLATILE);
                   1040:        } else {
                   1041:            Tcl_AppendResult(interp, " ", p2, (char *) NULL);
                   1042:        }
                   1043:     }
                   1044:     return TCL_OK;
                   1045: }
                   1046: 
                   1047: /*
                   1048:  *----------------------------------------------------------------------
                   1049:  *
                   1050:  * Tcl_LsearchCmd --
                   1051:  *
                   1052:  *     This procedure is invoked to process the "lsearch" Tcl command.
                   1053:  *     See the user documentation for details on what it does.
                   1054:  *
                   1055:  * Results:
                   1056:  *     A standard Tcl result.
                   1057:  *
                   1058:  * Side effects:
                   1059:  *     See the user documentation.
                   1060:  *
                   1061:  *----------------------------------------------------------------------
                   1062:  */
                   1063: 
                   1064:        /* ARGSUSED */
                   1065: int
                   1066: Tcl_LsearchCmd(notUsed, interp, argc, argv)
                   1067:     ClientData notUsed;                        /* Not used. */
                   1068:     Tcl_Interp *interp;                        /* Current interpreter. */
                   1069:     int argc;                          /* Number of arguments. */
                   1070:     char **argv;                       /* Argument strings. */
                   1071: {
                   1072:     int listArgc;
                   1073:     char **listArgv;
                   1074:     int i, match;
                   1075: 
                   1076:     if (argc != 3) {
                   1077:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                   1078:                " list pattern\"", (char *) NULL);
                   1079:        return TCL_ERROR;
                   1080:     }
                   1081:     if (Tcl_SplitList(interp, argv[1], &listArgc, &listArgv) != TCL_OK) {
                   1082:        return TCL_ERROR;
                   1083:     }
                   1084:     match = -1;
                   1085:     for (i = 0; i < listArgc; i++) {
                   1086:        if (Tcl_StringMatch(listArgv[i], argv[2])) {
                   1087:            match = i;
                   1088:            break;
                   1089:        }
                   1090:     }
                   1091:     sprintf(interp->result, "%d", match);
                   1092:     ckfree((char *) listArgv);
                   1093:     return TCL_OK;
                   1094: }
                   1095: 
                   1096: /*
                   1097:  *----------------------------------------------------------------------
                   1098:  *
                   1099:  * Tcl_LsortCmd --
                   1100:  *
                   1101:  *     This procedure is invoked to process the "lsort" Tcl command.
                   1102:  *     See the user documentation for details on what it does.
                   1103:  *
                   1104:  * Results:
                   1105:  *     A standard Tcl result.
                   1106:  *
                   1107:  * Side effects:
                   1108:  *     See the user documentation.
                   1109:  *
                   1110:  *----------------------------------------------------------------------
                   1111:  */
                   1112: 
                   1113:        /* ARGSUSED */
                   1114: int
                   1115: Tcl_LsortCmd(notUsed, interp, argc, argv)
                   1116:     ClientData notUsed;                        /* Not used. */
                   1117:     Tcl_Interp *interp;                        /* Current interpreter. */
                   1118:     int argc;                          /* Number of arguments. */
                   1119:     char **argv;                       /* Argument strings. */
                   1120: {
                   1121:     int listArgc;
                   1122:     char **listArgv;
                   1123: 
                   1124:     if (argc != 2) {
                   1125:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                   1126:                " list\"", (char *) NULL);
                   1127:        return TCL_ERROR;
                   1128:     }
                   1129:     if (Tcl_SplitList(interp, argv[1], &listArgc, &listArgv) != TCL_OK) {
                   1130:        return TCL_ERROR;
                   1131:     }
                   1132:     qsort((VOID *) listArgv, listArgc, sizeof (char *), SortCompareProc);
                   1133:     interp->result = Tcl_Merge(listArgc, listArgv);
                   1134:     interp->freeProc = (Tcl_FreeProc *) free;
                   1135:     ckfree((char *) listArgv);
                   1136:     return TCL_OK;
                   1137: }
                   1138: 
                   1139: /*
                   1140:  * The procedure below is called back by qsort to determine
                   1141:  * the proper ordering between two elements.
                   1142:  */
                   1143: 
                   1144: static int
                   1145: SortCompareProc(first, second)
                   1146:     CONST VOID *first, *second;                /* Elements to be compared. */
                   1147: {
                   1148:     return strcmp(*((char **) first), *((char **) second));
                   1149: }

unix.superglobalmegacorp.com

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