]> cvs.zerfleddert.de Git - micropolis/blob - src/tcl/tclbasic.c
4cbcfe99061b7d820b174e98f2e501ef4ccbfed9
[micropolis] / src / tcl / tclbasic.c
1 /*
2 * tclBasic.c --
3 *
4 * Contains the basic facilities for TCL command interpretation,
5 * including interpreter creation and deletion, command creation
6 * and deletion, and command parsing and execution.
7 *
8 * Copyright 1987-1992 Regents of the University of California
9 * Permission to use, copy, modify, and distribute this
10 * software and its documentation for any purpose and without
11 * fee is hereby granted, provided that the above copyright
12 * notice appear in all copies. The University of California
13 * makes no representations about the suitability of this
14 * software for any purpose. It is provided "as is" without
15 * express or implied warranty.
16 */
17
18 #ifndef lint
19 static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclBasic.c,v 1.131 92/06/21 14:09:41 ouster Exp $ SPRITE (Berkeley)";
20 #endif
21
22 #include "tclint.h"
23
24 /*
25 * The following structure defines all of the commands in the Tcl core,
26 * and the C procedures that execute them.
27 */
28
29 typedef struct {
30 char *name; /* Name of command. */
31 Tcl_CmdProc *proc; /* Procedure that executes command. */
32 } CmdInfo;
33
34 /*
35 * Built-in commands, and the procedures associated with them:
36 */
37
38 static CmdInfo builtInCmds[] = {
39 /*
40 * Commands in the generic core:
41 */
42
43 {"append", Tcl_AppendCmd},
44 {"array", Tcl_ArrayCmd},
45 {"break", Tcl_BreakCmd},
46 {"case", Tcl_CaseCmd},
47 {"catch", Tcl_CatchCmd},
48 {"concat", Tcl_ConcatCmd},
49 {"continue", Tcl_ContinueCmd},
50 {"error", Tcl_ErrorCmd},
51 {"eval", Tcl_EvalCmd},
52 {"expr", Tcl_ExprCmd},
53 {"for", Tcl_ForCmd},
54 {"foreach", Tcl_ForeachCmd},
55 {"format", Tcl_FormatCmd},
56 {"global", Tcl_GlobalCmd},
57 {"if", Tcl_IfCmd},
58 {"incr", Tcl_IncrCmd},
59 {"info", Tcl_InfoCmd},
60 {"join", Tcl_JoinCmd},
61 {"lappend", Tcl_LappendCmd},
62 {"lindex", Tcl_LindexCmd},
63 {"linsert", Tcl_LinsertCmd},
64 {"list", Tcl_ListCmd},
65 {"llength", Tcl_LlengthCmd},
66 {"lrange", Tcl_LrangeCmd},
67 {"lreplace", Tcl_LreplaceCmd},
68 {"lsearch", Tcl_LsearchCmd},
69 {"lsort", Tcl_LsortCmd},
70 {"proc", Tcl_ProcCmd},
71 {"regexp", Tcl_RegexpCmd},
72 {"regsub", Tcl_RegsubCmd},
73 {"rename", Tcl_RenameCmd},
74 {"return", Tcl_ReturnCmd},
75 {"scan", Tcl_ScanCmd},
76 {"set", Tcl_SetCmd},
77 {"split", Tcl_SplitCmd},
78 {"string", Tcl_StringCmd},
79 {"trace", Tcl_TraceCmd},
80 {"unset", Tcl_UnsetCmd},
81 {"uplevel", Tcl_UplevelCmd},
82 {"upvar", Tcl_UpvarCmd},
83 {"while", Tcl_WhileCmd},
84
85 /*
86 * Commands in the UNIX core:
87 */
88
89 #ifndef TCL_GENERIC_ONLY
90 {"cd", Tcl_CdCmd},
91 {"close", Tcl_CloseCmd},
92 {"eof", Tcl_EofCmd},
93 {"exec", Tcl_ExecCmd},
94 {"exit", Tcl_ExitCmd},
95 {"file", Tcl_FileCmd},
96 {"flush", Tcl_FlushCmd},
97 {"gets", Tcl_GetsCmd},
98 {"glob", Tcl_GlobCmd},
99 {"open", Tcl_OpenCmd},
100 {"puts", Tcl_PutsCmd},
101 {"pwd", Tcl_PwdCmd},
102 {"read", Tcl_ReadCmd},
103 {"seek", Tcl_SeekCmd},
104 {"source", Tcl_SourceCmd},
105 {"tell", Tcl_TellCmd},
106 {"time", Tcl_TimeCmd},
107 #endif /* TCL_GENERIC_ONLY */
108 {NULL, (Tcl_CmdProc *) NULL}
109 };
110 \f
111 /*
112 *----------------------------------------------------------------------
113 *
114 * Tcl_CreateInterp --
115 *
116 * Create a new TCL command interpreter.
117 *
118 * Results:
119 * The return value is a token for the interpreter, which may be
120 * used in calls to procedures like Tcl_CreateCmd, Tcl_Eval, or
121 * Tcl_DeleteInterp.
122 *
123 * Side effects:
124 * The command interpreter is initialized with an empty variable
125 * table and the built-in commands.
126 *
127 *----------------------------------------------------------------------
128 */
129
130 Tcl_Interp *
131 Tcl_CreateInterp (void)
132 {
133 register Interp *iPtr;
134 register Command *cmdPtr;
135 register CmdInfo *cmdInfoPtr;
136 int i;
137
138 iPtr = (Interp *) ckalloc(sizeof(Interp));
139 iPtr->result = iPtr->resultSpace;
140 iPtr->freeProc = 0;
141 iPtr->errorLine = 0;
142 Tcl_InitHashTable(&iPtr->commandTable, TCL_STRING_KEYS);
143 Tcl_InitHashTable(&iPtr->globalTable, TCL_STRING_KEYS);
144 iPtr->numLevels = 0;
145 iPtr->framePtr = NULL;
146 iPtr->varFramePtr = NULL;
147 iPtr->activeTracePtr = NULL;
148 iPtr->numEvents = 0;
149 iPtr->events = NULL;
150 iPtr->curEvent = 0;
151 iPtr->curEventNum = 0;
152 iPtr->revPtr = NULL;
153 iPtr->historyFirst = NULL;
154 iPtr->revDisables = 1;
155 iPtr->evalFirst = iPtr->evalLast = NULL;
156 iPtr->appendResult = NULL;
157 iPtr->appendAvl = 0;
158 iPtr->appendUsed = 0;
159 iPtr->numFiles = 0;
160 iPtr->filePtrArray = NULL;
161 for (i = 0; i < NUM_REGEXPS; i++) {
162 iPtr->patterns[i] = NULL;
163 iPtr->patLengths[i] = -1;
164 iPtr->regexps[i] = NULL;
165 }
166 iPtr->cmdCount = 0;
167 iPtr->noEval = 0;
168 iPtr->scriptFile = NULL;
169 iPtr->flags = 0;
170 iPtr->tracePtr = NULL;
171 iPtr->resultSpace[0] = 0;
172
173 /*
174 * Create the built-in commands. Do it here, rather than calling
175 * Tcl_CreateCommand, because it's faster (there's no need to
176 * check for a pre-existing command by the same name).
177 */
178
179 for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
180 int new;
181 Tcl_HashEntry *hPtr;
182
183 hPtr = Tcl_CreateHashEntry(&iPtr->commandTable,
184 cmdInfoPtr->name, &new);
185 if (new) {
186 cmdPtr = (Command *) ckalloc(sizeof(Command));
187 cmdPtr->proc = cmdInfoPtr->proc;
188 cmdPtr->clientData = (ClientData) NULL;
189 cmdPtr->deleteProc = NULL;
190 Tcl_SetHashValue(hPtr, cmdPtr);
191 }
192 }
193
194 #ifndef TCL_GENERIC_ONLY
195 TclSetupEnv((Tcl_Interp *) iPtr);
196 #endif
197
198 return (Tcl_Interp *) iPtr;
199 }
200 \f
201 /*
202 *----------------------------------------------------------------------
203 *
204 * Tcl_DeleteInterp --
205 *
206 * Delete an interpreter and free up all of the resources associated
207 * with it.
208 *
209 * Results:
210 * None.
211 *
212 * Side effects:
213 * The interpreter is destroyed. The caller should never again
214 * use the interp token.
215 *
216 *----------------------------------------------------------------------
217 */
218
219 void
220 Tcl_DeleteInterp (
221 Tcl_Interp *interp /* Token for command interpreter (returned
222 * by a previous call to Tcl_CreateInterp). */
223 )
224 {
225 Interp *iPtr = (Interp *) interp;
226 Tcl_HashEntry *hPtr;
227 Tcl_HashSearch search;
228 register Command *cmdPtr;
229 int i;
230
231 /*
232 * If the interpreter is in use, delay the deletion until later.
233 */
234
235 iPtr->flags |= DELETED;
236 if (iPtr->numLevels != 0) {
237 return;
238 }
239
240 /*
241 * Free up any remaining resources associated with the
242 * interpreter.
243 */
244
245 for (hPtr = Tcl_FirstHashEntry(&iPtr->commandTable, &search);
246 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
247 cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
248 if (cmdPtr->deleteProc != NULL) {
249 (*cmdPtr->deleteProc)(cmdPtr->clientData);
250 }
251 ckfree((char *) cmdPtr);
252 }
253 Tcl_DeleteHashTable(&iPtr->commandTable);
254 TclDeleteVars(iPtr, &iPtr->globalTable);
255 if (iPtr->events != NULL) {
256 int i;
257
258 for (i = 0; i < iPtr->numEvents; i++) {
259 ckfree(iPtr->events[i].command);
260 }
261 ckfree((char *) iPtr->events);
262 }
263 while (iPtr->revPtr != NULL) {
264 HistoryRev *nextPtr = iPtr->revPtr->nextPtr;
265
266 ckfree((char *) iPtr->revPtr);
267 iPtr->revPtr = nextPtr;
268 }
269 if (iPtr->appendResult != NULL) {
270 ckfree(iPtr->appendResult);
271 }
272 #ifndef TCL_GENERIC_ONLY
273 if (iPtr->numFiles > 0) {
274 for (i = 0; i < iPtr->numFiles; i++) {
275 OpenFile *filePtr;
276
277 filePtr = iPtr->filePtrArray[i];
278 if (filePtr == NULL) {
279 continue;
280 }
281 if (i >= 3) {
282 fclose(filePtr->f);
283 if (filePtr->f2 != NULL) {
284 fclose(filePtr->f2);
285 }
286 if (filePtr->numPids > 0) {
287 Tcl_DetachPids(filePtr->numPids, filePtr->pidPtr);
288 ckfree((char *) filePtr->pidPtr);
289 }
290 }
291 ckfree((char *) filePtr);
292 }
293 ckfree((char *) iPtr->filePtrArray);
294 }
295 #endif
296 for (i = 0; i < NUM_REGEXPS; i++) {
297 if (iPtr->patterns[i] == NULL) {
298 break;
299 }
300 ckfree(iPtr->patterns[i]);
301 ckfree((char *) iPtr->regexps[i]);
302 }
303 while (iPtr->tracePtr != NULL) {
304 Trace *nextPtr = iPtr->tracePtr->nextPtr;
305
306 ckfree((char *) iPtr->tracePtr);
307 iPtr->tracePtr = nextPtr;
308 }
309 ckfree((char *) iPtr);
310 }
311 \f
312 /*
313 *----------------------------------------------------------------------
314 *
315 * Tcl_CreateCommand --
316 *
317 * Define a new command in a command table.
318 *
319 * Results:
320 * None.
321 *
322 * Side effects:
323 * If a command named cmdName already exists for interp, it is
324 * deleted. In the future, when cmdName is seen as the name of
325 * a command by Tcl_Eval, proc will be called. When the command
326 * is deleted from the table, deleteProc will be called. See the
327 * manual entry for details on the calling sequence.
328 *
329 *----------------------------------------------------------------------
330 */
331
332 void
333 Tcl_CreateCommand(
334 Tcl_Interp *interp, /* Token for command interpreter (returned
335 * by a previous call to Tcl_CreateInterp). */
336 char *cmdName, /* Name of command. */
337 Tcl_CmdProc *proc, /* Command procedure to associate with
338 * cmdName. */
339 ClientData clientData, /* Arbitrary one-word value to pass to proc. */
340 Tcl_CmdDeleteProc *deleteProc
341 /* If not NULL, gives a procedure to call when
342 * this command is deleted. */
343 )
344 {
345 Interp *iPtr = (Interp *) interp;
346 register Command *cmdPtr;
347 Tcl_HashEntry *hPtr;
348 int new;
349
350 hPtr = Tcl_CreateHashEntry(&iPtr->commandTable, cmdName, &new);
351 if (!new) {
352 /*
353 * Command already exists: delete the old one.
354 */
355
356 cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
357 if (cmdPtr->deleteProc != NULL) {
358 (*cmdPtr->deleteProc)(cmdPtr->clientData);
359 }
360 } else {
361 cmdPtr = (Command *) ckalloc(sizeof(Command));
362 Tcl_SetHashValue(hPtr, cmdPtr);
363 }
364 cmdPtr->proc = proc;
365 cmdPtr->clientData = clientData;
366 cmdPtr->deleteProc = deleteProc;
367 }
368 \f
369 /*
370 *----------------------------------------------------------------------
371 *
372 * Tcl_DeleteCommand --
373 *
374 * Remove the given command from the given interpreter.
375 *
376 * Results:
377 * 0 is returned if the command was deleted successfully.
378 * -1 is returned if there didn't exist a command by that
379 * name.
380 *
381 * Side effects:
382 * CmdName will no longer be recognized as a valid command for
383 * interp.
384 *
385 *----------------------------------------------------------------------
386 */
387
388 int
389 Tcl_DeleteCommand (
390 Tcl_Interp *interp, /* Token for command interpreter (returned
391 * by a previous call to Tcl_CreateInterp). */
392 char *cmdName /* Name of command to remove. */
393 )
394 {
395 Interp *iPtr = (Interp *) interp;
396 Tcl_HashEntry *hPtr;
397 Command *cmdPtr;
398
399 hPtr = Tcl_FindHashEntry(&iPtr->commandTable, cmdName);
400 if (hPtr == NULL) {
401 return -1;
402 }
403 cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
404 if (cmdPtr->deleteProc != NULL) {
405 (*cmdPtr->deleteProc)(cmdPtr->clientData);
406 }
407 ckfree((char *) cmdPtr);
408 Tcl_DeleteHashEntry(hPtr);
409 return 0;
410 }
411 \f
412 /*
413 *-----------------------------------------------------------------
414 *
415 * Tcl_Eval --
416 *
417 * Parse and execute a command in the Tcl language.
418 *
419 * Results:
420 * The return value is one of the return codes defined in tcl.hd
421 * (such as TCL_OK), and interp->result contains a string value
422 * to supplement the return code. The value of interp->result
423 * will persist only until the next call to Tcl_Eval: copy it or
424 * lose it! *TermPtr is filled in with the character just after
425 * the last one that was part of the command (usually a NULL
426 * character or a closing bracket).
427 *
428 * Side effects:
429 * Almost certainly; depends on the command.
430 *
431 *-----------------------------------------------------------------
432 */
433
434 int
435 Tcl_Eval (
436 Tcl_Interp *interp, /* Token for command interpreter (returned
437 * by a previous call to Tcl_CreateInterp). */
438 char *cmd, /* Pointer to TCL command to interpret. */
439 int flags, /* OR-ed combination of flags like
440 * TCL_BRACKET_TERM and TCL_RECORD_BOUNDS. */
441 char **termPtr /* If non-NULL, fill in the address it points
442 * to with the address of the char. just after
443 * the last one that was part of cmd. See
444 * the man page for details on this. */
445 )
446 {
447 /*
448 * The storage immediately below is used to generate a copy
449 * of the command, after all argument substitutions. Pv will
450 * contain the argv values passed to the command procedure.
451 */
452
453 # define NUM_CHARS 200
454 char copyStorage[NUM_CHARS];
455 ParseValue pv;
456 char *oldBuffer;
457
458 /*
459 * This procedure generates an (argv, argc) array for the command,
460 * It starts out with stack-allocated space but uses dynamically-
461 * allocated storage to increase it if needed.
462 */
463
464 # define NUM_ARGS 10
465 char *(argStorage[NUM_ARGS]);
466 char **argv = argStorage;
467 int argc;
468 int argSize = NUM_ARGS;
469
470 register char *src; /* Points to current character
471 * in cmd. */
472 char termChar; /* Return when this character is found
473 * (either ']' or '\0'). Zero means
474 * that newlines terminate commands. */
475 int result; /* Return value. */
476 register Interp *iPtr = (Interp *) interp;
477 Tcl_HashEntry *hPtr;
478 Command *cmdPtr;
479 char *dummy; /* Make termPtr point here if it was
480 * originally NULL. */
481 char *cmdStart; /* Points to first non-blank char. in
482 * command (used in calling trace
483 * procedures). */
484 char *ellipsis = ""; /* Used in setting errorInfo variable;
485 * set to "..." to indicate that not
486 * all of offending command is included
487 * in errorInfo. "" means that the
488 * command is all there. */
489 register Trace *tracePtr;
490
491 /*
492 * Initialize the result to an empty string and clear out any
493 * error information. This makes sure that we return an empty
494 * result if there are no commands in the command string.
495 */
496
497 Tcl_FreeResult((Tcl_Interp *) iPtr);
498 iPtr->result = iPtr->resultSpace;
499 iPtr->resultSpace[0] = 0;
500 result = TCL_OK;
501
502 /*
503 * Check depth of nested calls to Tcl_Eval: if this gets too large,
504 * it's probably because of an infinite loop somewhere.
505 */
506
507 iPtr->numLevels++;
508 if (iPtr->numLevels > MAX_NESTING_DEPTH) {
509 iPtr->numLevels--;
510 iPtr->result = "too many nested calls to Tcl_Eval (infinite loop?)";
511 return TCL_ERROR;
512 }
513
514 /*
515 * Initialize the area in which command copies will be assembled.
516 */
517
518 pv.buffer = copyStorage;
519 pv.end = copyStorage + NUM_CHARS - 1;
520 pv.expandProc = TclExpandParseValue;
521 pv.clientData = (ClientData) NULL;
522
523 src = cmd;
524 if (flags & TCL_BRACKET_TERM) {
525 termChar = ']';
526 } else {
527 termChar = 0;
528 }
529 if (termPtr == NULL) {
530 termPtr = &dummy;
531 }
532 *termPtr = src;
533 cmdStart = src;
534
535 /*
536 * There can be many sub-commands (separated by semi-colons or
537 * newlines) in one command string. This outer loop iterates over
538 * individual commands.
539 */
540
541 while (*src != termChar) {
542 iPtr->flags &= ~(ERR_IN_PROGRESS | ERROR_CODE_SET);
543
544 /*
545 * Skim off leading white space and semi-colons, and skip
546 * comments.
547 */
548
549 while (1) {
550 register char c = *src;
551
552 if ((CHAR_TYPE(c) != TCL_SPACE) && (c != ';') && (c != '\n')) {
553 break;
554 }
555 src += 1;
556 }
557 if (*src == '#') {
558 for (src++; *src != 0; src++) {
559 if (*src == '\n') {
560 src++;
561 break;
562 }
563 }
564 continue;
565 }
566 cmdStart = src;
567
568 /*
569 * Parse the words of the command, generating the argc and
570 * argv for the command procedure. May have to call
571 * TclParseWords several times, expanding the argv array
572 * between calls.
573 */
574
575 pv.next = oldBuffer = pv.buffer;
576 argc = 0;
577 while (1) {
578 int newArgs, maxArgs;
579 char **newArgv;
580 int i;
581
582 /*
583 * Note: the "- 2" below guarantees that we won't use the
584 * last two argv slots here. One is for a NULL pointer to
585 * mark the end of the list, and the other is to leave room
586 * for inserting the command name "unknown" as the first
587 * argument (see below).
588 */
589
590 maxArgs = argSize - argc - 2;
591 result = TclParseWords((Tcl_Interp *) iPtr, src, flags,
592 maxArgs, termPtr, &newArgs, &argv[argc], &pv);
593 src = *termPtr;
594 if (result != TCL_OK) {
595 ellipsis = "...";
596 goto done;
597 }
598
599 /*
600 * Careful! Buffer space may have gotten reallocated while
601 * parsing words. If this happened, be sure to update all
602 * of the older argv pointers to refer to the new space.
603 */
604
605 if (oldBuffer != pv.buffer) {
606 int i;
607
608 for (i = 0; i < argc; i++) {
609 argv[i] = pv.buffer + (argv[i] - oldBuffer);
610 }
611 oldBuffer = pv.buffer;
612 }
613 argc += newArgs;
614 if (newArgs < maxArgs) {
615 argv[argc] = (char *) NULL;
616 break;
617 }
618
619 /*
620 * Args didn't all fit in the current array. Make it bigger.
621 */
622
623 argSize *= 2;
624 newArgv = (char **)
625 ckalloc((unsigned) argSize * sizeof(char *));
626 for (i = 0; i < argc; i++) {
627 newArgv[i] = argv[i];
628 }
629 if (argv != argStorage) {
630 ckfree((char *) argv);
631 }
632 argv = newArgv;
633 }
634
635 /*
636 * If this is an empty command (or if we're just parsing
637 * commands without evaluating them), then just skip to the
638 * next command.
639 */
640
641 if ((argc == 0) || iPtr->noEval) {
642 continue;
643 }
644 argv[argc] = NULL;
645
646 /*
647 * Save information for the history module, if needed.
648 */
649
650 if (flags & TCL_RECORD_BOUNDS) {
651 iPtr->evalFirst = cmdStart;
652 iPtr->evalLast = src-1;
653 }
654
655 /*
656 * Find the procedure to execute this command. If there isn't
657 * one, then see if there is a command "unknown". If so,
658 * invoke it instead, passing it the words of the original
659 * command as arguments.
660 */
661
662 hPtr = Tcl_FindHashEntry(&iPtr->commandTable, argv[0]);
663 if (hPtr == NULL) {
664 int i;
665
666 hPtr = Tcl_FindHashEntry(&iPtr->commandTable, "unknown");
667 if (hPtr == NULL) {
668 Tcl_ResetResult(interp);
669 Tcl_AppendResult(interp, "invalid command name: \"",
670 argv[0], "\"", (char *) NULL);
671 result = TCL_ERROR;
672 goto done;
673 }
674 for (i = argc; i >= 0; i--) {
675 argv[i+1] = argv[i];
676 }
677 argv[0] = "unknown";
678 argc++;
679 }
680 cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
681
682 /*
683 * Call trace procedures, if any.
684 */
685
686 for (tracePtr = iPtr->tracePtr; tracePtr != NULL;
687 tracePtr = tracePtr->nextPtr) {
688 char saved;
689
690 if (tracePtr->level < iPtr->numLevels) {
691 continue;
692 }
693 saved = *src;
694 *src = 0;
695 (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,
696 cmdStart, cmdPtr->proc, cmdPtr->clientData, argc, argv);
697 *src = saved;
698 }
699
700 /*
701 * At long last, invoke the command procedure. Reset the
702 * result to its default empty value first (it could have
703 * gotten changed by earlier commands in the same command
704 * string).
705 */
706
707 iPtr->cmdCount++;
708 Tcl_FreeResult(iPtr);
709 iPtr->result = iPtr->resultSpace;
710 iPtr->resultSpace[0] = 0;
711 result = (*cmdPtr->proc)(cmdPtr->clientData, interp, argc, argv);
712 if (result != TCL_OK) {
713 break;
714 }
715 }
716
717 /*
718 * Free up any extra resources that were allocated.
719 */
720
721 done:
722 if (pv.buffer != copyStorage) {
723 ckfree((char *) pv.buffer);
724 }
725 if (argv != argStorage) {
726 ckfree((char *) argv);
727 }
728 iPtr->numLevels--;
729 if (iPtr->numLevels == 0) {
730 if (result == TCL_RETURN) {
731 result = TCL_OK;
732 }
733 if ((result != TCL_OK) && (result != TCL_ERROR)) {
734 Tcl_ResetResult(interp);
735 if (result == TCL_BREAK) {
736 iPtr->result = "invoked \"break\" outside of a loop";
737 } else if (result == TCL_CONTINUE) {
738 iPtr->result = "invoked \"continue\" outside of a loop";
739 } else {
740 iPtr->result = iPtr->resultSpace;
741 sprintf(iPtr->resultSpace, "command returned bad code: %d",
742 result);
743 }
744 result = TCL_ERROR;
745 }
746 if (iPtr->flags & DELETED) {
747 Tcl_DeleteInterp(interp);
748 }
749 }
750
751 /*
752 * If an error occurred, record information about what was being
753 * executed when the error occurred.
754 */
755
756 if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
757 int numChars;
758 register char *p;
759
760 /*
761 * Compute the line number where the error occurred.
762 */
763
764 iPtr->errorLine = 1;
765 for (p = cmd; p != cmdStart; p++) {
766 if (*p == '\n') {
767 iPtr->errorLine++;
768 }
769 }
770 for ( ; isspace(*p) || (*p == ';'); p++) {
771 if (*p == '\n') {
772 iPtr->errorLine++;
773 }
774 }
775
776 /*
777 * Figure out how much of the command to print in the error
778 * message (up to a certain number of characters, or up to
779 * the first new-line).
780 */
781
782 numChars = src - cmdStart;
783 if (numChars > (NUM_CHARS-50)) {
784 numChars = NUM_CHARS-50;
785 ellipsis = " ...";
786 }
787
788 if (!(iPtr->flags & ERR_IN_PROGRESS)) {
789 sprintf(copyStorage, "\n while executing\n\"%.*s%s\"",
790 numChars, cmdStart, ellipsis);
791 } else {
792 sprintf(copyStorage, "\n invoked from within\n\"%.*s%s\"",
793 numChars, cmdStart, ellipsis);
794 }
795 Tcl_AddErrorInfo(interp, copyStorage);
796 iPtr->flags &= ~ERR_ALREADY_LOGGED;
797 } else {
798 iPtr->flags &= ~ERR_ALREADY_LOGGED;
799 }
800 return result;
801 }
802 \f
803 /*
804 *----------------------------------------------------------------------
805 *
806 * Tcl_CreateTrace --
807 *
808 * Arrange for a procedure to be called to trace command execution.
809 *
810 * Results:
811 * The return value is a token for the trace, which may be passed
812 * to Tcl_DeleteTrace to eliminate the trace.
813 *
814 * Side effects:
815 * From now on, proc will be called just before a command procedure
816 * is called to execute a Tcl command. Calls to proc will have the
817 * following form:
818 *
819 * void
820 * proc(clientData, interp, level, command, cmdProc, cmdClientData,
821 * argc, argv)
822 * ClientData clientData;
823 * Tcl_Interp *interp;
824 * int level;
825 * char *command;
826 * int (*cmdProc)();
827 * ClientData cmdClientData;
828 * int argc;
829 * char **argv;
830 * {
831 * }
832 *
833 * The clientData and interp arguments to proc will be the same
834 * as the corresponding arguments to this procedure. Level gives
835 * the nesting level of command interpretation for this interpreter
836 * (0 corresponds to top level). Command gives the ASCII text of
837 * the raw command, cmdProc and cmdClientData give the procedure that
838 * will be called to process the command and the ClientData value it
839 * will receive, and argc and argv give the arguments to the
840 * command, after any argument parsing and substitution. Proc
841 * does not return a value.
842 *
843 *----------------------------------------------------------------------
844 */
845
846 Tcl_Trace
847 Tcl_CreateTrace(
848 Tcl_Interp *interp, /* Interpreter in which to create the trace. */
849 int level, /* Only call proc for commands at nesting level
850 * <= level (1 => top level). */
851 Tcl_CmdTraceProc *proc, /* Procedure to call before executing each
852 * command. */
853 ClientData clientData /* Arbitrary one-word value to pass to proc. */
854 )
855 {
856 register Trace *tracePtr;
857 register Interp *iPtr = (Interp *) interp;
858
859 tracePtr = (Trace *) ckalloc(sizeof(Trace));
860 tracePtr->level = level;
861 tracePtr->proc = proc;
862 tracePtr->clientData = clientData;
863 tracePtr->nextPtr = iPtr->tracePtr;
864 iPtr->tracePtr = tracePtr;
865
866 return (Tcl_Trace) tracePtr;
867 }
868 \f
869 /*
870 *----------------------------------------------------------------------
871 *
872 * Tcl_DeleteTrace --
873 *
874 * Remove a trace.
875 *
876 * Results:
877 * None.
878 *
879 * Side effects:
880 * From now on there will be no more calls to the procedure given
881 * in trace.
882 *
883 *----------------------------------------------------------------------
884 */
885
886 void
887 Tcl_DeleteTrace (
888 Tcl_Interp *interp, /* Interpreter that contains trace. */
889 Tcl_Trace trace /* Token for trace (returned previously by
890 * Tcl_CreateTrace). */
891 )
892 {
893 register Interp *iPtr = (Interp *) interp;
894 register Trace *tracePtr = (Trace *) trace;
895 register Trace *tracePtr2;
896
897 if (iPtr->tracePtr == tracePtr) {
898 iPtr->tracePtr = tracePtr->nextPtr;
899 ckfree((char *) tracePtr);
900 } else {
901 for (tracePtr2 = iPtr->tracePtr; tracePtr2 != NULL;
902 tracePtr2 = tracePtr2->nextPtr) {
903 if (tracePtr2->nextPtr == tracePtr) {
904 tracePtr2->nextPtr = tracePtr->nextPtr;
905 ckfree((char *) tracePtr);
906 return;
907 }
908 }
909 }
910 }
911 \f
912 /*
913 *----------------------------------------------------------------------
914 *
915 * Tcl_AddErrorInfo --
916 *
917 * Add information to a message being accumulated that describes
918 * the current error.
919 *
920 * Results:
921 * None.
922 *
923 * Side effects:
924 * The contents of message are added to the "errorInfo" variable.
925 * If Tcl_Eval has been called since the current value of errorInfo
926 * was set, errorInfo is cleared before adding the new message.
927 *
928 *----------------------------------------------------------------------
929 */
930
931 void
932 Tcl_AddErrorInfo (
933 Tcl_Interp *interp, /* Interpreter to which error information
934 * pertains. */
935 char *message /* Message to record. */
936 )
937 {
938 register Interp *iPtr = (Interp *) interp;
939
940 /*
941 * If an error is already being logged, then the new errorInfo
942 * is the concatenation of the old info and the new message.
943 * If this is the first piece of info for the error, then the
944 * new errorInfo is the concatenation of the message in
945 * interp->result and the new message.
946 */
947
948 if (!(iPtr->flags & ERR_IN_PROGRESS)) {
949 Tcl_SetVar2(interp, "errorInfo", (char *) NULL, interp->result,
950 TCL_GLOBAL_ONLY);
951 iPtr->flags |= ERR_IN_PROGRESS;
952
953 /*
954 * If the errorCode variable wasn't set by the code that generated
955 * the error, set it to "NONE".
956 */
957
958 if (!(iPtr->flags & ERROR_CODE_SET)) {
959 (void) Tcl_SetVar2(interp, "errorCode", (char *) NULL, "NONE",
960 TCL_GLOBAL_ONLY);
961 }
962 }
963 Tcl_SetVar2(interp, "errorInfo", (char *) NULL, message,
964 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
965 }
966 \f
967 /*
968 *----------------------------------------------------------------------
969 *
970 * Tcl_VarEval --
971 *
972 * Given a variable number of string arguments, concatenate them
973 * all together and execute the result as a Tcl command.
974 *
975 * Results:
976 * A standard Tcl return result. An error message or other
977 * result may be left in interp->result.
978 *
979 * Side effects:
980 * Depends on what was done by the command.
981 *
982 *----------------------------------------------------------------------
983 */
984 int
985 Tcl_VarEval(Tcl_Interp *interp, ...)
986 {
987 va_list argList;
988 #define FIXED_SIZE 200
989 char fixedSpace[FIXED_SIZE+1];
990 int spaceAvl, spaceUsed, length;
991 char *string, *cmd;
992 int result;
993
994 /*
995 * Copy the strings one after the other into a single larger
996 * string. Use stack-allocated space for small commands, but if
997 * the commands gets too large than call ckalloc to create the
998 * space.
999 */
1000
1001 va_start(argList, interp);
1002 spaceAvl = FIXED_SIZE;
1003 spaceUsed = 0;
1004 cmd = fixedSpace;
1005 while (1) {
1006 string = va_arg(argList, char *);
1007 if (string == NULL) {
1008 break;
1009 }
1010 length = strlen(string);
1011 if ((spaceUsed + length) > spaceAvl) {
1012 char *new;
1013
1014 spaceAvl = spaceUsed + length;
1015 spaceAvl += spaceAvl/2;
1016 new = ckalloc((unsigned) spaceAvl);
1017 memcpy((VOID *) new, (VOID *) cmd, spaceUsed);
1018 if (cmd != fixedSpace) {
1019 ckfree(cmd);
1020 }
1021 cmd = new;
1022 }
1023 strcpy(cmd + spaceUsed, string);
1024 spaceUsed += length;
1025 }
1026 va_end(argList);
1027 cmd[spaceUsed] = '\0';
1028
1029 result = Tcl_Eval(interp, cmd, 0, (char **) NULL);
1030 if (cmd != fixedSpace) {
1031 ckfree(cmd);
1032 }
1033 return result;
1034 }
1035 \f
1036 /*
1037 *----------------------------------------------------------------------
1038 *
1039 * Tcl_GlobalEval --
1040 *
1041 * Evaluate a command at global level in an interpreter.
1042 *
1043 * Results:
1044 * A standard Tcl result is returned, and interp->result is
1045 * modified accordingly.
1046 *
1047 * Side effects:
1048 * The command string is executed in interp, and the execution
1049 * is carried out in the variable context of global level (no
1050 * procedures active), just as if an "uplevel #0" command were
1051 * being executed.
1052 *
1053 *----------------------------------------------------------------------
1054 */
1055
1056 int
1057 Tcl_GlobalEval (
1058 Tcl_Interp *interp, /* Interpreter in which to evaluate command. */
1059 char *command /* Command to evaluate. */
1060 )
1061 {
1062 register Interp *iPtr = (Interp *) interp;
1063 int result;
1064 CallFrame *savedVarFramePtr;
1065
1066 savedVarFramePtr = iPtr->varFramePtr;
1067 iPtr->varFramePtr = NULL;
1068 result = Tcl_Eval(interp, command, 0, (char **) NULL);
1069 iPtr->varFramePtr = savedVarFramePtr;
1070 return result;
1071 }
Impressum, Datenschutz