/[dtapublic]/projs/dtats/trunk/shared_source/c_tcl_base_7_5_w_mods/tclbasic.c
ViewVC logotype

Annotation of /projs/dtats/trunk/shared_source/c_tcl_base_7_5_w_mods/tclbasic.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 64 - (hide annotations) (download)
Sun Oct 30 04:21:11 2016 UTC (7 years, 7 months ago) by dashley
Original Path: projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclbasic.c
File MIME type: text/plain
File size: 134657 byte(s)
Adjust line endings to Windows style.
Set properties to expand the "Header" keyword.
Change header and footer.
1 dashley 64 /* $Header$ */
2 dashley 25
3     /*
4     * tclBasic.c --
5     *
6     * Contains the basic facilities for TCL command interpretation,
7     * including interpreter creation and deletion, command creation
8     * and deletion, and command parsing and execution.
9     *
10     * Copyright (c) 1987-1994 The Regents of the University of California.
11     * Copyright (c) 1994-1997 Sun Microsystems, Inc.
12     * Copyright (c) 1998-1999 by Scriptics Corporation.
13     *
14     * See the file "license.terms" for information on usage and redistribution
15     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16     *
17     * RCS: @(#) $Id: tclbasic.c,v 1.1.1.1 2001/06/13 04:33:43 dtashley Exp $
18     */
19    
20     #include "tclInt.h"
21     #include "tclCompile.h"
22     #ifndef TCL_GENERIC_ONLY
23     # include "tclPort.h"
24     #endif
25    
26     /*
27     * Static procedures in this file:
28     */
29    
30     static void DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
31     static void ProcessUnexpectedResult _ANSI_ARGS_((
32     Tcl_Interp *interp, int returnCode));
33     static void RecordTracebackInfo _ANSI_ARGS_((
34     Tcl_Interp *interp, Tcl_Obj *objPtr,
35     int numSrcBytes));
36    
37     extern TclStubs tclStubs;
38    
39     /*
40     * The following structure defines the commands in the Tcl core.
41     */
42    
43     typedef struct {
44     char *name; /* Name of object-based command. */
45     Tcl_CmdProc *proc; /* String-based procedure for command. */
46     Tcl_ObjCmdProc *objProc; /* Object-based procedure for command. */
47     CompileProc *compileProc; /* Procedure called to compile command. */
48     int isSafe; /* If non-zero, command will be present
49     * in safe interpreter. Otherwise it will
50     * be hidden. */
51     } CmdInfo;
52    
53     /*
54     * The built-in commands, and the procedures that implement them:
55     */
56    
57     static CmdInfo builtInCmds[] = {
58     /*
59     * Commands in the generic core. Note that at least one of the proc or
60     * objProc members should be non-NULL. This avoids infinitely recursive
61     * calls between TclInvokeObjectCommand and TclInvokeStringCommand if a
62     * command name is computed at runtime and results in the name of a
63     * compiled command.
64     */
65    
66     {"append", (Tcl_CmdProc *) NULL, Tcl_AppendObjCmd,
67     (CompileProc *) NULL, 1},
68     {"array", (Tcl_CmdProc *) NULL, Tcl_ArrayObjCmd,
69     (CompileProc *) NULL, 1},
70     {"binary", (Tcl_CmdProc *) NULL, Tcl_BinaryObjCmd,
71     (CompileProc *) NULL, 1},
72     {"break", (Tcl_CmdProc *) NULL, Tcl_BreakObjCmd,
73     TclCompileBreakCmd, 1},
74     {"case", (Tcl_CmdProc *) NULL, Tcl_CaseObjCmd,
75     (CompileProc *) NULL, 1},
76     {"catch", (Tcl_CmdProc *) NULL, Tcl_CatchObjCmd,
77     TclCompileCatchCmd, 1},
78     {"clock", (Tcl_CmdProc *) NULL, Tcl_ClockObjCmd,
79     (CompileProc *) NULL, 1},
80     {"concat", (Tcl_CmdProc *) NULL, Tcl_ConcatObjCmd,
81     (CompileProc *) NULL, 1},
82     {"continue", (Tcl_CmdProc *) NULL, Tcl_ContinueObjCmd,
83     TclCompileContinueCmd, 1},
84     {"encoding", (Tcl_CmdProc *) NULL, Tcl_EncodingObjCmd,
85     (CompileProc *) NULL, 0},
86     {"error", (Tcl_CmdProc *) NULL, Tcl_ErrorObjCmd,
87     (CompileProc *) NULL, 1},
88     {"eval", (Tcl_CmdProc *) NULL, Tcl_EvalObjCmd,
89     (CompileProc *) NULL, 1},
90     {"exit", (Tcl_CmdProc *) NULL, Tcl_ExitObjCmd,
91     (CompileProc *) NULL, 0},
92     {"expr", (Tcl_CmdProc *) NULL, Tcl_ExprObjCmd,
93     TclCompileExprCmd, 1},
94     {"fcopy", (Tcl_CmdProc *) NULL, Tcl_FcopyObjCmd,
95     (CompileProc *) NULL, 1},
96     {"fileevent", (Tcl_CmdProc *) NULL, Tcl_FileEventObjCmd,
97     (CompileProc *) NULL, 1},
98     {"for", (Tcl_CmdProc *) NULL, Tcl_ForObjCmd,
99     TclCompileForCmd, 1},
100     {"foreach", (Tcl_CmdProc *) NULL, Tcl_ForeachObjCmd,
101     TclCompileForeachCmd, 1},
102     {"format", (Tcl_CmdProc *) NULL, Tcl_FormatObjCmd,
103     (CompileProc *) NULL, 1},
104     {"global", (Tcl_CmdProc *) NULL, Tcl_GlobalObjCmd,
105     (CompileProc *) NULL, 1},
106     {"if", (Tcl_CmdProc *) NULL, Tcl_IfObjCmd,
107     TclCompileIfCmd, 1},
108     {"incr", (Tcl_CmdProc *) NULL, Tcl_IncrObjCmd,
109     TclCompileIncrCmd, 1},
110     {"info", (Tcl_CmdProc *) NULL, Tcl_InfoObjCmd,
111     (CompileProc *) NULL, 1},
112     {"join", (Tcl_CmdProc *) NULL, Tcl_JoinObjCmd,
113     (CompileProc *) NULL, 1},
114     {"lappend", (Tcl_CmdProc *) NULL, Tcl_LappendObjCmd,
115     (CompileProc *) NULL, 1},
116     {"lindex", (Tcl_CmdProc *) NULL, Tcl_LindexObjCmd,
117     (CompileProc *) NULL, 1},
118     {"linsert", (Tcl_CmdProc *) NULL, Tcl_LinsertObjCmd,
119     (CompileProc *) NULL, 1},
120     {"list", (Tcl_CmdProc *) NULL, Tcl_ListObjCmd,
121     (CompileProc *) NULL, 1},
122     {"llength", (Tcl_CmdProc *) NULL, Tcl_LlengthObjCmd,
123     (CompileProc *) NULL, 1},
124     {"load", (Tcl_CmdProc *) NULL, Tcl_LoadObjCmd,
125     (CompileProc *) NULL, 0},
126     {"lrange", (Tcl_CmdProc *) NULL, Tcl_LrangeObjCmd,
127     (CompileProc *) NULL, 1},
128     {"lreplace", (Tcl_CmdProc *) NULL, Tcl_LreplaceObjCmd,
129     (CompileProc *) NULL, 1},
130     {"lsearch", (Tcl_CmdProc *) NULL, Tcl_LsearchObjCmd,
131     (CompileProc *) NULL, 1},
132     {"lsort", (Tcl_CmdProc *) NULL, Tcl_LsortObjCmd,
133     (CompileProc *) NULL, 1},
134     {"namespace", (Tcl_CmdProc *) NULL, Tcl_NamespaceObjCmd,
135     (CompileProc *) NULL, 1},
136     {"package", (Tcl_CmdProc *) NULL, Tcl_PackageObjCmd,
137     (CompileProc *) NULL, 1},
138     {"proc", (Tcl_CmdProc *) NULL, Tcl_ProcObjCmd,
139     (CompileProc *) NULL, 1},
140     {"regexp", (Tcl_CmdProc *) NULL, Tcl_RegexpObjCmd,
141     (CompileProc *) NULL, 1},
142     {"regsub", (Tcl_CmdProc *) NULL, Tcl_RegsubObjCmd,
143     (CompileProc *) NULL, 1},
144     {"rename", (Tcl_CmdProc *) NULL, Tcl_RenameObjCmd,
145     (CompileProc *) NULL, 1},
146     {"return", (Tcl_CmdProc *) NULL, Tcl_ReturnObjCmd,
147     (CompileProc *) NULL, 1},
148     {"scan", (Tcl_CmdProc *) NULL, Tcl_ScanObjCmd,
149     (CompileProc *) NULL, 1},
150     {"set", (Tcl_CmdProc *) NULL, Tcl_SetObjCmd,
151     TclCompileSetCmd, 1},
152     {"split", (Tcl_CmdProc *) NULL, Tcl_SplitObjCmd,
153     (CompileProc *) NULL, 1},
154     {"string", (Tcl_CmdProc *) NULL, Tcl_StringObjCmd,
155     (CompileProc *) NULL, 1},
156     {"subst", (Tcl_CmdProc *) NULL, Tcl_SubstObjCmd,
157     (CompileProc *) NULL, 1},
158     {"switch", (Tcl_CmdProc *) NULL, Tcl_SwitchObjCmd,
159     (CompileProc *) NULL, 1},
160     {"trace", (Tcl_CmdProc *) NULL, Tcl_TraceObjCmd,
161     (CompileProc *) NULL, 1},
162     {"unset", (Tcl_CmdProc *) NULL, Tcl_UnsetObjCmd,
163     (CompileProc *) NULL, 1},
164     {"uplevel", (Tcl_CmdProc *) NULL, Tcl_UplevelObjCmd,
165     (CompileProc *) NULL, 1},
166     {"upvar", (Tcl_CmdProc *) NULL, Tcl_UpvarObjCmd,
167     (CompileProc *) NULL, 1},
168     {"variable", (Tcl_CmdProc *) NULL, Tcl_VariableObjCmd,
169     (CompileProc *) NULL, 1},
170     {"while", (Tcl_CmdProc *) NULL, Tcl_WhileObjCmd,
171     TclCompileWhileCmd, 1},
172    
173     /*
174     * Commands in the UNIX core:
175     */
176    
177     #ifndef TCL_GENERIC_ONLY
178     {"after", (Tcl_CmdProc *) NULL, Tcl_AfterObjCmd,
179     (CompileProc *) NULL, 1},
180     {"cd", (Tcl_CmdProc *) NULL, Tcl_CdObjCmd,
181     (CompileProc *) NULL, 0},
182     {"close", (Tcl_CmdProc *) NULL, Tcl_CloseObjCmd,
183     (CompileProc *) NULL, 1},
184     {"eof", (Tcl_CmdProc *) NULL, Tcl_EofObjCmd,
185     (CompileProc *) NULL, 1},
186     {"fblocked", (Tcl_CmdProc *) NULL, Tcl_FblockedObjCmd,
187     (CompileProc *) NULL, 1},
188     {"fconfigure", (Tcl_CmdProc *) NULL, Tcl_FconfigureObjCmd,
189     (CompileProc *) NULL, 0},
190     {"file", (Tcl_CmdProc *) NULL, Tcl_FileObjCmd,
191     (CompileProc *) NULL, 0},
192     {"flush", (Tcl_CmdProc *) NULL, Tcl_FlushObjCmd,
193     (CompileProc *) NULL, 1},
194     {"gets", (Tcl_CmdProc *) NULL, Tcl_GetsObjCmd,
195     (CompileProc *) NULL, 1},
196     {"glob", (Tcl_CmdProc *) NULL, Tcl_GlobObjCmd,
197     (CompileProc *) NULL, 0},
198     {"open", (Tcl_CmdProc *) NULL, Tcl_OpenObjCmd,
199     (CompileProc *) NULL, 0},
200     {"pid", (Tcl_CmdProc *) NULL, Tcl_PidObjCmd,
201     (CompileProc *) NULL, 1},
202     {"puts", (Tcl_CmdProc *) NULL, Tcl_PutsObjCmd,
203     (CompileProc *) NULL, 1},
204     {"pwd", (Tcl_CmdProc *) NULL, Tcl_PwdObjCmd,
205     (CompileProc *) NULL, 0},
206     {"read", (Tcl_CmdProc *) NULL, Tcl_ReadObjCmd,
207     (CompileProc *) NULL, 1},
208     {"seek", (Tcl_CmdProc *) NULL, Tcl_SeekObjCmd,
209     (CompileProc *) NULL, 1},
210     {"socket", (Tcl_CmdProc *) NULL, Tcl_SocketObjCmd,
211     (CompileProc *) NULL, 0},
212     {"tell", (Tcl_CmdProc *) NULL, Tcl_TellObjCmd,
213     (CompileProc *) NULL, 1},
214     {"time", (Tcl_CmdProc *) NULL, Tcl_TimeObjCmd,
215     (CompileProc *) NULL, 1},
216     {"update", (Tcl_CmdProc *) NULL, Tcl_UpdateObjCmd,
217     (CompileProc *) NULL, 1},
218     {"vwait", (Tcl_CmdProc *) NULL, Tcl_VwaitObjCmd,
219     (CompileProc *) NULL, 1},
220    
221     #ifdef MAC_TCL
222     {"beep", (Tcl_CmdProc *) NULL, Tcl_BeepObjCmd,
223     (CompileProc *) NULL, 0},
224     {"echo", Tcl_EchoCmd, (Tcl_ObjCmdProc *) NULL,
225     (CompileProc *) NULL, 0},
226     {"ls", (Tcl_CmdProc *) NULL, Tcl_LsObjCmd,
227     (CompileProc *) NULL, 0},
228     {"resource", (Tcl_CmdProc *) NULL, Tcl_ResourceObjCmd,
229     (CompileProc *) NULL, 1},
230     {"source", (Tcl_CmdProc *) NULL, Tcl_MacSourceObjCmd,
231     (CompileProc *) NULL, 0},
232     #else
233     {"exec", (Tcl_CmdProc *) NULL, Tcl_ExecObjCmd,
234     (CompileProc *) NULL, 0},
235     {"source", (Tcl_CmdProc *) NULL, Tcl_SourceObjCmd,
236     (CompileProc *) NULL, 0},
237     #endif /* MAC_TCL */
238    
239     #endif /* TCL_GENERIC_ONLY */
240     {NULL, (Tcl_CmdProc *) NULL, (Tcl_ObjCmdProc *) NULL,
241     (CompileProc *) NULL, 0}
242     };
243    
244    
245     /*
246     *----------------------------------------------------------------------
247     *
248     * Tcl_CreateInterp --
249     *
250     * Create a new TCL command interpreter.
251     *
252     * Results:
253     * The return value is a token for the interpreter, which may be
254     * used in calls to procedures like Tcl_CreateCmd, Tcl_Eval, or
255     * Tcl_DeleteInterp.
256     *
257     * Side effects:
258     * The command interpreter is initialized with an empty variable
259     * table and the built-in commands.
260     *
261     *----------------------------------------------------------------------
262     */
263    
264     Tcl_Interp *
265     Tcl_CreateInterp()
266     {
267     Interp *iPtr;
268     Tcl_Interp *interp;
269     Command *cmdPtr;
270     BuiltinFunc *builtinFuncPtr;
271     MathFunc *mathFuncPtr;
272     Tcl_HashEntry *hPtr;
273     CmdInfo *cmdInfoPtr;
274     int i;
275     union {
276     char c[sizeof(short)];
277     short s;
278     } order;
279     #ifdef TCL_COMPILE_STATS
280     ByteCodeStats *statsPtr;
281     #endif /* TCL_COMPILE_STATS */
282    
283     TclInitSubsystems(NULL);
284    
285     /*
286     * Panic if someone updated the CallFrame structure without
287     * also updating the Tcl_CallFrame structure (or vice versa).
288     */
289    
290     if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
291     /*NOTREACHED*/
292     panic("Tcl_CallFrame and CallFrame are not the same size");
293     }
294    
295     /*
296     * Initialize support for namespaces and create the global namespace
297     * (whose name is ""; an alias is "::"). This also initializes the
298     * Tcl object type table and other object management code.
299     */
300    
301     iPtr = (Interp *) ckalloc(sizeof(Interp));
302     interp = (Tcl_Interp *) iPtr;
303    
304     iPtr->result = iPtr->resultSpace;
305     iPtr->freeProc = NULL;
306     iPtr->errorLine = 0;
307     iPtr->objResultPtr = Tcl_NewObj();
308     Tcl_IncrRefCount(iPtr->objResultPtr);
309     iPtr->handle = TclHandleCreate(iPtr);
310     iPtr->globalNsPtr = NULL;
311     iPtr->hiddenCmdTablePtr = NULL;
312     iPtr->interpInfo = NULL;
313     Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS);
314    
315     iPtr->numLevels = 0;
316     iPtr->maxNestingDepth = 1000;
317     iPtr->framePtr = NULL;
318     iPtr->varFramePtr = NULL;
319     iPtr->activeTracePtr = NULL;
320     iPtr->returnCode = TCL_OK;
321     iPtr->errorInfo = NULL;
322     iPtr->errorCode = NULL;
323    
324     iPtr->appendResult = NULL;
325     iPtr->appendAvl = 0;
326     iPtr->appendUsed = 0;
327    
328     Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
329     iPtr->packageUnknown = NULL;
330     iPtr->cmdCount = 0;
331     iPtr->termOffset = 0;
332     TclInitLiteralTable(&(iPtr->literalTable));
333     iPtr->compileEpoch = 0;
334     iPtr->compiledProcPtr = NULL;
335     iPtr->resolverPtr = NULL;
336     iPtr->evalFlags = 0;
337     iPtr->scriptFile = NULL;
338     iPtr->flags = 0;
339     iPtr->tracePtr = NULL;
340     iPtr->assocData = (Tcl_HashTable *) NULL;
341     iPtr->execEnvPtr = NULL; /* set after namespaces initialized */
342     iPtr->emptyObjPtr = Tcl_NewObj(); /* another empty object */
343     Tcl_IncrRefCount(iPtr->emptyObjPtr);
344     iPtr->resultSpace[0] = 0;
345    
346     iPtr->globalNsPtr = NULL; /* force creation of global ns below */
347     iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
348     (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
349     if (iPtr->globalNsPtr == NULL) {
350     panic("Tcl_CreateInterp: can't create global namespace");
351     }
352    
353     /*
354     * Initialize support for code compilation and execution. We call
355     * TclCreateExecEnv after initializing namespaces since it tries to
356     * reference a Tcl variable (it links to the Tcl "tcl_traceExec"
357     * variable).
358     */
359    
360     iPtr->execEnvPtr = TclCreateExecEnv(interp);
361    
362     /*
363     * Initialize the compilation and execution statistics kept for this
364     * interpreter.
365     */
366    
367     #ifdef TCL_COMPILE_STATS
368     statsPtr = &(iPtr->stats);
369     statsPtr->numExecutions = 0;
370     statsPtr->numCompilations = 0;
371     statsPtr->numByteCodesFreed = 0;
372     (VOID *) memset(statsPtr->instructionCount, 0,
373     sizeof(statsPtr->instructionCount));
374    
375     statsPtr->totalSrcBytes = 0.0;
376     statsPtr->totalByteCodeBytes = 0.0;
377     statsPtr->currentSrcBytes = 0.0;
378     statsPtr->currentByteCodeBytes = 0.0;
379     (VOID *) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
380     (VOID *) memset(statsPtr->byteCodeCount, 0,
381     sizeof(statsPtr->byteCodeCount));
382     (VOID *) memset(statsPtr->lifetimeCount, 0,
383     sizeof(statsPtr->lifetimeCount));
384    
385     statsPtr->currentInstBytes = 0.0;
386     statsPtr->currentLitBytes = 0.0;
387     statsPtr->currentExceptBytes = 0.0;
388     statsPtr->currentAuxBytes = 0.0;
389     statsPtr->currentCmdMapBytes = 0.0;
390    
391     statsPtr->numLiteralsCreated = 0;
392     statsPtr->totalLitStringBytes = 0.0;
393     statsPtr->currentLitStringBytes = 0.0;
394     (VOID *) memset(statsPtr->literalCount, 0,
395     sizeof(statsPtr->literalCount));
396     #endif /* TCL_COMPILE_STATS */
397    
398     /*
399     * Initialise the stub table pointer.
400     */
401    
402     iPtr->stubTable = &tclStubs;
403    
404    
405     /*
406     * Create the core commands. Do it here, rather than calling
407     * Tcl_CreateCommand, because it's faster (there's no need to check for
408     * a pre-existing command by the same name). If a command has a
409     * Tcl_CmdProc but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
410     * TclInvokeStringCommand. This is an object-based wrapper procedure
411     * that extracts strings, calls the string procedure, and creates an
412     * object for the result. Similarly, if a command has a Tcl_ObjCmdProc
413     * but no Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
414     */
415    
416     for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL;
417     cmdInfoPtr++) {
418     int new;
419     Tcl_HashEntry *hPtr;
420    
421     if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)
422     && (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
423     && (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
424     panic("Tcl_CreateInterp: builtin command with NULL string and object command procs and a NULL compile proc\n");
425     }
426    
427     hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
428     cmdInfoPtr->name, &new);
429     if (new) {
430     cmdPtr = (Command *) ckalloc(sizeof(Command));
431     cmdPtr->hPtr = hPtr;
432     cmdPtr->nsPtr = iPtr->globalNsPtr;
433     cmdPtr->refCount = 1;
434     cmdPtr->cmdEpoch = 0;
435     cmdPtr->compileProc = cmdInfoPtr->compileProc;
436     if (cmdInfoPtr->proc == (Tcl_CmdProc *) NULL) {
437     cmdPtr->proc = TclInvokeObjectCommand;
438     cmdPtr->clientData = (ClientData) cmdPtr;
439     } else {
440     cmdPtr->proc = cmdInfoPtr->proc;
441     cmdPtr->clientData = (ClientData) NULL;
442     }
443     if (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
444     cmdPtr->objProc = TclInvokeStringCommand;
445     cmdPtr->objClientData = (ClientData) cmdPtr;
446     } else {
447     cmdPtr->objProc = cmdInfoPtr->objProc;
448     cmdPtr->objClientData = (ClientData) NULL;
449     }
450     cmdPtr->deleteProc = NULL;
451     cmdPtr->deleteData = (ClientData) NULL;
452     cmdPtr->deleted = 0;
453     cmdPtr->importRefPtr = NULL;
454     Tcl_SetHashValue(hPtr, cmdPtr);
455     }
456     }
457    
458     /*
459     * Register the builtin math functions.
460     */
461    
462     i = 0;
463     for (builtinFuncPtr = builtinFuncTable; builtinFuncPtr->name != NULL;
464     builtinFuncPtr++) {
465     Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name,
466     builtinFuncPtr->numArgs, builtinFuncPtr->argTypes,
467     (Tcl_MathProc *) NULL, (ClientData) 0);
468     hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
469     builtinFuncPtr->name);
470     if (hPtr == NULL) {
471     panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);
472     return NULL;
473     }
474     mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
475     mathFuncPtr->builtinFuncIndex = i;
476     i++;
477     }
478     iPtr->flags |= EXPR_INITIALIZED;
479    
480     /*
481     * Do Multiple/Safe Interps Tcl init stuff
482     */
483    
484     TclInterpInit(interp);
485    
486     /*
487     * We used to create the "errorInfo" and "errorCode" global vars at this
488     * point because so much of the Tcl implementation assumes they already
489     * exist. This is not quite enough, however, since they can be unset
490     * at any time.
491     *
492     * There are 2 choices:
493     * + Check every place where a GetVar of those is used
494     * and the NULL result is not checked (like in tclLoad.c)
495     * + Make SetVar,... NULL friendly
496     * We choose the second option because :
497     * + It is easy and low cost to check for NULL pointer before
498     * calling strlen()
499     * + It can be helpfull to other people using those API
500     * + Passing a NULL value to those closest 'meaning' is empty string
501     * (specially with the new objects where 0 bytes strings are ok)
502     * So the following init is commented out: -- dl
503     *
504     * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL,
505     * "", TCL_GLOBAL_ONLY);
506     * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL,
507     * "NONE", TCL_GLOBAL_ONLY);
508     */
509    
510     #ifndef TCL_GENERIC_ONLY
511     TclSetupEnv(interp);
512     #endif
513    
514     /*
515     * Compute the byte order of this machine.
516     */
517    
518     order.s = 1;
519     Tcl_SetVar2(interp, "tcl_platform", "byteOrder",
520     ((order.c[0] == 1) ? "littleEndian" : "bigEndian"),
521     TCL_GLOBAL_ONLY);
522    
523     /*
524     * Set up other variables such as tcl_version and tcl_library
525     */
526    
527     Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
528     Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
529     Tcl_TraceVar2(interp, "tcl_precision", (char *) NULL,
530     TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
531     TclPrecTraceProc, (ClientData) NULL);
532     TclpSetVariables(interp);
533    
534     #ifdef TCL_THREADS
535     /*
536     * The existence of the "threaded" element of the tcl_platform array indicates
537     * that this particular Tcl shell has been compiled with threads turned on.
538     * Using "info exists tcl_platform(threaded)" a Tcl script can introspect on the
539     * interpreter level of thread safety.
540     */
541    
542    
543     Tcl_SetVar2(interp, "tcl_platform", "threaded", "1",
544     TCL_GLOBAL_ONLY);
545     #endif
546    
547     /*
548     * Register Tcl's version number.
549     */
550    
551     Tcl_PkgProvideEx(interp, "Tcl", TCL_VERSION, (ClientData) &tclStubs);
552    
553     #ifdef Tcl_InitStubs
554     #undef Tcl_InitStubs
555     #endif
556     Tcl_InitStubs(interp, TCL_VERSION, 1);
557    
558     return interp;
559     }
560    
561     /*
562     *----------------------------------------------------------------------
563     *
564     * TclHideUnsafeCommands --
565     *
566     * Hides base commands that are not marked as safe from this
567     * interpreter.
568     *
569     * Results:
570     * TCL_OK if it succeeds, TCL_ERROR else.
571     *
572     * Side effects:
573     * Hides functionality in an interpreter.
574     *
575     *----------------------------------------------------------------------
576     */
577    
578     int
579     TclHideUnsafeCommands(interp)
580     Tcl_Interp *interp; /* Hide commands in this interpreter. */
581     {
582     register CmdInfo *cmdInfoPtr;
583    
584     if (interp == (Tcl_Interp *) NULL) {
585     return TCL_ERROR;
586     }
587     for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
588     if (!cmdInfoPtr->isSafe) {
589     Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
590     }
591     }
592     return TCL_OK;
593     }
594    
595     /*
596     *--------------------------------------------------------------
597     *
598     * Tcl_CallWhenDeleted --
599     *
600     * Arrange for a procedure to be called before a given
601     * interpreter is deleted. The procedure is called as soon
602     * as Tcl_DeleteInterp is called; if Tcl_CallWhenDeleted is
603     * called on an interpreter that has already been deleted,
604     * the procedure will be called when the last Tcl_Release is
605     * done on the interpreter.
606     *
607     * Results:
608     * None.
609     *
610     * Side effects:
611     * When Tcl_DeleteInterp is invoked to delete interp,
612     * proc will be invoked. See the manual entry for
613     * details.
614     *
615     *--------------------------------------------------------------
616     */
617    
618     void
619     Tcl_CallWhenDeleted(interp, proc, clientData)
620     Tcl_Interp *interp; /* Interpreter to watch. */
621     Tcl_InterpDeleteProc *proc; /* Procedure to call when interpreter
622     * is about to be deleted. */
623     ClientData clientData; /* One-word value to pass to proc. */
624     {
625     Interp *iPtr = (Interp *) interp;
626     static int assocDataCounter = 0;
627     #ifdef TCL_THREADS
628     static Tcl_Mutex assocMutex;
629     #endif
630     int new;
631     char buffer[32 + TCL_INTEGER_SPACE];
632     AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));
633     Tcl_HashEntry *hPtr;
634    
635     Tcl_MutexLock(&assocMutex);
636     sprintf(buffer, "Assoc Data Key #%d", assocDataCounter);
637     assocDataCounter++;
638     Tcl_MutexUnlock(&assocMutex);
639    
640     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
641     iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
642     Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
643     }
644     hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &new);
645     dPtr->proc = proc;
646     dPtr->clientData = clientData;
647     Tcl_SetHashValue(hPtr, dPtr);
648     }
649    
650     /*
651     *--------------------------------------------------------------
652     *
653     * Tcl_DontCallWhenDeleted --
654     *
655     * Cancel the arrangement for a procedure to be called when
656     * a given interpreter is deleted.
657     *
658     * Results:
659     * None.
660     *
661     * Side effects:
662     * If proc and clientData were previously registered as a
663     * callback via Tcl_CallWhenDeleted, they are unregistered.
664     * If they weren't previously registered then nothing
665     * happens.
666     *
667     *--------------------------------------------------------------
668     */
669    
670     void
671     Tcl_DontCallWhenDeleted(interp, proc, clientData)
672     Tcl_Interp *interp; /* Interpreter to watch. */
673     Tcl_InterpDeleteProc *proc; /* Procedure to call when interpreter
674     * is about to be deleted. */
675     ClientData clientData; /* One-word value to pass to proc. */
676     {
677     Interp *iPtr = (Interp *) interp;
678     Tcl_HashTable *hTablePtr;
679     Tcl_HashSearch hSearch;
680     Tcl_HashEntry *hPtr;
681     AssocData *dPtr;
682    
683     hTablePtr = iPtr->assocData;
684     if (hTablePtr == (Tcl_HashTable *) NULL) {
685     return;
686     }
687     for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
688     hPtr = Tcl_NextHashEntry(&hSearch)) {
689     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
690     if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
691     ckfree((char *) dPtr);
692     Tcl_DeleteHashEntry(hPtr);
693     return;
694     }
695     }
696     }
697    
698     /*
699     *----------------------------------------------------------------------
700     *
701     * Tcl_SetAssocData --
702     *
703     * Creates a named association between user-specified data, a delete
704     * function and this interpreter. If the association already exists
705     * the data is overwritten with the new data. The delete function will
706     * be invoked when the interpreter is deleted.
707     *
708     * Results:
709     * None.
710     *
711     * Side effects:
712     * Sets the associated data, creates the association if needed.
713     *
714     *----------------------------------------------------------------------
715     */
716    
717     void
718     Tcl_SetAssocData(interp, name, proc, clientData)
719     Tcl_Interp *interp; /* Interpreter to associate with. */
720     char *name; /* Name for association. */
721     Tcl_InterpDeleteProc *proc; /* Proc to call when interpreter is
722     * about to be deleted. */
723     ClientData clientData; /* One-word value to pass to proc. */
724     {
725     Interp *iPtr = (Interp *) interp;
726     AssocData *dPtr;
727     Tcl_HashEntry *hPtr;
728     int new;
729    
730     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
731     iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
732     Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
733     }
734     hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &new);
735     if (new == 0) {
736     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
737     } else {
738     dPtr = (AssocData *) ckalloc(sizeof(AssocData));
739     }
740     dPtr->proc = proc;
741     dPtr->clientData = clientData;
742    
743     Tcl_SetHashValue(hPtr, dPtr);
744     }
745    
746     /*
747     *----------------------------------------------------------------------
748     *
749     * Tcl_DeleteAssocData --
750     *
751     * Deletes a named association of user-specified data with
752     * the specified interpreter.
753     *
754     * Results:
755     * None.
756     *
757     * Side effects:
758     * Deletes the association.
759     *
760     *----------------------------------------------------------------------
761     */
762    
763     void
764     Tcl_DeleteAssocData(interp, name)
765     Tcl_Interp *interp; /* Interpreter to associate with. */
766     char *name; /* Name of association. */
767     {
768     Interp *iPtr = (Interp *) interp;
769     AssocData *dPtr;
770     Tcl_HashEntry *hPtr;
771    
772     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
773     return;
774     }
775     hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
776     if (hPtr == (Tcl_HashEntry *) NULL) {
777     return;
778     }
779     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
780     if (dPtr->proc != NULL) {
781     (dPtr->proc) (dPtr->clientData, interp);
782     }
783     ckfree((char *) dPtr);
784     Tcl_DeleteHashEntry(hPtr);
785     }
786    
787     /*
788     *----------------------------------------------------------------------
789     *
790     * Tcl_GetAssocData --
791     *
792     * Returns the client data associated with this name in the
793     * specified interpreter.
794     *
795     * Results:
796     * The client data in the AssocData record denoted by the named
797     * association, or NULL.
798     *
799     * Side effects:
800     * None.
801     *
802     *----------------------------------------------------------------------
803     */
804    
805     ClientData
806     Tcl_GetAssocData(interp, name, procPtr)
807     Tcl_Interp *interp; /* Interpreter associated with. */
808     char *name; /* Name of association. */
809     Tcl_InterpDeleteProc **procPtr; /* Pointer to place to store address
810     * of current deletion callback. */
811     {
812     Interp *iPtr = (Interp *) interp;
813     AssocData *dPtr;
814     Tcl_HashEntry *hPtr;
815    
816     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
817     return (ClientData) NULL;
818     }
819     hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
820     if (hPtr == (Tcl_HashEntry *) NULL) {
821     return (ClientData) NULL;
822     }
823     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
824     if (procPtr != (Tcl_InterpDeleteProc **) NULL) {
825     *procPtr = dPtr->proc;
826     }
827     return dPtr->clientData;
828     }
829    
830     /*
831     *----------------------------------------------------------------------
832     *
833     * Tcl_InterpDeleted --
834     *
835     * Returns nonzero if the interpreter has been deleted with a call
836     * to Tcl_DeleteInterp.
837     *
838     * Results:
839     * Nonzero if the interpreter is deleted, zero otherwise.
840     *
841     * Side effects:
842     * None.
843     *
844     *----------------------------------------------------------------------
845     */
846    
847     int
848     Tcl_InterpDeleted(interp)
849     Tcl_Interp *interp;
850     {
851     return (((Interp *) interp)->flags & DELETED) ? 1 : 0;
852     }
853    
854     /*
855     *----------------------------------------------------------------------
856     *
857     * Tcl_DeleteInterp --
858     *
859     * Ensures that the interpreter will be deleted eventually. If there
860     * are no Tcl_Preserve calls in effect for this interpreter, it is
861     * deleted immediately, otherwise the interpreter is deleted when
862     * the last Tcl_Preserve is matched by a call to Tcl_Release. In either
863     * case, the procedure runs the currently registered deletion callbacks.
864     *
865     * Results:
866     * None.
867     *
868     * Side effects:
869     * The interpreter is marked as deleted. The caller may still use it
870     * safely if there are calls to Tcl_Preserve in effect for the
871     * interpreter, but further calls to Tcl_Eval etc in this interpreter
872     * will fail.
873     *
874     *----------------------------------------------------------------------
875     */
876    
877     void
878     Tcl_DeleteInterp(interp)
879     Tcl_Interp *interp; /* Token for command interpreter (returned
880     * by a previous call to Tcl_CreateInterp). */
881     {
882     Interp *iPtr = (Interp *) interp;
883    
884     /*
885     * If the interpreter has already been marked deleted, just punt.
886     */
887    
888     if (iPtr->flags & DELETED) {
889     return;
890     }
891    
892     /*
893     * Mark the interpreter as deleted. No further evals will be allowed.
894     */
895    
896     iPtr->flags |= DELETED;
897    
898     /*
899     * Ensure that the interpreter is eventually deleted.
900     */
901    
902     Tcl_EventuallyFree((ClientData) interp,
903     (Tcl_FreeProc *) DeleteInterpProc);
904     }
905    
906     /*
907     *----------------------------------------------------------------------
908     *
909     * DeleteInterpProc --
910     *
911     * Helper procedure to delete an interpreter. This procedure is
912     * called when the last call to Tcl_Preserve on this interpreter
913     * is matched by a call to Tcl_Release. The procedure cleans up
914     * all resources used in the interpreter and calls all currently
915     * registered interpreter deletion callbacks.
916     *
917     * Results:
918     * None.
919     *
920     * Side effects:
921     * Whatever the interpreter deletion callbacks do. Frees resources
922     * used by the interpreter.
923     *
924     *----------------------------------------------------------------------
925     */
926    
927     static void
928     DeleteInterpProc(interp)
929     Tcl_Interp *interp; /* Interpreter to delete. */
930     {
931     Interp *iPtr = (Interp *) interp;
932     Tcl_HashEntry *hPtr;
933     Tcl_HashSearch search;
934     Tcl_HashTable *hTablePtr;
935     ResolverScheme *resPtr, *nextResPtr;
936    
937     /*
938     * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
939     */
940    
941     if (iPtr->numLevels > 0) {
942     panic("DeleteInterpProc called with active evals");
943     }
944    
945     /*
946     * The interpreter should already be marked deleted; otherwise how
947     * did we get here?
948     */
949    
950     if (!(iPtr->flags & DELETED)) {
951     panic("DeleteInterpProc called on interpreter not marked deleted");
952     }
953    
954     TclHandleFree(iPtr->handle);
955    
956     /*
957     * Dismantle everything in the global namespace except for the
958     * "errorInfo" and "errorCode" variables. These remain until the
959     * namespace is actually destroyed, in case any errors occur.
960     *
961     * Dismantle the namespace here, before we clear the assocData. If any
962     * background errors occur here, they will be deleted below.
963     */
964    
965     TclTeardownNamespace(iPtr->globalNsPtr);
966    
967     /*
968     * Delete all the hidden commands.
969     */
970    
971     hTablePtr = iPtr->hiddenCmdTablePtr;
972     if (hTablePtr != NULL) {
973     /*
974     * Non-pernicious deletion. The deletion callbacks will not be
975     * allowed to create any new hidden or non-hidden commands.
976     * Tcl_DeleteCommandFromToken() will remove the entry from the
977     * hiddenCmdTablePtr.
978     */
979    
980     hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
981     for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
982     Tcl_DeleteCommandFromToken(interp,
983     (Tcl_Command) Tcl_GetHashValue(hPtr));
984     }
985     Tcl_DeleteHashTable(hTablePtr);
986     ckfree((char *) hTablePtr);
987     }
988     /*
989     * Tear down the math function table.
990     */
991    
992     for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search);
993     hPtr != NULL;
994     hPtr = Tcl_NextHashEntry(&search)) {
995     ckfree((char *) Tcl_GetHashValue(hPtr));
996     }
997     Tcl_DeleteHashTable(&iPtr->mathFuncTable);
998    
999     /*
1000     * Invoke deletion callbacks; note that a callback can create new
1001     * callbacks, so we iterate.
1002     */
1003    
1004     while (iPtr->assocData != (Tcl_HashTable *) NULL) {
1005     AssocData *dPtr;
1006    
1007     hTablePtr = iPtr->assocData;
1008     iPtr->assocData = (Tcl_HashTable *) NULL;
1009     for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
1010     hPtr != NULL;
1011     hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
1012     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
1013     Tcl_DeleteHashEntry(hPtr);
1014     if (dPtr->proc != NULL) {
1015     (*dPtr->proc)(dPtr->clientData, interp);
1016     }
1017     ckfree((char *) dPtr);
1018     }
1019     Tcl_DeleteHashTable(hTablePtr);
1020     ckfree((char *) hTablePtr);
1021     }
1022    
1023     /*
1024     * Finish deleting the global namespace.
1025     */
1026    
1027     Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
1028    
1029     /*
1030     * Free up the result *after* deleting variables, since variable
1031     * deletion could have transferred ownership of the result string
1032     * to Tcl.
1033     */
1034    
1035     Tcl_FreeResult(interp);
1036     interp->result = NULL;
1037     Tcl_DecrRefCount(iPtr->objResultPtr);
1038     iPtr->objResultPtr = NULL;
1039     if (iPtr->errorInfo != NULL) {
1040     ckfree(iPtr->errorInfo);
1041     iPtr->errorInfo = NULL;
1042     }
1043     if (iPtr->errorCode != NULL) {
1044     ckfree(iPtr->errorCode);
1045     iPtr->errorCode = NULL;
1046     }
1047     if (iPtr->appendResult != NULL) {
1048     ckfree(iPtr->appendResult);
1049     iPtr->appendResult = NULL;
1050     }
1051     TclFreePackageInfo(iPtr);
1052     while (iPtr->tracePtr != NULL) {
1053     Trace *nextPtr = iPtr->tracePtr->nextPtr;
1054    
1055     ckfree((char *) iPtr->tracePtr);
1056     iPtr->tracePtr = nextPtr;
1057     }
1058     if (iPtr->execEnvPtr != NULL) {
1059     TclDeleteExecEnv(iPtr->execEnvPtr);
1060     }
1061     Tcl_DecrRefCount(iPtr->emptyObjPtr);
1062     iPtr->emptyObjPtr = NULL;
1063    
1064     resPtr = iPtr->resolverPtr;
1065     while (resPtr) {
1066     nextResPtr = resPtr->nextPtr;
1067     ckfree(resPtr->name);
1068     ckfree((char *) resPtr);
1069     resPtr = nextResPtr;
1070     }
1071    
1072     /*
1073     * Free up literal objects created for scripts compiled by the
1074     * interpreter.
1075     */
1076    
1077     TclDeleteLiteralTable(interp, &(iPtr->literalTable));
1078     ckfree((char *) iPtr);
1079     }
1080    
1081     /*
1082     *---------------------------------------------------------------------------
1083     *
1084     * Tcl_HideCommand --
1085     *
1086     * Makes a command hidden so that it cannot be invoked from within
1087     * an interpreter, only from within an ancestor.
1088     *
1089     * Results:
1090     * A standard Tcl result; also leaves a message in the interp's result
1091     * if an error occurs.
1092     *
1093     * Side effects:
1094     * Removes a command from the command table and create an entry
1095     * into the hidden command table under the specified token name.
1096     *
1097     *---------------------------------------------------------------------------
1098     */
1099    
1100     int
1101     Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
1102     Tcl_Interp *interp; /* Interpreter in which to hide command. */
1103     char *cmdName; /* Name of command to hide. */
1104     char *hiddenCmdToken; /* Token name of the to-be-hidden command. */
1105     {
1106     Interp *iPtr = (Interp *) interp;
1107     Tcl_Command cmd;
1108     Command *cmdPtr;
1109     Tcl_HashTable *hiddenCmdTablePtr;
1110     Tcl_HashEntry *hPtr;
1111     int new;
1112    
1113     if (iPtr->flags & DELETED) {
1114    
1115     /*
1116     * The interpreter is being deleted. Do not create any new
1117     * structures, because it is not safe to modify the interpreter.
1118     */
1119    
1120     return TCL_ERROR;
1121     }
1122    
1123     /*
1124     * Disallow hiding of commands that are currently in a namespace or
1125     * renaming (as part of hiding) into a namespace.
1126     *
1127     * (because the current implementation with a single global table
1128     * and the needed uniqueness of names cause problems with namespaces)
1129     *
1130     * we don't need to check for "::" in cmdName because the real check is
1131     * on the nsPtr below.
1132     *
1133     * hiddenCmdToken is just a string which is not interpreted in any way.
1134     * It may contain :: but the string is not interpreted as a namespace
1135     * qualifier command name. Thus, hiding foo::bar to foo::bar and then
1136     * trying to expose or invoke ::foo::bar will NOT work; but if the
1137     * application always uses the same strings it will get consistent
1138     * behaviour.
1139     *
1140     * But as we currently limit ourselves to the global namespace only
1141     * for the source, in order to avoid potential confusion,
1142     * lets prevent "::" in the token too. --dl
1143     */
1144    
1145     if (strstr(hiddenCmdToken, "::") != NULL) {
1146     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1147     "cannot use namespace qualifiers as hidden command",
1148     "token (rename)", (char *) NULL);
1149     return TCL_ERROR;
1150     }
1151    
1152     /*
1153     * Find the command to hide. An error is returned if cmdName can't
1154     * be found. Look up the command only from the global namespace.
1155     * Full path of the command must be given if using namespaces.
1156     */
1157    
1158     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
1159     /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1160     if (cmd == (Tcl_Command) NULL) {
1161     return TCL_ERROR;
1162     }
1163     cmdPtr = (Command *) cmd;
1164    
1165     /*
1166     * Check that the command is really in global namespace
1167     */
1168    
1169     if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
1170     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1171     "can only hide global namespace commands",
1172     " (use rename then hide)", (char *) NULL);
1173     return TCL_ERROR;
1174     }
1175    
1176     /*
1177     * Initialize the hidden command table if necessary.
1178     */
1179    
1180     hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
1181     if (hiddenCmdTablePtr == NULL) {
1182     hiddenCmdTablePtr = (Tcl_HashTable *)
1183     ckalloc((unsigned) sizeof(Tcl_HashTable));
1184     Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
1185     iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr;
1186     }
1187    
1188     /*
1189     * It is an error to move an exposed command to a hidden command with
1190     * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
1191     * exists.
1192     */
1193    
1194     hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &new);
1195     if (!new) {
1196     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1197     "hidden command named \"", hiddenCmdToken, "\" already exists",
1198     (char *) NULL);
1199     return TCL_ERROR;
1200     }
1201    
1202     /*
1203     * Nb : This code is currently 'like' a rename to a specialy set apart
1204     * name table. Changes here and in TclRenameCommand must
1205     * be kept in synch untill the common parts are actually
1206     * factorized out.
1207     */
1208    
1209     /*
1210     * Remove the hash entry for the command from the interpreter command
1211     * table. This is like deleting the command, so bump its command epoch;
1212     * this invalidates any cached references that point to the command.
1213     */
1214    
1215     if (cmdPtr->hPtr != NULL) {
1216     Tcl_DeleteHashEntry(cmdPtr->hPtr);
1217     cmdPtr->hPtr = (Tcl_HashEntry *) NULL;
1218     cmdPtr->cmdEpoch++;
1219     }
1220    
1221     /*
1222     * Now link the hash table entry with the command structure.
1223     * We ensured above that the nsPtr was right.
1224     */
1225    
1226     cmdPtr->hPtr = hPtr;
1227     Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
1228    
1229     /*
1230     * If the command being hidden has a compile procedure, increment the
1231     * interpreter's compileEpoch to invalidate its compiled code. This
1232     * makes sure that we don't later try to execute old code compiled with
1233     * command-specific (i.e., inline) bytecodes for the now-hidden
1234     * command. This field is checked in Tcl_EvalObj and ObjInterpProc,
1235     * and code whose compilation epoch doesn't match is recompiled.
1236     */
1237    
1238     if (cmdPtr->compileProc != NULL) {
1239     iPtr->compileEpoch++;
1240     }
1241     return TCL_OK;
1242     }
1243    
1244     /*
1245     *----------------------------------------------------------------------
1246     *
1247     * Tcl_ExposeCommand --
1248     *
1249     * Makes a previously hidden command callable from inside the
1250     * interpreter instead of only by its ancestors.
1251     *
1252     * Results:
1253     * A standard Tcl result. If an error occurs, a message is left
1254     * in the interp's result.
1255     *
1256     * Side effects:
1257     * Moves commands from one hash table to another.
1258     *
1259     *----------------------------------------------------------------------
1260     */
1261    
1262     int
1263     Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
1264     Tcl_Interp *interp; /* Interpreter in which to make command
1265     * callable. */
1266     char *hiddenCmdToken; /* Name of hidden command. */
1267     char *cmdName; /* Name of to-be-exposed command. */
1268     {
1269     Interp *iPtr = (Interp *) interp;
1270     Command *cmdPtr;
1271     Namespace *nsPtr;
1272     Tcl_HashEntry *hPtr;
1273     Tcl_HashTable *hiddenCmdTablePtr;
1274     int new;
1275    
1276     if (iPtr->flags & DELETED) {
1277     /*
1278     * The interpreter is being deleted. Do not create any new
1279     * structures, because it is not safe to modify the interpreter.
1280     */
1281    
1282     return TCL_ERROR;
1283     }
1284    
1285     /*
1286     * Check that we have a regular name for the command
1287     * (that the user is not trying to do an expose and a rename
1288     * (to another namespace) at the same time)
1289     */
1290    
1291     if (strstr(cmdName, "::") != NULL) {
1292     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1293     "can not expose to a namespace ",
1294     "(use expose to toplevel, then rename)",
1295     (char *) NULL);
1296     return TCL_ERROR;
1297     }
1298    
1299     /*
1300     * Get the command from the hidden command table:
1301     */
1302    
1303     hPtr = NULL;
1304     hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
1305     if (hiddenCmdTablePtr != NULL) {
1306     hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
1307     }
1308     if (hPtr == (Tcl_HashEntry *) NULL) {
1309     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1310     "unknown hidden command \"", hiddenCmdToken,
1311     "\"", (char *) NULL);
1312     return TCL_ERROR;
1313     }
1314     cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
1315    
1316    
1317     /*
1318     * Check that we have a true global namespace
1319     * command (enforced by Tcl_HideCommand() but let's double
1320     * check. (If it was not, we would not really know how to
1321     * handle it).
1322     */
1323     if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
1324     /*
1325     * This case is theoritically impossible,
1326     * we might rather panic() than 'nicely' erroring out ?
1327     */
1328     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1329     "trying to expose a non global command name space command",
1330     (char *) NULL);
1331     return TCL_ERROR;
1332     }
1333    
1334     /* This is the global table */
1335     nsPtr = cmdPtr->nsPtr;
1336    
1337     /*
1338     * It is an error to overwrite an existing exposed command as a result
1339     * of exposing a previously hidden command.
1340     */
1341    
1342     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &new);
1343     if (!new) {
1344     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1345     "exposed command \"", cmdName,
1346     "\" already exists", (char *) NULL);
1347     return TCL_ERROR;
1348     }
1349    
1350     /*
1351     * Remove the hash entry for the command from the interpreter hidden
1352     * command table.
1353     */
1354    
1355     if (cmdPtr->hPtr != NULL) {
1356     Tcl_DeleteHashEntry(cmdPtr->hPtr);
1357     cmdPtr->hPtr = NULL;
1358     }
1359    
1360     /*
1361     * Now link the hash table entry with the command structure.
1362     * This is like creating a new command, so deal with any shadowing
1363     * of commands in the global namespace.
1364     */
1365    
1366     cmdPtr->hPtr = hPtr;
1367    
1368     Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
1369    
1370     /*
1371     * Not needed as we are only in the global namespace
1372     * (but would be needed again if we supported namespace command hiding)
1373     *
1374     * TclResetShadowedCmdRefs(interp, cmdPtr);
1375     */
1376    
1377    
1378     /*
1379     * If the command being exposed has a compile procedure, increment
1380     * interpreter's compileEpoch to invalidate its compiled code. This
1381     * makes sure that we don't later try to execute old code compiled
1382     * assuming the command is hidden. This field is checked in Tcl_EvalObj
1383     * and ObjInterpProc, and code whose compilation epoch doesn't match is
1384     * recompiled.
1385     */
1386    
1387     if (cmdPtr->compileProc != NULL) {
1388     iPtr->compileEpoch++;
1389     }
1390     return TCL_OK;
1391     }
1392    
1393     /*
1394     *----------------------------------------------------------------------
1395     *
1396     * Tcl_CreateCommand --
1397     *
1398     * Define a new command in a command table.
1399     *
1400     * Results:
1401     * The return value is a token for the command, which can
1402     * be used in future calls to Tcl_GetCommandName.
1403     *
1404     * Side effects:
1405     * If a command named cmdName already exists for interp, it is deleted.
1406     * In the future, when cmdName is seen as the name of a command by
1407     * Tcl_Eval, proc will be called. To support the bytecode interpreter,
1408     * the command is created with a wrapper Tcl_ObjCmdProc
1409     * (TclInvokeStringCommand) that eventially calls proc. When the
1410     * command is deleted from the table, deleteProc will be called.
1411     * See the manual entry for details on the calling sequence.
1412     *
1413     *----------------------------------------------------------------------
1414     */
1415    
1416     Tcl_Command
1417     Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
1418     Tcl_Interp *interp; /* Token for command interpreter returned by
1419     * a previous call to Tcl_CreateInterp. */
1420     char *cmdName; /* Name of command. If it contains namespace
1421     * qualifiers, the new command is put in the
1422     * specified namespace; otherwise it is put
1423     * in the global namespace. */
1424     Tcl_CmdProc *proc; /* Procedure to associate with cmdName. */
1425     ClientData clientData; /* Arbitrary value passed to string proc. */
1426     Tcl_CmdDeleteProc *deleteProc;
1427     /* If not NULL, gives a procedure to call
1428     * when this command is deleted. */
1429     {
1430     Interp *iPtr = (Interp *) interp;
1431     ImportRef *oldRefPtr = NULL;
1432     Namespace *nsPtr, *dummy1, *dummy2;
1433     Command *cmdPtr, *refCmdPtr;
1434     Tcl_HashEntry *hPtr;
1435     char *tail;
1436     int new;
1437     ImportedCmdData *dataPtr;
1438    
1439     if (iPtr->flags & DELETED) {
1440     /*
1441     * The interpreter is being deleted. Don't create any new
1442     * commands; it's not safe to muck with the interpreter anymore.
1443     */
1444    
1445     return (Tcl_Command) NULL;
1446     }
1447    
1448     /*
1449     * Determine where the command should reside. If its name contains
1450     * namespace qualifiers, we put it in the specified namespace;
1451     * otherwise, we always put it in the global namespace.
1452     */
1453    
1454     if (strstr(cmdName, "::") != NULL) {
1455     TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
1456     CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
1457     if ((nsPtr == NULL) || (tail == NULL)) {
1458     return (Tcl_Command) NULL;
1459     }
1460     } else {
1461     nsPtr = iPtr->globalNsPtr;
1462     tail = cmdName;
1463     }
1464    
1465     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
1466     if (!new) {
1467     /*
1468     * Command already exists. Delete the old one.
1469     * Be careful to preserve any existing import links so we can
1470     * restore them down below. That way, you can redefine a
1471     * command and its import status will remain intact.
1472     */
1473    
1474     cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
1475     oldRefPtr = cmdPtr->importRefPtr;
1476     cmdPtr->importRefPtr = NULL;
1477    
1478     Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
1479     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
1480     if (!new) {
1481     /*
1482     * If the deletion callback recreated the command, just throw
1483     * away the new command (if we try to delete it again, we
1484     * could get stuck in an infinite loop).
1485     */
1486    
1487     ckfree((char*) Tcl_GetHashValue(hPtr));
1488     }
1489     }
1490     cmdPtr = (Command *) ckalloc(sizeof(Command));
1491     Tcl_SetHashValue(hPtr, cmdPtr);
1492     cmdPtr->hPtr = hPtr;
1493     cmdPtr->nsPtr = nsPtr;
1494     cmdPtr->refCount = 1;
1495     cmdPtr->cmdEpoch = 0;
1496     cmdPtr->compileProc = (CompileProc *) NULL;
1497     cmdPtr->objProc = TclInvokeStringCommand;
1498     cmdPtr->objClientData = (ClientData) cmdPtr;
1499     cmdPtr->proc = proc;
1500     cmdPtr->clientData = clientData;
1501     cmdPtr->deleteProc = deleteProc;
1502     cmdPtr->deleteData = clientData;
1503     cmdPtr->deleted = 0;
1504     cmdPtr->importRefPtr = NULL;
1505    
1506     /*
1507     * Plug in any existing import references found above. Be sure
1508     * to update all of these references to point to the new command.
1509     */
1510    
1511     if (oldRefPtr != NULL) {
1512     cmdPtr->importRefPtr = oldRefPtr;
1513     while (oldRefPtr != NULL) {
1514     refCmdPtr = oldRefPtr->importedCmdPtr;
1515     dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
1516     dataPtr->realCmdPtr = cmdPtr;
1517     oldRefPtr = oldRefPtr->nextPtr;
1518     }
1519     }
1520    
1521     /*
1522     * We just created a command, so in its namespace and all of its parent
1523     * namespaces, it may shadow global commands with the same name. If any
1524     * shadowed commands are found, invalidate all cached command references
1525     * in the affected namespaces.
1526     */
1527    
1528     TclResetShadowedCmdRefs(interp, cmdPtr);
1529     return (Tcl_Command) cmdPtr;
1530     }
1531    
1532     /*
1533     *----------------------------------------------------------------------
1534     *
1535     * Tcl_CreateObjCommand --
1536     *
1537     * Define a new object-based command in a command table.
1538     *
1539     * Results:
1540     * The return value is a token for the command, which can
1541     * be used in future calls to Tcl_GetCommandName.
1542     *
1543     * Side effects:
1544     * If no command named "cmdName" already exists for interp, one is
1545     * created. Otherwise, if a command does exist, then if the
1546     * object-based Tcl_ObjCmdProc is TclInvokeStringCommand, we assume
1547     * Tcl_CreateCommand was called previously for the same command and
1548     * just set its Tcl_ObjCmdProc to the argument "proc"; otherwise, we
1549     * delete the old command.
1550     *
1551     * In the future, during bytecode evaluation when "cmdName" is seen as
1552     * the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
1553     * Tcl_ObjCmdProc proc will be called. When the command is deleted from
1554     * the table, deleteProc will be called. See the manual entry for
1555     * details on the calling sequence.
1556     *
1557     *----------------------------------------------------------------------
1558     */
1559    
1560     Tcl_Command
1561     Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
1562     Tcl_Interp *interp; /* Token for command interpreter (returned
1563     * by previous call to Tcl_CreateInterp). */
1564     char *cmdName; /* Name of command. If it contains namespace
1565     * qualifiers, the new command is put in the
1566     * specified namespace; otherwise it is put
1567     * in the global namespace. */
1568     Tcl_ObjCmdProc *proc; /* Object-based procedure to associate with
1569     * name. */
1570     ClientData clientData; /* Arbitrary value to pass to object
1571     * procedure. */
1572     Tcl_CmdDeleteProc *deleteProc;
1573     /* If not NULL, gives a procedure to call
1574     * when this command is deleted. */
1575     {
1576     Interp *iPtr = (Interp *) interp;
1577     ImportRef *oldRefPtr = NULL;
1578     Namespace *nsPtr, *dummy1, *dummy2;
1579     Command *cmdPtr, *refCmdPtr;
1580     Tcl_HashEntry *hPtr;
1581     char *tail;
1582     int new;
1583     ImportedCmdData *dataPtr;
1584    
1585     if (iPtr->flags & DELETED) {
1586     /*
1587     * The interpreter is being deleted. Don't create any new
1588     * commands; it's not safe to muck with the interpreter anymore.
1589     */
1590    
1591     return (Tcl_Command) NULL;
1592     }
1593    
1594     /*
1595     * Determine where the command should reside. If its name contains
1596     * namespace qualifiers, we put it in the specified namespace;
1597     * otherwise, we always put it in the global namespace.
1598     */
1599    
1600     if (strstr(cmdName, "::") != NULL) {
1601     TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
1602     CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
1603     if ((nsPtr == NULL) || (tail == NULL)) {
1604     return (Tcl_Command) NULL;
1605     }
1606     } else {
1607     nsPtr = iPtr->globalNsPtr;
1608     tail = cmdName;
1609     }
1610    
1611     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
1612     if (!new) {
1613     cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
1614    
1615     /*
1616     * Command already exists. If its object-based Tcl_ObjCmdProc is
1617     * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
1618     * argument "proc". Otherwise, we delete the old command.
1619     */
1620    
1621     if (cmdPtr->objProc == TclInvokeStringCommand) {
1622     cmdPtr->objProc = proc;
1623     cmdPtr->objClientData = clientData;
1624     cmdPtr->deleteProc = deleteProc;
1625     cmdPtr->deleteData = clientData;
1626     return (Tcl_Command) cmdPtr;
1627     }
1628    
1629     /*
1630     * Otherwise, we delete the old command. Be careful to preserve
1631     * any existing import links so we can restore them down below.
1632     * That way, you can redefine a command and its import status
1633     * will remain intact.
1634     */
1635    
1636     oldRefPtr = cmdPtr->importRefPtr;
1637     cmdPtr->importRefPtr = NULL;
1638    
1639     Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
1640     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
1641     if (!new) {
1642     /*
1643     * If the deletion callback recreated the command, just throw
1644     * away the new command (if we try to delete it again, we
1645     * could get stuck in an infinite loop).
1646     */
1647    
1648     ckfree((char *) Tcl_GetHashValue(hPtr));
1649     }
1650     }
1651     cmdPtr = (Command *) ckalloc(sizeof(Command));
1652     Tcl_SetHashValue(hPtr, cmdPtr);
1653     cmdPtr->hPtr = hPtr;
1654     cmdPtr->nsPtr = nsPtr;
1655     cmdPtr->refCount = 1;
1656     cmdPtr->cmdEpoch = 0;
1657     cmdPtr->compileProc = (CompileProc *) NULL;
1658     cmdPtr->objProc = proc;
1659     cmdPtr->objClientData = clientData;
1660     cmdPtr->proc = TclInvokeObjectCommand;
1661     cmdPtr->clientData = (ClientData) cmdPtr;
1662     cmdPtr->deleteProc = deleteProc;
1663     cmdPtr->deleteData = clientData;
1664     cmdPtr->deleted = 0;
1665     cmdPtr->importRefPtr = NULL;
1666    
1667     /*
1668     * Plug in any existing import references found above. Be sure
1669     * to update all of these references to point to the new command.
1670     */
1671    
1672     if (oldRefPtr != NULL) {
1673     cmdPtr->importRefPtr = oldRefPtr;
1674     while (oldRefPtr != NULL) {
1675     refCmdPtr = oldRefPtr->importedCmdPtr;
1676     dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
1677     dataPtr->realCmdPtr = cmdPtr;
1678     oldRefPtr = oldRefPtr->nextPtr;
1679     }
1680     }
1681    
1682     /*
1683     * We just created a command, so in its namespace and all of its parent
1684     * namespaces, it may shadow global commands with the same name. If any
1685     * shadowed commands are found, invalidate all cached command references
1686     * in the affected namespaces.
1687     */
1688    
1689     TclResetShadowedCmdRefs(interp, cmdPtr);
1690     return (Tcl_Command) cmdPtr;
1691     }
1692    
1693     /*
1694     *----------------------------------------------------------------------
1695     *
1696     * TclInvokeStringCommand --
1697     *
1698     * "Wrapper" Tcl_ObjCmdProc used to call an existing string-based
1699     * Tcl_CmdProc if no object-based procedure exists for a command. A
1700     * pointer to this procedure is stored as the Tcl_ObjCmdProc in a
1701     * Command structure. It simply turns around and calls the string
1702     * Tcl_CmdProc in the Command structure.
1703     *
1704     * Results:
1705     * A standard Tcl object result value.
1706     *
1707     * Side effects:
1708     * Besides those side effects of the called Tcl_CmdProc,
1709     * TclInvokeStringCommand allocates and frees storage.
1710     *
1711     *----------------------------------------------------------------------
1712     */
1713    
1714     int
1715     TclInvokeStringCommand(clientData, interp, objc, objv)
1716     ClientData clientData; /* Points to command's Command structure. */
1717     Tcl_Interp *interp; /* Current interpreter. */
1718     register int objc; /* Number of arguments. */
1719     Tcl_Obj *CONST objv[]; /* Argument objects. */
1720     {
1721     register Command *cmdPtr = (Command *) clientData;
1722     register int i;
1723     int result;
1724    
1725     /*
1726     * This procedure generates an argv array for the string arguments. It
1727     * starts out with stack-allocated space but uses dynamically-allocated
1728     * storage if needed.
1729     */
1730    
1731     #define NUM_ARGS 20
1732     char *(argStorage[NUM_ARGS]);
1733     char **argv = argStorage;
1734    
1735     /*
1736     * Create the string argument array "argv". Make sure argv is large
1737     * enough to hold the objc arguments plus 1 extra for the zero
1738     * end-of-argv word.
1739     */
1740    
1741     if ((objc + 1) > NUM_ARGS) {
1742     argv = (char **) ckalloc((unsigned)(objc + 1) * sizeof(char *));
1743     }
1744    
1745     for (i = 0; i < objc; i++) {
1746     argv[i] = Tcl_GetString(objv[i]);
1747     }
1748     argv[objc] = 0;
1749    
1750     /*
1751     * Invoke the command's string-based Tcl_CmdProc.
1752     */
1753    
1754     result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv);
1755    
1756     /*
1757     * Free the argv array if malloc'ed storage was used.
1758     */
1759    
1760     if (argv != argStorage) {
1761     ckfree((char *) argv);
1762     }
1763     return result;
1764     #undef NUM_ARGS
1765     }
1766    
1767     /*
1768     *----------------------------------------------------------------------
1769     *
1770     * TclInvokeObjectCommand --
1771     *
1772     * "Wrapper" Tcl_CmdProc used to call an existing object-based
1773     * Tcl_ObjCmdProc if no string-based procedure exists for a command.
1774     * A pointer to this procedure is stored as the Tcl_CmdProc in a
1775     * Command structure. It simply turns around and calls the object
1776     * Tcl_ObjCmdProc in the Command structure.
1777     *
1778     * Results:
1779     * A standard Tcl string result value.
1780     *
1781     * Side effects:
1782     * Besides those side effects of the called Tcl_CmdProc,
1783     * TclInvokeStringCommand allocates and frees storage.
1784     *
1785     *----------------------------------------------------------------------
1786     */
1787    
1788     int
1789     TclInvokeObjectCommand(clientData, interp, argc, argv)
1790     ClientData clientData; /* Points to command's Command structure. */
1791     Tcl_Interp *interp; /* Current interpreter. */
1792     int argc; /* Number of arguments. */
1793     register char **argv; /* Argument strings. */
1794     {
1795     Command *cmdPtr = (Command *) clientData;
1796     register Tcl_Obj *objPtr;
1797     register int i;
1798     int length, result;
1799    
1800     /*
1801     * This procedure generates an objv array for object arguments that hold
1802     * the argv strings. It starts out with stack-allocated space but uses
1803     * dynamically-allocated storage if needed.
1804     */
1805    
1806     #define NUM_ARGS 20
1807     Tcl_Obj *(argStorage[NUM_ARGS]);
1808     register Tcl_Obj **objv = argStorage;
1809    
1810     /*
1811     * Create the object argument array "objv". Make sure objv is large
1812     * enough to hold the objc arguments plus 1 extra for the zero
1813     * end-of-objv word.
1814     */
1815    
1816     if ((argc + 1) > NUM_ARGS) {
1817     objv = (Tcl_Obj **)
1818     ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
1819     }
1820    
1821     for (i = 0; i < argc; i++) {
1822     length = strlen(argv[i]);
1823     TclNewObj(objPtr);
1824     TclInitStringRep(objPtr, argv[i], length);
1825     Tcl_IncrRefCount(objPtr);
1826     objv[i] = objPtr;
1827     }
1828     objv[argc] = 0;
1829    
1830     /*
1831     * Invoke the command's object-based Tcl_ObjCmdProc.
1832     */
1833    
1834     result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);
1835    
1836     /*
1837     * Move the interpreter's object result to the string result,
1838     * then reset the object result.
1839     */
1840    
1841     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
1842     TCL_VOLATILE);
1843    
1844     /*
1845     * Decrement the ref counts for the argument objects created above,
1846     * then free the objv array if malloc'ed storage was used.
1847     */
1848    
1849     for (i = 0; i < argc; i++) {
1850     objPtr = objv[i];
1851     Tcl_DecrRefCount(objPtr);
1852     }
1853     if (objv != argStorage) {
1854     ckfree((char *) objv);
1855     }
1856     return result;
1857     #undef NUM_ARGS
1858     }
1859    
1860     /*
1861     *----------------------------------------------------------------------
1862     *
1863     * TclRenameCommand --
1864     *
1865     * Called to give an existing Tcl command a different name. Both the
1866     * old command name and the new command name can have "::" namespace
1867     * qualifiers. If the new command has a different namespace context,
1868     * the command will be moved to that namespace and will execute in
1869     * the context of that new namespace.
1870     *
1871     * If the new command name is NULL or the null string, the command is
1872     * deleted.
1873     *
1874     * Results:
1875     * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
1876     *
1877     * Side effects:
1878     * If anything goes wrong, an error message is returned in the
1879     * interpreter's result object.
1880     *
1881     *----------------------------------------------------------------------
1882     */
1883    
1884     int
1885     TclRenameCommand(interp, oldName, newName)
1886     Tcl_Interp *interp; /* Current interpreter. */
1887     char *oldName; /* Existing command name. */
1888     char *newName; /* New command name. */
1889     {
1890     Interp *iPtr = (Interp *) interp;
1891     char *newTail;
1892     Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2;
1893     Tcl_Command cmd;
1894     Command *cmdPtr;
1895     Tcl_HashEntry *hPtr, *oldHPtr;
1896     int new, result;
1897    
1898     /*
1899     * Find the existing command. An error is returned if cmdName can't
1900     * be found.
1901     */
1902    
1903     cmd = Tcl_FindCommand(interp, oldName, (Tcl_Namespace *) NULL,
1904     /*flags*/ 0);
1905     cmdPtr = (Command *) cmd;
1906     if (cmdPtr == NULL) {
1907     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't ",
1908     ((newName == NULL)||(*newName == '\0'))? "delete":"rename",
1909     " \"", oldName, "\": command doesn't exist", (char *) NULL);
1910     return TCL_ERROR;
1911     }
1912     cmdNsPtr = cmdPtr->nsPtr;
1913    
1914     /*
1915     * If the new command name is NULL or empty, delete the command. Do this
1916     * with Tcl_DeleteCommandFromToken, since we already have the command.
1917     */
1918    
1919     if ((newName == NULL) || (*newName == '\0')) {
1920     Tcl_DeleteCommandFromToken(interp, cmd);
1921     return TCL_OK;
1922     }
1923    
1924     /*
1925     * Make sure that the destination command does not already exist.
1926     * The rename operation is like creating a command, so we should
1927     * automatically create the containing namespaces just like
1928     * Tcl_CreateCommand would.
1929     */
1930    
1931     TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL,
1932     CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
1933    
1934     if ((newNsPtr == NULL) || (newTail == NULL)) {
1935     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1936     "can't rename to \"", newName, "\": bad command name",
1937     (char *) NULL);
1938     return TCL_ERROR;
1939     }
1940     if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) {
1941     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1942     "can't rename to \"", newName,
1943     "\": command already exists", (char *) NULL);
1944     return TCL_ERROR;
1945     }
1946    
1947    
1948     /*
1949     * Warning: any changes done in the code here are likely
1950     * to be needed in Tcl_HideCommand() code too.
1951     * (until the common parts are extracted out) --dl
1952     */
1953    
1954     /*
1955     * Put the command in the new namespace so we can check for an alias
1956     * loop. Since we are adding a new command to a namespace, we must
1957     * handle any shadowing of the global commands that this might create.
1958     */
1959    
1960     oldHPtr = cmdPtr->hPtr;
1961     hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &new);
1962     Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
1963     cmdPtr->hPtr = hPtr;
1964     cmdPtr->nsPtr = newNsPtr;
1965     TclResetShadowedCmdRefs(interp, cmdPtr);
1966    
1967     /*
1968     * Now check for an alias loop. If we detect one, put everything back
1969     * the way it was and report the error.
1970     */
1971    
1972     result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr);
1973     if (result != TCL_OK) {
1974     Tcl_DeleteHashEntry(cmdPtr->hPtr);
1975     cmdPtr->hPtr = oldHPtr;
1976     cmdPtr->nsPtr = cmdNsPtr;
1977     return result;
1978     }
1979    
1980     /*
1981     * The new command name is okay, so remove the command from its
1982     * current namespace. This is like deleting the command, so bump
1983     * the cmdEpoch to invalidate any cached references to the command.
1984     */
1985    
1986     Tcl_DeleteHashEntry(oldHPtr);
1987     cmdPtr->cmdEpoch++;
1988    
1989     /*
1990     * If the command being renamed has a compile procedure, increment the
1991     * interpreter's compileEpoch to invalidate its compiled code. This
1992     * makes sure that we don't later try to execute old code compiled for
1993     * the now-renamed command.
1994     */
1995    
1996     if (cmdPtr->compileProc != NULL) {
1997     iPtr->compileEpoch++;
1998     }
1999    
2000     return TCL_OK;
2001     }
2002    
2003     /*
2004     *----------------------------------------------------------------------
2005     *
2006     * Tcl_SetCommandInfo --
2007     *
2008     * Modifies various information about a Tcl command. Note that
2009     * this procedure will not change a command's namespace; use
2010     * Tcl_RenameCommand to do that. Also, the isNativeObjectProc
2011     * member of *infoPtr is ignored.
2012     *
2013     * Results:
2014     * If cmdName exists in interp, then the information at *infoPtr
2015     * is stored with the command in place of the current information
2016     * and 1 is returned. If the command doesn't exist then 0 is
2017     * returned.
2018     *
2019     * Side effects:
2020     * None.
2021     *
2022     *----------------------------------------------------------------------
2023     */
2024    
2025     int
2026     Tcl_SetCommandInfo(interp, cmdName, infoPtr)
2027     Tcl_Interp *interp; /* Interpreter in which to look
2028     * for command. */
2029     char *cmdName; /* Name of desired command. */
2030     Tcl_CmdInfo *infoPtr; /* Where to find information
2031     * to store in the command. */
2032     {
2033     Tcl_Command cmd;
2034     Command *cmdPtr;
2035    
2036     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
2037     /*flags*/ 0);
2038     if (cmd == (Tcl_Command) NULL) {
2039     return 0;
2040     }
2041    
2042     /*
2043     * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
2044     */
2045    
2046     cmdPtr = (Command *) cmd;
2047     cmdPtr->proc = infoPtr->proc;
2048     cmdPtr->clientData = infoPtr->clientData;
2049     if (infoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
2050     cmdPtr->objProc = TclInvokeStringCommand;
2051     cmdPtr->objClientData = (ClientData) cmdPtr;
2052     } else {
2053     cmdPtr->objProc = infoPtr->objProc;
2054     cmdPtr->objClientData = infoPtr->objClientData;
2055     }
2056     cmdPtr->deleteProc = infoPtr->deleteProc;
2057     cmdPtr->deleteData = infoPtr->deleteData;
2058     return 1;
2059     }
2060    
2061     /*
2062     *----------------------------------------------------------------------
2063     *
2064     * Tcl_GetCommandInfo --
2065     *
2066     * Returns various information about a Tcl command.
2067     *
2068     * Results:
2069     * If cmdName exists in interp, then *infoPtr is modified to
2070     * hold information about cmdName and 1 is returned. If the
2071     * command doesn't exist then 0 is returned and *infoPtr isn't
2072     * modified.
2073     *
2074     * Side effects:
2075     * None.
2076     *
2077     *----------------------------------------------------------------------
2078     */
2079    
2080     int
2081     Tcl_GetCommandInfo(interp, cmdName, infoPtr)
2082     Tcl_Interp *interp; /* Interpreter in which to look
2083     * for command. */
2084     char *cmdName; /* Name of desired command. */
2085     Tcl_CmdInfo *infoPtr; /* Where to store information about
2086     * command. */
2087     {
2088     Tcl_Command cmd;
2089     Command *cmdPtr;
2090    
2091     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
2092     /*flags*/ 0);
2093     if (cmd == (Tcl_Command) NULL) {
2094     return 0;
2095     }
2096    
2097     /*
2098     * Set isNativeObjectProc 1 if objProc was registered by a call to
2099     * Tcl_CreateObjCommand. Otherwise set it to 0.
2100     */
2101    
2102     cmdPtr = (Command *) cmd;
2103     infoPtr->isNativeObjectProc =
2104     (cmdPtr->objProc != TclInvokeStringCommand);
2105     infoPtr->objProc = cmdPtr->objProc;
2106     infoPtr->objClientData = cmdPtr->objClientData;
2107     infoPtr->proc = cmdPtr->proc;
2108     infoPtr->clientData = cmdPtr->clientData;
2109     infoPtr->deleteProc = cmdPtr->deleteProc;
2110     infoPtr->deleteData = cmdPtr->deleteData;
2111     infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
2112     return 1;
2113     }
2114    
2115     /*
2116     *----------------------------------------------------------------------
2117     *
2118     * Tcl_GetCommandName --
2119     *
2120     * Given a token returned by Tcl_CreateCommand, this procedure
2121     * returns the current name of the command (which may have changed
2122     * due to renaming).
2123     *
2124     * Results:
2125     * The return value is the name of the given command.
2126     *
2127     * Side effects:
2128     * None.
2129     *
2130     *----------------------------------------------------------------------
2131     */
2132    
2133     char *
2134     Tcl_GetCommandName(interp, command)
2135     Tcl_Interp *interp; /* Interpreter containing the command. */
2136     Tcl_Command command; /* Token for command returned by a previous
2137     * call to Tcl_CreateCommand. The command
2138     * must not have been deleted. */
2139     {
2140     Command *cmdPtr = (Command *) command;
2141    
2142     if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
2143    
2144     /*
2145     * This should only happen if command was "created" after the
2146     * interpreter began to be deleted, so there isn't really any
2147     * command. Just return an empty string.
2148     */
2149    
2150     return "";
2151     }
2152     return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
2153     }
2154    
2155     /*
2156     *----------------------------------------------------------------------
2157     *
2158     * Tcl_GetCommandFullName --
2159     *
2160     * Given a token returned by, e.g., Tcl_CreateCommand or
2161     * Tcl_FindCommand, this procedure appends to an object the command's
2162     * full name, qualified by a sequence of parent namespace names. The
2163     * command's fully-qualified name may have changed due to renaming.
2164     *
2165     * Results:
2166     * None.
2167     *
2168     * Side effects:
2169     * The command's fully-qualified name is appended to the string
2170     * representation of objPtr.
2171     *
2172     *----------------------------------------------------------------------
2173     */
2174    
2175     void
2176     Tcl_GetCommandFullName(interp, command, objPtr)
2177     Tcl_Interp *interp; /* Interpreter containing the command. */
2178     Tcl_Command command; /* Token for command returned by a previous
2179     * call to Tcl_CreateCommand. The command
2180     * must not have been deleted. */
2181     Tcl_Obj *objPtr; /* Points to the object onto which the
2182     * command's full name is appended. */
2183    
2184     {
2185     Interp *iPtr = (Interp *) interp;
2186     register Command *cmdPtr = (Command *) command;
2187     char *name;
2188    
2189     /*
2190     * Add the full name of the containing namespace, followed by the "::"
2191     * separator, and the command name.
2192     */
2193    
2194     if (cmdPtr != NULL) {
2195     if (cmdPtr->nsPtr != NULL) {
2196     Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1);
2197     if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
2198     Tcl_AppendToObj(objPtr, "::", 2);
2199     }
2200     }
2201     if (cmdPtr->hPtr != NULL) {
2202     name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
2203     Tcl_AppendToObj(objPtr, name, -1);
2204     }
2205     }
2206     }
2207    
2208     /*
2209     *----------------------------------------------------------------------
2210     *
2211     * Tcl_DeleteCommand --
2212     *
2213     * Remove the given command from the given interpreter.
2214     *
2215     * Results:
2216     * 0 is returned if the command was deleted successfully.
2217     * -1 is returned if there didn't exist a command by that name.
2218     *
2219     * Side effects:
2220     * cmdName will no longer be recognized as a valid command for
2221     * interp.
2222     *
2223     *----------------------------------------------------------------------
2224     */
2225    
2226     int
2227     Tcl_DeleteCommand(interp, cmdName)
2228     Tcl_Interp *interp; /* Token for command interpreter (returned
2229     * by a previous Tcl_CreateInterp call). */
2230     char *cmdName; /* Name of command to remove. */
2231     {
2232     Tcl_Command cmd;
2233    
2234     /*
2235     * Find the desired command and delete it.
2236     */
2237    
2238     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
2239     /*flags*/ 0);
2240     if (cmd == (Tcl_Command) NULL) {
2241     return -1;
2242     }
2243     return Tcl_DeleteCommandFromToken(interp, cmd);
2244     }
2245    
2246     /*
2247     *----------------------------------------------------------------------
2248     *
2249     * Tcl_DeleteCommandFromToken --
2250     *
2251     * Removes the given command from the given interpreter. This procedure
2252     * resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead
2253     * of a command name for efficiency.
2254     *
2255     * Results:
2256     * 0 is returned if the command was deleted successfully.
2257     * -1 is returned if there didn't exist a command by that name.
2258     *
2259     * Side effects:
2260     * The command specified by "cmd" will no longer be recognized as a
2261     * valid command for "interp".
2262     *
2263     *----------------------------------------------------------------------
2264     */
2265    
2266     int
2267     Tcl_DeleteCommandFromToken(interp, cmd)
2268     Tcl_Interp *interp; /* Token for command interpreter returned by
2269     * a previous call to Tcl_CreateInterp. */
2270     Tcl_Command cmd; /* Token for command to delete. */
2271     {
2272     Interp *iPtr = (Interp *) interp;
2273     Command *cmdPtr = (Command *) cmd;
2274     ImportRef *refPtr, *nextRefPtr;
2275     Tcl_Command importCmd;
2276    
2277     /*
2278     * The code here is tricky. We can't delete the hash table entry
2279     * before invoking the deletion callback because there are cases
2280     * where the deletion callback needs to invoke the command (e.g.
2281     * object systems such as OTcl). However, this means that the
2282     * callback could try to delete or rename the command. The deleted
2283     * flag allows us to detect these cases and skip nested deletes.
2284     */
2285    
2286     if (cmdPtr->deleted) {
2287     /*
2288     * Another deletion is already in progress. Remove the hash
2289     * table entry now, but don't invoke a callback or free the
2290     * command structure.
2291     */
2292    
2293     Tcl_DeleteHashEntry(cmdPtr->hPtr);
2294     cmdPtr->hPtr = NULL;
2295     return 0;
2296     }
2297    
2298     /*
2299     * If the command being deleted has a compile procedure, increment the
2300     * interpreter's compileEpoch to invalidate its compiled code. This
2301     * makes sure that we don't later try to execute old code compiled with
2302     * command-specific (i.e., inline) bytecodes for the now-deleted
2303     * command. This field is checked in Tcl_EvalObj and ObjInterpProc, and
2304     * code whose compilation epoch doesn't match is recompiled.
2305     */
2306    
2307     if (cmdPtr->compileProc != NULL) {
2308     iPtr->compileEpoch++;
2309     }
2310    
2311     cmdPtr->deleted = 1;
2312     if (cmdPtr->deleteProc != NULL) {
2313     /*
2314     * Delete the command's client data. If this was an imported command
2315     * created when a command was imported into a namespace, this client
2316     * data will be a pointer to a ImportedCmdData structure describing
2317     * the "real" command that this imported command refers to.
2318     */
2319    
2320     /*
2321     * If you are getting a crash during the call to deleteProc and
2322     * cmdPtr->deleteProc is a pointer to the function free(), the
2323     * most likely cause is that your extension allocated memory
2324     * for the clientData argument to Tcl_CreateObjCommand() with
2325     * the ckalloc() macro and you are now trying to deallocate
2326     * this memory with free() instead of ckfree(). You should
2327     * pass a pointer to your own method that calls ckfree().
2328     */
2329    
2330     (*cmdPtr->deleteProc)(cmdPtr->deleteData);
2331     }
2332    
2333     /*
2334     * Bump the command epoch counter. This will invalidate all cached
2335     * references that point to this command.
2336     */
2337    
2338     cmdPtr->cmdEpoch++;
2339    
2340     /*
2341     * If this command was imported into other namespaces, then imported
2342     * commands were created that refer back to this command. Delete these
2343     * imported commands now.
2344     */
2345    
2346     for (refPtr = cmdPtr->importRefPtr; refPtr != NULL;
2347     refPtr = nextRefPtr) {
2348     nextRefPtr = refPtr->nextPtr;
2349     importCmd = (Tcl_Command) refPtr->importedCmdPtr;
2350     Tcl_DeleteCommandFromToken(interp, importCmd);
2351     }
2352    
2353     /*
2354     * Don't use hPtr to delete the hash entry here, because it's
2355     * possible that the deletion callback renamed the command.
2356     * Instead, use cmdPtr->hptr, and make sure that no-one else
2357     * has already deleted the hash entry.
2358     */
2359    
2360     if (cmdPtr->hPtr != NULL) {
2361     Tcl_DeleteHashEntry(cmdPtr->hPtr);
2362     }
2363    
2364     /*
2365     * Mark the Command structure as no longer valid. This allows
2366     * TclExecuteByteCode to recognize when a Command has logically been
2367     * deleted and a pointer to this Command structure cached in a CmdName
2368     * object is invalid. TclExecuteByteCode will look up the command again
2369     * in the interpreter's command hashtable.
2370     */
2371    
2372     cmdPtr->objProc = NULL;
2373    
2374     /*
2375     * Now free the Command structure, unless there is another reference to
2376     * it from a CmdName Tcl object in some ByteCode code sequence. In that
2377     * case, delay the cleanup until all references are either discarded
2378     * (when a ByteCode is freed) or replaced by a new reference (when a
2379     * cached CmdName Command reference is found to be invalid and
2380     * TclExecuteByteCode looks up the command in the command hashtable).
2381     */
2382    
2383     TclCleanupCommand(cmdPtr);
2384     return 0;
2385     }
2386    
2387     /*
2388     *----------------------------------------------------------------------
2389     *
2390     * TclCleanupCommand --
2391     *
2392     * This procedure frees up a Command structure unless it is still
2393     * referenced from an interpreter's command hashtable or from a CmdName
2394     * Tcl object representing the name of a command in a ByteCode
2395     * instruction sequence.
2396     *
2397     * Results:
2398     * None.
2399     *
2400     * Side effects:
2401     * Memory gets freed unless a reference to the Command structure still
2402     * exists. In that case the cleanup is delayed until the command is
2403     * deleted or when the last ByteCode referring to it is freed.
2404     *
2405     *----------------------------------------------------------------------
2406     */
2407    
2408     void
2409     TclCleanupCommand(cmdPtr)
2410     register Command *cmdPtr; /* Points to the Command structure to
2411     * be freed. */
2412     {
2413     cmdPtr->refCount--;
2414     if (cmdPtr->refCount <= 0) {
2415     ckfree((char *) cmdPtr);
2416     }
2417     }
2418    
2419     /*
2420     *----------------------------------------------------------------------
2421     *
2422     * Tcl_CreateMathFunc --
2423     *
2424     * Creates a new math function for expressions in a given
2425     * interpreter.
2426     *
2427     * Results:
2428     * None.
2429     *
2430     * Side effects:
2431     * The function defined by "name" is created or redefined. If the
2432     * function already exists then its definition is replaced; this
2433     * includes the builtin functions. Redefining a builtin function forces
2434     * all existing code to be invalidated since that code may be compiled
2435     * using an instruction specific to the replaced function. In addition,
2436     * redefioning a non-builtin function will force existing code to be
2437     * invalidated if the number of arguments has changed.
2438     *
2439     *----------------------------------------------------------------------
2440     */
2441    
2442     void
2443     Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
2444     Tcl_Interp *interp; /* Interpreter in which function is
2445     * to be available. */
2446     char *name; /* Name of function (e.g. "sin"). */
2447     int numArgs; /* Nnumber of arguments required by
2448     * function. */
2449     Tcl_ValueType *argTypes; /* Array of types acceptable for
2450     * each argument. */
2451     Tcl_MathProc *proc; /* Procedure that implements the
2452     * math function. */
2453     ClientData clientData; /* Additional value to pass to the
2454     * function. */
2455     {
2456     Interp *iPtr = (Interp *) interp;
2457     Tcl_HashEntry *hPtr;
2458     MathFunc *mathFuncPtr;
2459     int new, i;
2460    
2461     hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
2462     if (new) {
2463     Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
2464     }
2465     mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
2466    
2467     if (!new) {
2468     if (mathFuncPtr->builtinFuncIndex >= 0) {
2469     /*
2470     * We are redefining a builtin math function. Invalidate the
2471     * interpreter's existing code by incrementing its
2472     * compileEpoch member. This field is checked in Tcl_EvalObj
2473     * and ObjInterpProc, and code whose compilation epoch doesn't
2474     * match is recompiled. Newly compiled code will no longer
2475     * treat the function as builtin.
2476     */
2477    
2478     iPtr->compileEpoch++;
2479     } else {
2480     /*
2481     * A non-builtin function is being redefined. We must invalidate
2482     * existing code if the number of arguments has changed. This
2483     * is because existing code was compiled assuming that number.
2484     */
2485    
2486     if (numArgs != mathFuncPtr->numArgs) {
2487     iPtr->compileEpoch++;
2488     }
2489     }
2490     }
2491    
2492     mathFuncPtr->builtinFuncIndex = -1; /* can't be a builtin function */
2493     if (numArgs > MAX_MATH_ARGS) {
2494     numArgs = MAX_MATH_ARGS;
2495     }
2496     mathFuncPtr->numArgs = numArgs;
2497     for (i = 0; i < numArgs; i++) {
2498     mathFuncPtr->argTypes[i] = argTypes[i];
2499     }
2500     mathFuncPtr->proc = proc;
2501     mathFuncPtr->clientData = clientData;
2502     }
2503    
2504     /*
2505     *----------------------------------------------------------------------
2506     *
2507     * Tcl_EvalObjEx --
2508     *
2509     * Execute Tcl commands stored in a Tcl object. These commands are
2510     * compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT
2511     * is specified.
2512     *
2513     * Results:
2514     * The return value is one of the return codes defined in tcl.h
2515     * (such as TCL_OK), and the interpreter's result contains a value
2516     * to supplement the return code.
2517     *
2518     * Side effects:
2519     * The object is converted, if necessary, to a ByteCode object that
2520     * holds the bytecode instructions for the commands. Executing the
2521     * commands will almost certainly have side effects that depend
2522     * on those commands.
2523     *
2524     * Just as in Tcl_Eval, interp->termOffset is set to the offset of the
2525     * last character executed in the objPtr's string.
2526     *
2527     *----------------------------------------------------------------------
2528     */
2529    
2530     int
2531     Tcl_EvalObjEx(interp, objPtr, flags)
2532     Tcl_Interp *interp; /* Token for command interpreter
2533     * (returned by a previous call to
2534     * Tcl_CreateInterp). */
2535     register Tcl_Obj *objPtr; /* Pointer to object containing
2536     * commands to execute. */
2537     int flags; /* Collection of OR-ed bits that
2538     * control the evaluation of the
2539     * script. Supported values are
2540     * TCL_EVAL_GLOBAL and
2541     * TCL_EVAL_DIRECT. */
2542     {
2543     register Interp *iPtr = (Interp *) interp;
2544     int evalFlags; /* Interp->evalFlags value when the
2545     * procedure was called. */
2546     register ByteCode* codePtr; /* Tcl Internal type of bytecode. */
2547     int oldCount = iPtr->cmdCount; /* Used to tell whether any commands
2548     * at all were executed. */
2549     int numSrcBytes;
2550     int result;
2551     CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
2552     * in case TCL_EVAL_GLOBAL was set. */
2553     Namespace *namespacePtr;
2554    
2555     Tcl_IncrRefCount(objPtr);
2556    
2557     if ((iPtr->flags & USE_EVAL_DIRECT) || (flags & TCL_EVAL_DIRECT)) {
2558     /*
2559     * We're not supposed to use the compiler or byte-code interpreter.
2560     * Let Tcl_EvalEx evaluate the command directly (and probably
2561     * more slowly).
2562     *
2563     * Pure List Optimization (no string representation). In this
2564     * case, we can safely use Tcl_EvalObjv instead and get an
2565     * appreciable improvement in execution speed. This is because it
2566     * allows us to avoid a setFromAny step that would just pack
2567     * everything into a string and back out again.
2568     *
2569     * USE_EVAL_DIRECT is a special flag used for testing purpose only
2570     * (ensure we go into the TCL_EVAL_DIRECT path, avoiding opt)
2571     */
2572     if (!(iPtr->flags & USE_EVAL_DIRECT) &&
2573     (objPtr->typePtr == &tclListType) && /* is a list... */
2574     (objPtr->bytes == NULL) /* ...without a string rep */) {
2575     register List *listRepPtr =
2576     (List *) objPtr->internalRep.otherValuePtr;
2577     result = Tcl_EvalObjv(interp, listRepPtr->elemCount,
2578     listRepPtr->elements, flags);
2579     } else {
2580     register char *p;
2581     p = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
2582     result = Tcl_EvalEx(interp, p, numSrcBytes, flags);
2583     }
2584     Tcl_DecrRefCount(objPtr);
2585     return result;
2586     }
2587    
2588     /*
2589     * Prevent the object from being deleted as a side effect of evaling it.
2590     */
2591    
2592     savedVarFramePtr = iPtr->varFramePtr;
2593     if (flags & TCL_EVAL_GLOBAL) {
2594     iPtr->varFramePtr = NULL;
2595     }
2596    
2597     /*
2598     * Reset both the interpreter's string and object results and clear out
2599     * any error information. This makes sure that we return an empty
2600     * result if there are no commands in the command string.
2601     */
2602    
2603     Tcl_ResetResult(interp);
2604    
2605     /*
2606     * Check depth of nested calls to Tcl_Eval: if this gets too large,
2607     * it's probably because of an infinite loop somewhere.
2608     */
2609    
2610     iPtr->numLevels++;
2611     if (iPtr->numLevels > iPtr->maxNestingDepth) {
2612     Tcl_AppendToObj(Tcl_GetObjResult(interp),
2613     "too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
2614     result = TCL_ERROR;
2615     goto done;
2616     }
2617    
2618     /*
2619     * On the Mac, we will never reach the default recursion limit before
2620     * blowing the stack. So we need to do a check here.
2621     */
2622    
2623     if (TclpCheckStackSpace() == 0) {
2624     /*NOTREACHED*/
2625     Tcl_AppendToObj(Tcl_GetObjResult(interp),
2626     "too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
2627     result = TCL_ERROR;
2628     goto done;
2629     }
2630    
2631     /*
2632     * If the interpreter has been deleted, return an error.
2633     */
2634    
2635     if (iPtr->flags & DELETED) {
2636     Tcl_ResetResult(interp);
2637     Tcl_AppendToObj(Tcl_GetObjResult(interp),
2638     "attempt to call eval in deleted interpreter", -1);
2639     Tcl_SetErrorCode(interp, "CORE", "IDELETE",
2640     "attempt to call eval in deleted interpreter",
2641     (char *) NULL);
2642     result = TCL_ERROR;
2643     goto done;
2644     }
2645    
2646     /*
2647     * Get the ByteCode from the object. If it exists, make sure it hasn't
2648     * been invalidated by, e.g., someone redefining a command with a
2649     * compile procedure (this might make the compiled code wrong). If
2650     * necessary, convert the object to be a ByteCode object and compile it.
2651     * Also, if the code was compiled in/for a different interpreter,
2652     * or for a different namespace, or for the same namespace but
2653     * with different name resolution rules, we recompile it.
2654     *
2655     * Precompiled objects, however, are immutable and therefore
2656     * they are not recompiled, even if the epoch has changed.
2657     *
2658     * To be pedantically correct, we should also check that the
2659     * originating procPtr is the same as the current context procPtr
2660     * (assuming one exists at all - none for global level). This
2661     * code is #def'ed out because [info body] was changed to never
2662     * return a bytecode type object, which should obviate us from
2663     * the extra checks here.
2664     */
2665    
2666     if (iPtr->varFramePtr != NULL) {
2667     namespacePtr = iPtr->varFramePtr->nsPtr;
2668     } else {
2669     namespacePtr = iPtr->globalNsPtr;
2670     }
2671    
2672     if (objPtr->typePtr == &tclByteCodeType) {
2673     codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
2674    
2675     if (((Interp *) *codePtr->interpHandle != iPtr)
2676     || (codePtr->compileEpoch != iPtr->compileEpoch)
2677     #ifdef CHECK_PROC_ORIGINATION /* [Bug: 3412 Pedantic] */
2678     || (codePtr->procPtr != NULL && !(iPtr->varFramePtr &&
2679     iPtr->varFramePtr->procPtr == codePtr->procPtr))
2680     #endif
2681     || (codePtr->nsPtr != namespacePtr)
2682     || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
2683     if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
2684     if ((Interp *) *codePtr->interpHandle != iPtr) {
2685     panic("Tcl_EvalObj: compiled script jumped interps");
2686     }
2687     codePtr->compileEpoch = iPtr->compileEpoch;
2688     } else {
2689     tclByteCodeType.freeIntRepProc(objPtr);
2690     }
2691     }
2692     }
2693     if (objPtr->typePtr != &tclByteCodeType) {
2694     iPtr->errorLine = 1;
2695     result = tclByteCodeType.setFromAnyProc(interp, objPtr);
2696     if (result != TCL_OK) {
2697     goto done;
2698     }
2699     } else {
2700     codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
2701     if (((Interp *) *codePtr->interpHandle != iPtr)
2702     || (codePtr->compileEpoch != iPtr->compileEpoch)) {
2703     (*tclByteCodeType.freeIntRepProc)(objPtr);
2704     iPtr->errorLine = 1;
2705     result = (*tclByteCodeType.setFromAnyProc)(interp, objPtr);
2706     if (result != TCL_OK) {
2707     iPtr->numLevels--;
2708     return result;
2709     }
2710     }
2711     }
2712     codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
2713    
2714     /*
2715     * Extract then reset the compilation flags in the interpreter.
2716     * Resetting the flags must be done after any compilation.
2717     */
2718    
2719     evalFlags = iPtr->evalFlags;
2720     iPtr->evalFlags = 0;
2721    
2722     /*
2723     * Execute the commands. If the code was compiled from an empty string,
2724     * don't bother executing the code.
2725     */
2726    
2727     numSrcBytes = codePtr->numSrcBytes;
2728     if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
2729     /*
2730     * Increment the code's ref count while it is being executed. If
2731     * afterwards no references to it remain, free the code.
2732     */
2733    
2734     codePtr->refCount++;
2735     result = TclExecuteByteCode(interp, codePtr);
2736     codePtr->refCount--;
2737     if (codePtr->refCount <= 0) {
2738     TclCleanupByteCode(codePtr);
2739     }
2740     } else {
2741     result = TCL_OK;
2742     }
2743    
2744     /*
2745     * If no commands at all were executed, check for asynchronous
2746     * handlers so that they at least get one change to execute.
2747     * This is needed to handle event loops written in Tcl with
2748     * empty bodies.
2749     */
2750    
2751     if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
2752     result = Tcl_AsyncInvoke(interp, result);
2753     }
2754    
2755     /*
2756     * Update the interpreter's evaluation level count. If we are again at
2757     * the top level, process any unusual return code returned by the
2758     * evaluated code.
2759     */
2760    
2761     if (iPtr->numLevels == 1) {
2762     if (result == TCL_RETURN) {
2763     result = TclUpdateReturnInfo(iPtr);
2764     }
2765     if ((result != TCL_OK) && (result != TCL_ERROR)
2766     && ((evalFlags & TCL_ALLOW_EXCEPTIONS) == 0)) {
2767     ProcessUnexpectedResult(interp, result);
2768     result = TCL_ERROR;
2769     }
2770     }
2771    
2772     /*
2773     * If an error occurred, record information about what was being
2774     * executed when the error occurred.
2775     */
2776    
2777     if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
2778     RecordTracebackInfo(interp, objPtr, numSrcBytes);
2779     }
2780    
2781     /*
2782     * Set the interpreter's termOffset member to the offset of the
2783     * character just after the last one executed. We approximate the offset
2784     * of the last character executed by using the number of characters
2785     * compiled.
2786     */
2787    
2788     iPtr->termOffset = numSrcBytes;
2789     iPtr->flags &= ~ERR_ALREADY_LOGGED;
2790    
2791     done:
2792     TclDecrRefCount(objPtr);
2793     iPtr->varFramePtr = savedVarFramePtr;
2794     iPtr->numLevels--;
2795     return result;
2796     }
2797    
2798     /*
2799     *----------------------------------------------------------------------
2800     *
2801     * ProcessUnexpectedResult --
2802     *
2803     * Procedure called by Tcl_EvalObj to set the interpreter's result
2804     * value to an appropriate error message when the code it evaluates
2805     * returns an unexpected result code (not TCL_OK and not TCL_ERROR) to
2806     * the topmost evaluation level.
2807     *
2808     * Results:
2809     * None.
2810     *
2811     * Side effects:
2812     * The interpreter result is set to an error message appropriate to
2813     * the result code.
2814     *
2815     *----------------------------------------------------------------------
2816     */
2817    
2818     static void
2819     ProcessUnexpectedResult(interp, returnCode)
2820     Tcl_Interp *interp; /* The interpreter in which the unexpected
2821     * result code was returned. */
2822     int returnCode; /* The unexpected result code. */
2823     {
2824     Tcl_ResetResult(interp);
2825     if (returnCode == TCL_BREAK) {
2826     Tcl_AppendToObj(Tcl_GetObjResult(interp),
2827     "invoked \"break\" outside of a loop", -1);
2828     } else if (returnCode == TCL_CONTINUE) {
2829     Tcl_AppendToObj(Tcl_GetObjResult(interp),
2830     "invoked \"continue\" outside of a loop", -1);
2831     } else {
2832     char buf[30 + TCL_INTEGER_SPACE];
2833    
2834     sprintf(buf, "command returned bad code: %d", returnCode);
2835     Tcl_SetResult(interp, buf, TCL_VOLATILE);
2836     }
2837     }
2838    
2839     /*
2840     *----------------------------------------------------------------------
2841     *
2842     * RecordTracebackInfo --
2843     *
2844     * Procedure called by Tcl_EvalObj to record information about what was
2845     * being executed when the error occurred.
2846     *
2847     * Results:
2848     * None.
2849     *
2850     * Side effects:
2851     * Appends information about the script being evaluated to the
2852     * interpreter's "errorInfo" variable.
2853     *
2854     *----------------------------------------------------------------------
2855     */
2856    
2857     static void
2858     RecordTracebackInfo(interp, objPtr, numSrcBytes)
2859     Tcl_Interp *interp; /* The interpreter in which the error
2860     * occurred. */
2861     Tcl_Obj *objPtr; /* Points to object containing script whose
2862     * evaluation resulted in an error. */
2863     int numSrcBytes; /* Number of bytes compiled in script. */
2864     {
2865     Interp *iPtr = (Interp *) interp;
2866     char buf[200];
2867     char *ellipsis, *bytes;
2868     int length;
2869    
2870     /*
2871     * Decide how much of the command to print in the error message
2872     * (up to a certain number of bytes).
2873     */
2874    
2875     bytes = Tcl_GetStringFromObj(objPtr, &length);
2876     length = TclMin(numSrcBytes, length);
2877    
2878     ellipsis = "";
2879     if (length > 150) {
2880     length = 150;
2881     ellipsis = " ...";
2882     }
2883    
2884     if (!(iPtr->flags & ERR_IN_PROGRESS)) {
2885     sprintf(buf, "\n while executing\n\"%.*s%s\"",
2886     length, bytes, ellipsis);
2887     } else {
2888     sprintf(buf, "\n invoked from within\n\"%.*s%s\"",
2889     length, bytes, ellipsis);
2890     }
2891     Tcl_AddObjErrorInfo(interp, buf, -1);
2892     }
2893    
2894     /*
2895     *---------------------------------------------------------------------------
2896     *
2897     * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
2898     *
2899     * Procedures to evaluate an expression and return its value in a
2900     * particular form.
2901     *
2902     * Results:
2903     * Each of the procedures below returns a standard Tcl result. If an
2904     * error occurs then an error message is left in the interp's result.
2905     * Otherwise the value of the expression, in the appropriate form,
2906     * is stored at *ptr. If the expression had a result that was
2907     * incompatible with the desired form then an error is returned.
2908     *
2909     * Side effects:
2910     * None.
2911     *
2912     *---------------------------------------------------------------------------
2913     */
2914    
2915     int
2916     Tcl_ExprLong(interp, string, ptr)
2917     Tcl_Interp *interp; /* Context in which to evaluate the
2918     * expression. */
2919     char *string; /* Expression to evaluate. */
2920     long *ptr; /* Where to store result. */
2921     {
2922     register Tcl_Obj *exprPtr;
2923     Tcl_Obj *resultPtr;
2924     int length = strlen(string);
2925     int result = TCL_OK;
2926    
2927     if (length > 0) {
2928     exprPtr = Tcl_NewStringObj(string, length);
2929     Tcl_IncrRefCount(exprPtr);
2930     result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
2931     if (result == TCL_OK) {
2932     /*
2933     * Store an integer based on the expression result.
2934     */
2935    
2936     if (resultPtr->typePtr == &tclIntType) {
2937     *ptr = resultPtr->internalRep.longValue;
2938     } else if (resultPtr->typePtr == &tclDoubleType) {
2939     *ptr = (long) resultPtr->internalRep.doubleValue;
2940     } else {
2941     Tcl_SetResult(interp,
2942     "expression didn't have numeric value", TCL_STATIC);
2943     result = TCL_ERROR;
2944     }
2945     Tcl_DecrRefCount(resultPtr); /* discard the result object */
2946     } else {
2947     /*
2948     * Move the interpreter's object result to the string result,
2949     * then reset the object result.
2950     */
2951    
2952     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
2953     TCL_VOLATILE);
2954     }
2955     Tcl_DecrRefCount(exprPtr); /* discard the expression object */
2956     } else {
2957     /*
2958     * An empty string. Just set the result integer to 0.
2959     */
2960    
2961     *ptr = 0;
2962     }
2963     return result;
2964     }
2965    
2966     int
2967     Tcl_ExprDouble(interp, string, ptr)
2968     Tcl_Interp *interp; /* Context in which to evaluate the
2969     * expression. */
2970     char *string; /* Expression to evaluate. */
2971     double *ptr; /* Where to store result. */
2972     {
2973     register Tcl_Obj *exprPtr;
2974     Tcl_Obj *resultPtr;
2975     int length = strlen(string);
2976     int result = TCL_OK;
2977    
2978     if (length > 0) {
2979     exprPtr = Tcl_NewStringObj(string, length);
2980     Tcl_IncrRefCount(exprPtr);
2981     result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
2982     if (result == TCL_OK) {
2983     /*
2984     * Store a double based on the expression result.
2985     */
2986    
2987     if (resultPtr->typePtr == &tclIntType) {
2988     *ptr = (double) resultPtr->internalRep.longValue;
2989     } else if (resultPtr->typePtr == &tclDoubleType) {
2990     *ptr = resultPtr->internalRep.doubleValue;
2991     } else {
2992     Tcl_SetResult(interp,
2993     "expression didn't have numeric value", TCL_STATIC);
2994     result = TCL_ERROR;
2995     }
2996     Tcl_DecrRefCount(resultPtr); /* discard the result object */
2997     } else {
2998     /*
2999     * Move the interpreter's object result to the string result,
3000     * then reset the object result.
3001     */
3002    
3003     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
3004     TCL_VOLATILE);
3005     }
3006     Tcl_DecrRefCount(exprPtr); /* discard the expression object */
3007     } else {
3008     /*
3009     * An empty string. Just set the result double to 0.0.
3010     */
3011    
3012     *ptr = 0.0;
3013     }
3014     return result;
3015     }
3016    
3017     int
3018     Tcl_ExprBoolean(interp, string, ptr)
3019     Tcl_Interp *interp; /* Context in which to evaluate the
3020     * expression. */
3021     char *string; /* Expression to evaluate. */
3022     int *ptr; /* Where to store 0/1 result. */
3023     {
3024     register Tcl_Obj *exprPtr;
3025     Tcl_Obj *resultPtr;
3026     int length = strlen(string);
3027     int result = TCL_OK;
3028    
3029     if (length > 0) {
3030     exprPtr = Tcl_NewStringObj(string, length);
3031     Tcl_IncrRefCount(exprPtr);
3032     result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
3033     if (result == TCL_OK) {
3034     /*
3035     * Store a boolean based on the expression result.
3036     */
3037    
3038     if (resultPtr->typePtr == &tclIntType) {
3039     *ptr = (resultPtr->internalRep.longValue != 0);
3040     } else if (resultPtr->typePtr == &tclDoubleType) {
3041     *ptr = (resultPtr->internalRep.doubleValue != 0.0);
3042     } else {
3043     result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
3044     }
3045     Tcl_DecrRefCount(resultPtr); /* discard the result object */
3046     }
3047     if (result != TCL_OK) {
3048     /*
3049     * Move the interpreter's object result to the string result,
3050     * then reset the object result.
3051     */
3052    
3053     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
3054     TCL_VOLATILE);
3055     }
3056     Tcl_DecrRefCount(exprPtr); /* discard the expression object */
3057     } else {
3058     /*
3059     * An empty string. Just set the result boolean to 0 (false).
3060     */
3061    
3062     *ptr = 0;
3063     }
3064     return result;
3065     }
3066    
3067     /*
3068     *--------------------------------------------------------------
3069     *
3070     * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
3071     *
3072     * Procedures to evaluate an expression in an object and return its
3073     * value in a particular form.
3074     *
3075     * Results:
3076     * Each of the procedures below returns a standard Tcl result
3077     * object. If an error occurs then an error message is left in the
3078     * interpreter's result. Otherwise the value of the expression, in the
3079     * appropriate form, is stored at *ptr. If the expression had a result
3080     * that was incompatible with the desired form then an error is
3081     * returned.
3082     *
3083     * Side effects:
3084     * None.
3085     *
3086     *--------------------------------------------------------------
3087     */
3088    
3089     int
3090     Tcl_ExprLongObj(interp, objPtr, ptr)
3091     Tcl_Interp *interp; /* Context in which to evaluate the
3092     * expression. */
3093     register Tcl_Obj *objPtr; /* Expression to evaluate. */
3094     long *ptr; /* Where to store long result. */
3095     {
3096     Tcl_Obj *resultPtr;
3097     int result;
3098    
3099     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
3100     if (result == TCL_OK) {
3101     if (resultPtr->typePtr == &tclIntType) {
3102     *ptr = resultPtr->internalRep.longValue;
3103     } else if (resultPtr->typePtr == &tclDoubleType) {
3104     *ptr = (long) resultPtr->internalRep.doubleValue;
3105     } else {
3106     result = Tcl_GetLongFromObj(interp, resultPtr, ptr);
3107     if (result != TCL_OK) {
3108     return result;
3109     }
3110     }
3111     Tcl_DecrRefCount(resultPtr); /* discard the result object */
3112     }
3113     return result;
3114     }
3115    
3116     int
3117     Tcl_ExprDoubleObj(interp, objPtr, ptr)
3118     Tcl_Interp *interp; /* Context in which to evaluate the
3119     * expression. */
3120     register Tcl_Obj *objPtr; /* Expression to evaluate. */
3121     double *ptr; /* Where to store double result. */
3122     {
3123     Tcl_Obj *resultPtr;
3124     int result;
3125    
3126     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
3127     if (result == TCL_OK) {
3128     if (resultPtr->typePtr == &tclIntType) {
3129     *ptr = (double) resultPtr->internalRep.longValue;
3130     } else if (resultPtr->typePtr == &tclDoubleType) {
3131     *ptr = resultPtr->internalRep.doubleValue;
3132     } else {
3133     result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
3134     if (result != TCL_OK) {
3135     return result;
3136     }
3137     }
3138     Tcl_DecrRefCount(resultPtr); /* discard the result object */
3139     }
3140     return result;
3141     }
3142    
3143     int
3144     Tcl_ExprBooleanObj(interp, objPtr, ptr)
3145     Tcl_Interp *interp; /* Context in which to evaluate the
3146     * expression. */
3147     register Tcl_Obj *objPtr; /* Expression to evaluate. */
3148     int *ptr; /* Where to store 0/1 result. */
3149     {
3150     Tcl_Obj *resultPtr;
3151     int result;
3152    
3153     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
3154     if (result == TCL_OK) {
3155     if (resultPtr->typePtr == &tclIntType) {
3156     *ptr = (resultPtr->internalRep.longValue != 0);
3157     } else if (resultPtr->typePtr == &tclDoubleType) {
3158     *ptr = (resultPtr->internalRep.doubleValue != 0.0);
3159     } else {
3160     result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
3161     }
3162     Tcl_DecrRefCount(resultPtr); /* discard the result object */
3163     }
3164     return result;
3165     }
3166    
3167     /*
3168     *----------------------------------------------------------------------
3169     *
3170     * TclInvoke --
3171     *
3172     * Invokes a Tcl command, given an argv/argc, from either the
3173     * exposed or the hidden sets of commands in the given interpreter.
3174     * NOTE: The command is invoked in the current stack frame of
3175     * the interpreter, thus it can modify local variables.
3176     *
3177     * Results:
3178     * A standard Tcl result.
3179     *
3180     * Side effects:
3181     * Whatever the command does.
3182     *
3183     *----------------------------------------------------------------------
3184     */
3185    
3186     int
3187     TclInvoke(interp, argc, argv, flags)
3188     Tcl_Interp *interp; /* Where to invoke the command. */
3189     int argc; /* Count of args. */
3190     register char **argv; /* The arg strings; argv[0] is the name of
3191     * the command to invoke. */
3192     int flags; /* Combination of flags controlling the
3193     * call: TCL_INVOKE_HIDDEN and
3194     * TCL_INVOKE_NO_UNKNOWN. */
3195     {
3196     register Tcl_Obj *objPtr;
3197     register int i;
3198     int length, result;
3199    
3200     /*
3201     * This procedure generates an objv array for object arguments that hold
3202     * the argv strings. It starts out with stack-allocated space but uses
3203     * dynamically-allocated storage if needed.
3204     */
3205    
3206     #define NUM_ARGS 20
3207     Tcl_Obj *(objStorage[NUM_ARGS]);
3208     register Tcl_Obj **objv = objStorage;
3209    
3210     /*
3211     * Create the object argument array "objv". Make sure objv is large
3212     * enough to hold the objc arguments plus 1 extra for the zero
3213     * end-of-objv word.
3214     */
3215    
3216     if ((argc + 1) > NUM_ARGS) {
3217     objv = (Tcl_Obj **)
3218     ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
3219     }
3220    
3221     for (i = 0; i < argc; i++) {
3222     length = strlen(argv[i]);
3223     objv[i] = Tcl_NewStringObj(argv[i], length);
3224     Tcl_IncrRefCount(objv[i]);
3225     }
3226     objv[argc] = 0;
3227    
3228     /*
3229     * Use TclObjInterpProc to actually invoke the command.
3230     */
3231    
3232     result = TclObjInvoke(interp, argc, objv, flags);
3233    
3234     /*
3235     * Move the interpreter's object result to the string result,
3236     * then reset the object result.
3237     */
3238    
3239     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
3240     TCL_VOLATILE);
3241    
3242     /*
3243     * Decrement the ref counts on the objv elements since we are done
3244     * with them.
3245     */
3246    
3247     for (i = 0; i < argc; i++) {
3248     objPtr = objv[i];
3249     Tcl_DecrRefCount(objPtr);
3250     }
3251    
3252     /*
3253     * Free the objv array if malloc'ed storage was used.
3254     */
3255    
3256     if (objv != objStorage) {
3257     ckfree((char *) objv);
3258     }
3259     return result;
3260     #undef NUM_ARGS
3261     }
3262    
3263     /*
3264     *----------------------------------------------------------------------
3265     *
3266     * TclGlobalInvoke --
3267     *
3268     * Invokes a Tcl command, given an argv/argc, from either the
3269     * exposed or hidden sets of commands in the given interpreter.
3270     * NOTE: The command is invoked in the global stack frame of
3271     * the interpreter, thus it cannot see any current state on
3272     * the stack for that interpreter.
3273     *
3274     * Results:
3275     * A standard Tcl result.
3276     *
3277     * Side effects:
3278     * Whatever the command does.
3279     *
3280     *----------------------------------------------------------------------
3281     */
3282    
3283     int
3284     TclGlobalInvoke(interp, argc, argv, flags)
3285     Tcl_Interp *interp; /* Where to invoke the command. */
3286     int argc; /* Count of args. */
3287     register char **argv; /* The arg strings; argv[0] is the name of
3288     * the command to invoke. */
3289     int flags; /* Combination of flags controlling the
3290     * call: TCL_INVOKE_HIDDEN and
3291     * TCL_INVOKE_NO_UNKNOWN. */
3292     {
3293     register Interp *iPtr = (Interp *) interp;
3294     int result;
3295     CallFrame *savedVarFramePtr;
3296    
3297     savedVarFramePtr = iPtr->varFramePtr;
3298     iPtr->varFramePtr = NULL;
3299     result = TclInvoke(interp, argc, argv, flags);
3300     iPtr->varFramePtr = savedVarFramePtr;
3301     return result;
3302     }
3303    
3304     /*
3305     *----------------------------------------------------------------------
3306     *
3307     * TclObjInvokeGlobal --
3308     *
3309     * Object version: Invokes a Tcl command, given an objv/objc, from
3310     * either the exposed or hidden set of commands in the given
3311     * interpreter.
3312     * NOTE: The command is invoked in the global stack frame of the
3313     * interpreter, thus it cannot see any current state on the
3314     * stack of that interpreter.
3315     *
3316     * Results:
3317     * A standard Tcl result.
3318     *
3319     * Side effects:
3320     * Whatever the command does.
3321     *
3322     *----------------------------------------------------------------------
3323     */
3324    
3325     int
3326     TclObjInvokeGlobal(interp, objc, objv, flags)
3327     Tcl_Interp *interp; /* Interpreter in which command is to be
3328     * invoked. */
3329     int objc; /* Count of arguments. */
3330     Tcl_Obj *CONST objv[]; /* Argument objects; objv[0] points to the
3331     * name of the command to invoke. */
3332     int flags; /* Combination of flags controlling the
3333     * call: TCL_INVOKE_HIDDEN,
3334     * TCL_INVOKE_NO_UNKNOWN, or
3335     * TCL_INVOKE_NO_TRACEBACK. */
3336     {
3337     register Interp *iPtr = (Interp *) interp;
3338     int result;
3339     CallFrame *savedVarFramePtr;
3340    
3341     savedVarFramePtr = iPtr->varFramePtr;
3342     iPtr->varFramePtr = NULL;
3343     result = TclObjInvoke(interp, objc, objv, flags);
3344     iPtr->varFramePtr = savedVarFramePtr;
3345     return result;
3346     }
3347    
3348     /*
3349     *----------------------------------------------------------------------
3350     *
3351     * TclObjInvoke --
3352     *
3353     * Invokes a Tcl command, given an objv/objc, from either the
3354     * exposed or the hidden sets of commands in the given interpreter.
3355     *
3356     * Results:
3357     * A standard Tcl object result.
3358     *
3359     * Side effects:
3360     * Whatever the command does.
3361     *
3362     *----------------------------------------------------------------------
3363     */
3364    
3365     int
3366     TclObjInvoke(interp, objc, objv, flags)
3367     Tcl_Interp *interp; /* Interpreter in which command is to be
3368     * invoked. */
3369     int objc; /* Count of arguments. */
3370     Tcl_Obj *CONST objv[]; /* Argument objects; objv[0] points to the
3371     * name of the command to invoke. */
3372     int flags; /* Combination of flags controlling the
3373     * call: TCL_INVOKE_HIDDEN,
3374     * TCL_INVOKE_NO_UNKNOWN, or
3375     * TCL_INVOKE_NO_TRACEBACK. */
3376     {
3377     register Interp *iPtr = (Interp *) interp;
3378     Tcl_HashTable *hTblPtr; /* Table of hidden commands. */
3379     char *cmdName; /* Name of the command from objv[0]. */
3380     register Tcl_HashEntry *hPtr;
3381     Tcl_Command cmd;
3382     Command *cmdPtr;
3383     int localObjc; /* Used to invoke "unknown" if the */
3384     Tcl_Obj **localObjv = NULL; /* command is not found. */
3385     register int i;
3386     int length, result;
3387     char *bytes;
3388    
3389     if (interp == (Tcl_Interp *) NULL) {
3390     return TCL_ERROR;
3391     }
3392    
3393     if ((objc < 1) || (objv == (Tcl_Obj **) NULL)) {
3394     Tcl_AppendToObj(Tcl_GetObjResult(interp),
3395     "illegal argument vector", -1);
3396     return TCL_ERROR;
3397     }
3398    
3399     cmdName = Tcl_GetString(objv[0]);
3400     if (flags & TCL_INVOKE_HIDDEN) {
3401     /*
3402     * We never invoke "unknown" for hidden commands.
3403     */
3404    
3405     hPtr = NULL;
3406     hTblPtr = ((Interp *) interp)->hiddenCmdTablePtr;
3407     if (hTblPtr != NULL) {
3408     hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
3409     }
3410     if (hPtr == NULL) {
3411     Tcl_ResetResult(interp);
3412     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
3413     "invalid hidden command name \"", cmdName, "\"",
3414     (char *) NULL);
3415     return TCL_ERROR;
3416     }
3417     cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
3418     } else {
3419     cmdPtr = NULL;
3420     cmd = Tcl_FindCommand(interp, cmdName,
3421     (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
3422     if (cmd != (Tcl_Command) NULL) {
3423     cmdPtr = (Command *) cmd;
3424     }
3425     if (cmdPtr == NULL) {
3426     if (!(flags & TCL_INVOKE_NO_UNKNOWN)) {
3427     cmd = Tcl_FindCommand(interp, "unknown",
3428     (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
3429     if (cmd != (Tcl_Command) NULL) {
3430     cmdPtr = (Command *) cmd;
3431     }
3432     if (cmdPtr != NULL) {
3433     localObjc = (objc + 1);
3434     localObjv = (Tcl_Obj **)
3435     ckalloc((unsigned) (sizeof(Tcl_Obj *) * localObjc));
3436     localObjv[0] = Tcl_NewStringObj("unknown", -1);
3437     Tcl_IncrRefCount(localObjv[0]);
3438     for (i = 0; i < objc; i++) {
3439     localObjv[i+1] = objv[i];
3440     }
3441     objc = localObjc;
3442     objv = localObjv;
3443     }
3444     }
3445    
3446     /*
3447     * Check again if we found the command. If not, "unknown" is
3448     * not present and we cannot help, or the caller said not to
3449     * call "unknown" (they specified TCL_INVOKE_NO_UNKNOWN).
3450     */
3451    
3452     if (cmdPtr == NULL) {
3453     Tcl_ResetResult(interp);
3454     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
3455     "invalid command name \"", cmdName, "\"",
3456     (char *) NULL);
3457     return TCL_ERROR;
3458     }
3459     }
3460     }
3461    
3462     /*
3463     * Invoke the command procedure. First reset the interpreter's string
3464     * and object results to their default empty values since they could
3465     * have gotten changed by earlier invocations.
3466     */
3467    
3468     Tcl_ResetResult(interp);
3469     iPtr->cmdCount++;
3470     result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
3471    
3472     /*
3473     * If an error occurred, record information about what was being
3474     * executed when the error occurred.
3475     */
3476    
3477     if ((result == TCL_ERROR)
3478     && ((flags & TCL_INVOKE_NO_TRACEBACK) == 0)
3479     && ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
3480     Tcl_DString ds;
3481    
3482     Tcl_DStringInit(&ds);
3483     if (!(iPtr->flags & ERR_IN_PROGRESS)) {
3484     Tcl_DStringAppend(&ds, "\n while invoking\n\"", -1);
3485     } else {
3486     Tcl_DStringAppend(&ds, "\n invoked from within\n\"", -1);
3487     }
3488     for (i = 0; i < objc; i++) {
3489     bytes = Tcl_GetStringFromObj(objv[i], &length);
3490     Tcl_DStringAppend(&ds, bytes, length);
3491     if (i < (objc - 1)) {
3492     Tcl_DStringAppend(&ds, " ", -1);
3493     } else if (Tcl_DStringLength(&ds) > 100) {
3494     Tcl_DStringSetLength(&ds, 100);
3495     Tcl_DStringAppend(&ds, "...", -1);
3496     break;
3497     }
3498     }
3499    
3500     Tcl_DStringAppend(&ds, "\"", -1);
3501     Tcl_AddObjErrorInfo(interp, Tcl_DStringValue(&ds), -1);
3502     Tcl_DStringFree(&ds);
3503     iPtr->flags &= ~ERR_ALREADY_LOGGED;
3504     }
3505    
3506     /*
3507     * Free any locally allocated storage used to call "unknown".
3508     */
3509    
3510     if (localObjv != (Tcl_Obj **) NULL) {
3511     Tcl_DecrRefCount(localObjv[0]);
3512     ckfree((char *) localObjv);
3513     }
3514     return result;
3515     }
3516    
3517     /*
3518     *---------------------------------------------------------------------------
3519     *
3520     * Tcl_ExprString --
3521     *
3522     * Evaluate an expression in a string and return its value in string
3523     * form.
3524     *
3525     * Results:
3526     * A standard Tcl result. If the result is TCL_OK, then the interp's
3527     * result is set to the string value of the expression. If the result
3528     * is TCL_ERROR, then the interp's result contains an error message.
3529     *
3530     * Side effects:
3531     * A Tcl object is allocated to hold a copy of the expression string.
3532     * This expression object is passed to Tcl_ExprObj and then
3533     * deallocated.
3534     *
3535     *---------------------------------------------------------------------------
3536     */
3537    
3538     int
3539     Tcl_ExprString(interp, string)
3540     Tcl_Interp *interp; /* Context in which to evaluate the
3541     * expression. */
3542     char *string; /* Expression to evaluate. */
3543     {
3544     register Tcl_Obj *exprPtr;
3545     Tcl_Obj *resultPtr;
3546     int length = strlen(string);
3547     char buf[TCL_DOUBLE_SPACE];
3548     int result = TCL_OK;
3549    
3550     if (length > 0) {
3551     TclNewObj(exprPtr);
3552     TclInitStringRep(exprPtr, string, length);
3553     Tcl_IncrRefCount(exprPtr);
3554    
3555     result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
3556     if (result == TCL_OK) {
3557     /*
3558     * Set the interpreter's string result from the result object.
3559     */
3560    
3561     if (resultPtr->typePtr == &tclIntType) {
3562     sprintf(buf, "%ld", resultPtr->internalRep.longValue);
3563     Tcl_SetResult(interp, buf, TCL_VOLATILE);
3564     } else if (resultPtr->typePtr == &tclDoubleType) {
3565     Tcl_PrintDouble((Tcl_Interp *) NULL,
3566     resultPtr->internalRep.doubleValue, buf);
3567     Tcl_SetResult(interp, buf, TCL_VOLATILE);
3568     } else {
3569     /*
3570     * Set interpreter's string result from the result object.
3571     */
3572    
3573     Tcl_SetResult(interp, TclGetString(resultPtr),
3574     TCL_VOLATILE);
3575     }
3576     Tcl_DecrRefCount(resultPtr); /* discard the result object */
3577     } else {
3578     /*
3579     * Move the interpreter's object result to the string result,
3580     * then reset the object result.
3581     */
3582    
3583     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
3584     TCL_VOLATILE);
3585     }
3586     Tcl_DecrRefCount(exprPtr); /* discard the expression object */
3587     } else {
3588     /*
3589     * An empty string. Just set the interpreter's result to 0.
3590     */
3591    
3592     Tcl_SetResult(interp, "0", TCL_VOLATILE);
3593     }
3594     return result;
3595     }
3596    
3597     /*
3598     *--------------------------------------------------------------
3599     *
3600     * Tcl_ExprObj --
3601     *
3602     * Evaluate an expression in a Tcl_Obj.
3603     *
3604     * Results:
3605     * A standard Tcl object result. If the result is other than TCL_OK,
3606     * then the interpreter's result contains an error message. If the
3607     * result is TCL_OK, then a pointer to the expression's result value
3608     * object is stored in resultPtrPtr. In that case, the object's ref
3609     * count is incremented to reflect the reference returned to the
3610     * caller; the caller is then responsible for the resulting object
3611     * and must, for example, decrement the ref count when it is finished
3612     * with the object.
3613     *
3614     * Side effects:
3615     * Any side effects caused by subcommands in the expression, if any.
3616     * The interpreter result is not modified unless there is an error.
3617     *
3618     *--------------------------------------------------------------
3619     */
3620    
3621     int
3622     Tcl_ExprObj(interp, objPtr, resultPtrPtr)
3623     Tcl_Interp *interp; /* Context in which to evaluate the
3624     * expression. */
3625     register Tcl_Obj *objPtr; /* Points to Tcl object containing
3626     * expression to evaluate. */
3627     Tcl_Obj **resultPtrPtr; /* Where the Tcl_Obj* that is the expression
3628     * result is stored if no errors occur. */
3629     {
3630     Interp *iPtr = (Interp *) interp;
3631     CompileEnv compEnv; /* Compilation environment structure
3632     * allocated in frame. */
3633     LiteralTable *localTablePtr = &(compEnv.localLitTable);
3634     register ByteCode *codePtr = NULL;
3635     /* Tcl Internal type of bytecode.
3636     * Initialized to avoid compiler warning. */
3637     AuxData *auxDataPtr;
3638     LiteralEntry *entryPtr;
3639     Tcl_Obj *saveObjPtr;
3640     char *string;
3641     int length, i, result;
3642    
3643     /*
3644     * First handle some common expressions specially.
3645     */
3646    
3647     string = Tcl_GetStringFromObj(objPtr, &length);
3648     if (length == 1) {
3649     if (*string == '0') {
3650     *resultPtrPtr = Tcl_NewLongObj(0);
3651     Tcl_IncrRefCount(*resultPtrPtr);
3652     return TCL_OK;
3653     } else if (*string == '1') {
3654     *resultPtrPtr = Tcl_NewLongObj(1);
3655     Tcl_IncrRefCount(*resultPtrPtr);
3656     return TCL_OK;
3657     }
3658     } else if ((length == 2) && (*string == '!')) {
3659     if (*(string+1) == '0') {
3660     *resultPtrPtr = Tcl_NewLongObj(1);
3661     Tcl_IncrRefCount(*resultPtrPtr);
3662     return TCL_OK;
3663     } else if (*(string+1) == '1') {
3664     *resultPtrPtr = Tcl_NewLongObj(0);
3665     Tcl_IncrRefCount(*resultPtrPtr);
3666     return TCL_OK;
3667     }
3668     }
3669    
3670     /*
3671     * Get the ByteCode from the object. If it exists, make sure it hasn't
3672     * been invalidated by, e.g., someone redefining a command with a
3673     * compile procedure (this might make the compiled code wrong). If
3674     * necessary, convert the object to be a ByteCode object and compile it.
3675     * Also, if the code was compiled in/for a different interpreter, we
3676     * recompile it.
3677     *
3678     * Precompiled expressions, however, are immutable and therefore
3679     * they are not recompiled, even if the epoch has changed.
3680     *
3681     */
3682    
3683     if (objPtr->typePtr == &tclByteCodeType) {
3684     codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
3685     if (((Interp *) *codePtr->interpHandle != iPtr)
3686     || (codePtr->compileEpoch != iPtr->compileEpoch)) {
3687     if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
3688     if ((Interp *) *codePtr->interpHandle != iPtr) {
3689     panic("Tcl_ExprObj: compiled expression jumped interps");
3690     }
3691     codePtr->compileEpoch = iPtr->compileEpoch;
3692     } else {
3693     (*tclByteCodeType.freeIntRepProc)(objPtr);
3694     objPtr->typePtr = (Tcl_ObjType *) NULL;
3695     }
3696     }
3697     }
3698     if (objPtr->typePtr != &tclByteCodeType) {
3699     TclInitCompileEnv(interp, &compEnv, string, length);
3700     result = TclCompileExpr(interp, string, length, &compEnv);
3701    
3702     /*
3703     * Free the compilation environment's literal table bucket array if
3704     * it was dynamically allocated.
3705     */
3706    
3707     if (localTablePtr->buckets != localTablePtr->staticBuckets) {
3708     ckfree((char *) localTablePtr->buckets);
3709     }
3710    
3711     if (result != TCL_OK) {
3712     /*
3713     * Compilation errors. Free storage allocated for compilation.
3714     */
3715    
3716     #ifdef TCL_COMPILE_DEBUG
3717     TclVerifyLocalLiteralTable(&compEnv);
3718     #endif /*TCL_COMPILE_DEBUG*/
3719     entryPtr = compEnv.literalArrayPtr;
3720     for (i = 0; i < compEnv.literalArrayNext; i++) {
3721     TclReleaseLiteral(interp, entryPtr->objPtr);
3722     entryPtr++;
3723     }
3724     #ifdef TCL_COMPILE_DEBUG
3725     TclVerifyGlobalLiteralTable(iPtr);
3726     #endif /*TCL_COMPILE_DEBUG*/
3727    
3728     auxDataPtr = compEnv.auxDataArrayPtr;
3729     for (i = 0; i < compEnv.auxDataArrayNext; i++) {
3730     if (auxDataPtr->type->freeProc != NULL) {
3731     auxDataPtr->type->freeProc(auxDataPtr->clientData);
3732     }
3733     auxDataPtr++;
3734     }
3735     TclFreeCompileEnv(&compEnv);
3736     return result;
3737     }
3738    
3739     /*
3740     * Successful compilation. If the expression yielded no
3741     * instructions, push an zero object as the expression's result.
3742     */
3743    
3744     if (compEnv.codeNext == compEnv.codeStart) {
3745     TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),
3746     &compEnv);
3747     }
3748    
3749     /*
3750     * Add a "done" instruction as the last instruction and change the
3751     * object into a ByteCode object. Ownership of the literal objects
3752     * and aux data items is given to the ByteCode object.
3753     */
3754    
3755     compEnv.numSrcBytes = iPtr->termOffset;
3756     TclEmitOpcode(INST_DONE, &compEnv);
3757     TclInitByteCodeObj(objPtr, &compEnv);
3758     TclFreeCompileEnv(&compEnv);
3759     codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
3760     #ifdef TCL_COMPILE_DEBUG
3761     if (tclTraceCompile == 2) {
3762     TclPrintByteCodeObj(interp, objPtr);
3763     }
3764     #endif /* TCL_COMPILE_DEBUG */
3765     }
3766    
3767     /*
3768     * Execute the expression after first saving the interpreter's result.
3769     */
3770    
3771     saveObjPtr = Tcl_GetObjResult(interp);
3772     Tcl_IncrRefCount(saveObjPtr);
3773     Tcl_ResetResult(interp);
3774    
3775     /*
3776     * Increment the code's ref count while it is being executed. If
3777     * afterwards no references to it remain, free the code.
3778     */
3779    
3780     codePtr->refCount++;
3781     result = TclExecuteByteCode(interp, codePtr);
3782     codePtr->refCount--;
3783     if (codePtr->refCount <= 0) {
3784     TclCleanupByteCode(codePtr);
3785     objPtr->typePtr = NULL;
3786     objPtr->internalRep.otherValuePtr = NULL;
3787     }
3788    
3789     /*
3790     * If the expression evaluated successfully, store a pointer to its
3791     * value object in resultPtrPtr then restore the old interpreter result.
3792     * We increment the object's ref count to reflect the reference that we
3793     * are returning to the caller. We also decrement the ref count of the
3794     * interpreter's result object after calling Tcl_SetResult since we
3795     * next store into that field directly.
3796     */
3797    
3798     if (result == TCL_OK) {
3799     *resultPtrPtr = iPtr->objResultPtr;
3800     Tcl_IncrRefCount(iPtr->objResultPtr);
3801    
3802     Tcl_SetObjResult(interp, saveObjPtr);
3803     }
3804     Tcl_DecrRefCount(saveObjPtr);
3805     return result;
3806     }
3807    
3808     /*
3809     *----------------------------------------------------------------------
3810     *
3811     * Tcl_CreateTrace --
3812     *
3813     * Arrange for a procedure to be called to trace command execution.
3814     *
3815     * Results:
3816     * The return value is a token for the trace, which may be passed
3817     * to Tcl_DeleteTrace to eliminate the trace.
3818     *
3819     * Side effects:
3820     * From now on, proc will be called just before a command procedure
3821     * is called to execute a Tcl command. Calls to proc will have the
3822     * following form:
3823     *
3824     * void
3825     * proc(clientData, interp, level, command, cmdProc, cmdClientData,
3826     * argc, argv)
3827     * ClientData clientData;
3828     * Tcl_Interp *interp;
3829     * int level;
3830     * char *command;
3831     * int (*cmdProc)();
3832     * ClientData cmdClientData;
3833     * int argc;
3834     * char **argv;
3835     * {
3836     * }
3837     *
3838     * The clientData and interp arguments to proc will be the same
3839     * as the corresponding arguments to this procedure. Level gives
3840     * the nesting level of command interpretation for this interpreter
3841     * (0 corresponds to top level). Command gives the ASCII text of
3842     * the raw command, cmdProc and cmdClientData give the procedure that
3843     * will be called to process the command and the ClientData value it
3844     * will receive, and argc and argv give the arguments to the
3845     * command, after any argument parsing and substitution. Proc
3846     * does not return a value.
3847     *
3848     *----------------------------------------------------------------------
3849     */
3850    
3851     Tcl_Trace
3852     Tcl_CreateTrace(interp, level, proc, clientData)
3853     Tcl_Interp *interp; /* Interpreter in which to create trace. */
3854     int level; /* Only call proc for commands at nesting
3855     * level<=argument level (1=>top level). */
3856     Tcl_CmdTraceProc *proc; /* Procedure to call before executing each
3857     * command. */
3858     ClientData clientData; /* Arbitrary value word to pass to proc. */
3859     {
3860     register Trace *tracePtr;
3861     register Interp *iPtr = (Interp *) interp;
3862    
3863     /*
3864     * Invalidate existing compiled code for this interpreter and arrange
3865     * (by setting the DONT_COMPILE_CMDS_INLINE flag) that when compiling
3866     * new code, no commands will be compiled inline (i.e., into an inline
3867     * sequence of instructions). We do this because commands that were
3868     * compiled inline will never result in a command trace being called.
3869     */
3870    
3871     iPtr->compileEpoch++;
3872     iPtr->flags |= DONT_COMPILE_CMDS_INLINE;
3873    
3874     tracePtr = (Trace *) ckalloc(sizeof(Trace));
3875     tracePtr->level = level;
3876     tracePtr->proc = proc;
3877     tracePtr->clientData = clientData;
3878     tracePtr->nextPtr = iPtr->tracePtr;
3879     iPtr->tracePtr = tracePtr;
3880    
3881     return (Tcl_Trace) tracePtr;
3882     }
3883    
3884     /*
3885     *----------------------------------------------------------------------
3886     *
3887     * Tcl_DeleteTrace --
3888     *
3889     * Remove a trace.
3890     *
3891     * Results:
3892     * None.
3893     *
3894     * Side effects:
3895     * From now on there will be no more calls to the procedure given
3896     * in trace.
3897     *
3898     *----------------------------------------------------------------------
3899     */
3900    
3901     void
3902     Tcl_DeleteTrace(interp, trace)
3903     Tcl_Interp *interp; /* Interpreter that contains trace. */
3904     Tcl_Trace trace; /* Token for trace (returned previously by
3905     * Tcl_CreateTrace). */
3906     {
3907     register Interp *iPtr = (Interp *) interp;
3908     register Trace *tracePtr = (Trace *) trace;
3909     register Trace *tracePtr2;
3910    
3911     if (iPtr->tracePtr == tracePtr) {
3912     iPtr->tracePtr = tracePtr->nextPtr;
3913     ckfree((char *) tracePtr);
3914     } else {
3915     for (tracePtr2 = iPtr->tracePtr; tracePtr2 != NULL;
3916     tracePtr2 = tracePtr2->nextPtr) {
3917     if (tracePtr2->nextPtr == tracePtr) {
3918     tracePtr2->nextPtr = tracePtr->nextPtr;
3919     ckfree((char *) tracePtr);
3920     break;
3921     }
3922     }
3923     }
3924    
3925     if (iPtr->tracePtr == NULL) {
3926     /*
3927     * When compiling new code, allow commands to be compiled inline.
3928     */
3929    
3930     iPtr->flags &= ~DONT_COMPILE_CMDS_INLINE;
3931     }
3932     }
3933    
3934     /*
3935     *----------------------------------------------------------------------
3936     *
3937     * Tcl_AddErrorInfo --
3938     *
3939     * Add information to the "errorInfo" variable that describes the
3940     * current error.
3941     *
3942     * Results:
3943     * None.
3944     *
3945     * Side effects:
3946     * The contents of message are added to the "errorInfo" variable.
3947     * If Tcl_Eval has been called since the current value of errorInfo
3948     * was set, errorInfo is cleared before adding the new message.
3949     * If we are just starting to log an error, errorInfo is initialized
3950     * from the error message in the interpreter's result.
3951     *
3952     *----------------------------------------------------------------------
3953     */
3954    
3955     void
3956     Tcl_AddErrorInfo(interp, message)
3957     Tcl_Interp *interp; /* Interpreter to which error information
3958     * pertains. */
3959     CONST char *message; /* Message to record. */
3960     {
3961     Tcl_AddObjErrorInfo(interp, message, -1);
3962     }
3963    
3964     /*
3965     *----------------------------------------------------------------------
3966     *
3967     * Tcl_AddObjErrorInfo --
3968     *
3969     * Add information to the "errorInfo" variable that describes the
3970     * current error. This routine differs from Tcl_AddErrorInfo by
3971     * taking a byte pointer and length.
3972     *
3973     * Results:
3974     * None.
3975     *
3976     * Side effects:
3977     * "length" bytes from "message" are added to the "errorInfo" variable.
3978     * If "length" is negative, use bytes up to the first NULL byte.
3979     * If Tcl_EvalObj has been called since the current value of errorInfo
3980     * was set, errorInfo is cleared before adding the new message.
3981     * If we are just starting to log an error, errorInfo is initialized
3982     * from the error message in the interpreter's result.
3983     *
3984     *----------------------------------------------------------------------
3985     */
3986    
3987     void
3988     Tcl_AddObjErrorInfo(interp, message, length)
3989     Tcl_Interp *interp; /* Interpreter to which error information
3990     * pertains. */
3991     CONST char *message; /* Points to the first byte of an array of
3992     * bytes of the message. */
3993     int length; /* The number of bytes in the message.
3994     * If < 0, then append all bytes up to a
3995     * NULL byte. */
3996     {
3997     register Interp *iPtr = (Interp *) interp;
3998     Tcl_Obj *messagePtr;
3999    
4000     /*
4001     * If we are just starting to log an error, errorInfo is initialized
4002     * from the error message in the interpreter's result.
4003     */
4004    
4005     if (!(iPtr->flags & ERR_IN_PROGRESS)) { /* just starting to log error */
4006     iPtr->flags |= ERR_IN_PROGRESS;
4007    
4008     if (iPtr->result[0] == 0) {
4009     (void) Tcl_SetVar2Ex(interp, "errorInfo", NULL, iPtr->objResultPtr,
4010     TCL_GLOBAL_ONLY);
4011     } else { /* use the string result */
4012     Tcl_SetVar2(interp, "errorInfo", (char *) NULL, interp->result,
4013     TCL_GLOBAL_ONLY);
4014     }
4015    
4016     /*
4017     * If the errorCode variable wasn't set by the code that generated
4018     * the error, set it to "NONE".
4019     */
4020    
4021     if (!(iPtr->flags & ERROR_CODE_SET)) {
4022     (void) Tcl_SetVar2(interp, "errorCode", (char *) NULL, "NONE",
4023     TCL_GLOBAL_ONLY);
4024     }
4025     }
4026    
4027     /*
4028     * Now append "message" to the end of errorInfo.
4029     */
4030    
4031     if (length != 0) {
4032     messagePtr = Tcl_NewStringObj(message, length);
4033     Tcl_IncrRefCount(messagePtr);
4034     Tcl_SetVar2Ex(interp, "errorInfo", NULL, messagePtr,
4035     (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE));
4036     Tcl_DecrRefCount(messagePtr); /* free msg object appended above */
4037     }
4038     }
4039    
4040     /*
4041     *---------------------------------------------------------------------------
4042     *
4043     * Tcl_VarEvalVA --
4044     *
4045     * Given a variable number of string arguments, concatenate them
4046     * all together and execute the result as a Tcl command.
4047     *
4048     * Results:
4049     * A standard Tcl return result. An error message or other result may
4050     * be left in the interp's result.
4051     *
4052     * Side effects:
4053     * Depends on what was done by the command.
4054     *
4055     *---------------------------------------------------------------------------
4056     */
4057    
4058     int
4059     Tcl_VarEvalVA (interp, argList)
4060     Tcl_Interp *interp; /* Interpreter in which to evaluate command. */
4061     va_list argList; /* Variable argument list. */
4062     {
4063     Tcl_DString buf;
4064     char *string;
4065     int result;
4066    
4067     /*
4068     * Copy the strings one after the other into a single larger
4069     * string. Use stack-allocated space for small commands, but if
4070     * the command gets too large than call ckalloc to create the
4071     * space.
4072     */
4073    
4074     Tcl_DStringInit(&buf);
4075     while (1) {
4076     string = va_arg(argList, char *);
4077     if (string == NULL) {
4078     break;
4079     }
4080     Tcl_DStringAppend(&buf, string, -1);
4081     }
4082    
4083     result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
4084     Tcl_DStringFree(&buf);
4085     return result;
4086     }
4087    
4088     /*
4089     *----------------------------------------------------------------------
4090     *
4091     * Tcl_VarEval --
4092     *
4093     * Given a variable number of string arguments, concatenate them
4094     * all together and execute the result as a Tcl command.
4095     *
4096     * Results:
4097     * A standard Tcl return result. An error message or other
4098     * result may be left in interp->result.
4099     *
4100     * Side effects:
4101     * Depends on what was done by the command.
4102     *
4103     *----------------------------------------------------------------------
4104     */
4105     /* VARARGS2 */ /* ARGSUSED */
4106     int
4107     Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1)
4108     {
4109     Tcl_Interp *interp;
4110     va_list argList;
4111     int result;
4112    
4113     interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
4114     result = Tcl_VarEvalVA(interp, argList);
4115     va_end(argList);
4116    
4117     return result;
4118     }
4119    
4120     /*
4121     *---------------------------------------------------------------------------
4122     *
4123     * Tcl_GlobalEval --
4124     *
4125     * Evaluate a command at global level in an interpreter.
4126     *
4127     * Results:
4128     * A standard Tcl result is returned, and the interp's result is
4129     * modified accordingly.
4130     *
4131     * Side effects:
4132     * The command string is executed in interp, and the execution
4133     * is carried out in the variable context of global level (no
4134     * procedures active), just as if an "uplevel #0" command were
4135     * being executed.
4136     *
4137     ---------------------------------------------------------------------------
4138     */
4139    
4140     int
4141     Tcl_GlobalEval(interp, command)
4142     Tcl_Interp *interp; /* Interpreter in which to evaluate command. */
4143     char *command; /* Command to evaluate. */
4144     {
4145     register Interp *iPtr = (Interp *) interp;
4146     int result;
4147     CallFrame *savedVarFramePtr;
4148    
4149     savedVarFramePtr = iPtr->varFramePtr;
4150     iPtr->varFramePtr = NULL;
4151     result = Tcl_Eval(interp, command);
4152     iPtr->varFramePtr = savedVarFramePtr;
4153     return result;
4154     }
4155    
4156     /*
4157     *----------------------------------------------------------------------
4158     *
4159     * Tcl_SetRecursionLimit --
4160     *
4161     * Set the maximum number of recursive calls that may be active
4162     * for an interpreter at once.
4163     *
4164     * Results:
4165     * The return value is the old limit on nesting for interp.
4166     *
4167     * Side effects:
4168     * None.
4169     *
4170     *----------------------------------------------------------------------
4171     */
4172    
4173     int
4174     Tcl_SetRecursionLimit(interp, depth)
4175     Tcl_Interp *interp; /* Interpreter whose nesting limit
4176     * is to be set. */
4177     int depth; /* New value for maximimum depth. */
4178     {
4179     Interp *iPtr = (Interp *) interp;
4180     int old;
4181    
4182     old = iPtr->maxNestingDepth;
4183     if (depth > 0) {
4184     iPtr->maxNestingDepth = depth;
4185     }
4186     return old;
4187     }
4188    
4189     /*
4190     *----------------------------------------------------------------------
4191     *
4192     * Tcl_AllowExceptions --
4193     *
4194     * Sets a flag in an interpreter so that exceptions can occur
4195     * in the next call to Tcl_Eval without them being turned into
4196     * errors.
4197     *
4198     * Results:
4199     * None.
4200     *
4201     * Side effects:
4202     * The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's
4203     * evalFlags structure. See the reference documentation for
4204     * more details.
4205     *
4206     *----------------------------------------------------------------------
4207     */
4208    
4209     void
4210     Tcl_AllowExceptions(interp)
4211     Tcl_Interp *interp; /* Interpreter in which to set flag. */
4212     {
4213     Interp *iPtr = (Interp *) interp;
4214    
4215     iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS;
4216     }
4217    
4218    
4219     /*
4220     *----------------------------------------------------------------------
4221     *
4222     * Tcl_GetVersion
4223     *
4224     * Get the Tcl major, minor, and patchlevel version numbers and
4225     * the release type. A patch is a release type TCL_FINAL_RELEASE
4226     * with a patchLevel > 0.
4227     *
4228     * Results:
4229     * None.
4230     *
4231     * Side effects:
4232     * None.
4233     *
4234     *----------------------------------------------------------------------
4235     */
4236    
4237     void Tcl_GetVersion(majorV, minorV, patchLevelV, type)
4238     int *majorV;
4239     int *minorV;
4240     int *patchLevelV;
4241     int *type;
4242     {
4243     if (majorV != NULL) {
4244     *majorV = TCL_MAJOR_VERSION;
4245     }
4246     if (minorV != NULL) {
4247     *minorV = TCL_MINOR_VERSION;
4248     }
4249     if (patchLevelV != NULL) {
4250     *patchLevelV = TCL_RELEASE_SERIAL;
4251     }
4252     if (type != NULL) {
4253     *type = TCL_RELEASE_LEVEL;
4254     }
4255     }
4256    
4257    
4258     /* $History: tclbasic.c $
4259     *
4260     * ***************** Version 1 *****************
4261     * User: Dtashley Date: 1/02/01 Time: 1:34a
4262     * Created in $/IjuScripter, IjuConsole/Source/Tcl Base
4263     * Initial check-in.
4264     */
4265    
4266     /* End of TCLBASIC.C */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25