|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.