Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/generic/tclBasic.c @ 35

Last change on this file since 35 was 25, checked in by landauf, 17 years ago

added tcl to libs

File size: 182.6 KB
RevLine 
[25]1/*
2 * tclBasic.c --
3 *
4 *      Contains the basic facilities for TCL command interpretation,
5 *      including interpreter creation and deletion, command creation and
6 *      deletion, and command/script execution.
7 *
8 * Copyright (c) 1987-1994 The Regents of the University of California.
9 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10 * Copyright (c) 1998-1999 by Scriptics Corporation.
11 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
12 * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
13 *
14 * See the file "license.terms" for information on usage and redistribution of
15 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 *
17 * RCS: @(#) $Id: tclBasic.c,v 1.295 2008/03/14 19:53:10 dgp Exp $
18 */
19
20#include "tclInt.h"
21#include "tclCompile.h"
22#include <float.h>
23#include <limits.h>
24#include <math.h>
25#include "tommath.h"
26
27/*
28 * Determine whether we're using IEEE floating point
29 */
30
31#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
32#   define IEEE_FLOATING_POINT
33/* Largest odd integer that can be represented exactly in a double */
34#   define MAX_EXACT 9007199254740991.0
35#endif
36
37/*
38 * The following structure defines the client data for a math function
39 * registered with Tcl_CreateMathFunc
40 */
41
42typedef struct OldMathFuncData {
43    Tcl_MathProc *proc;         /* Handler function */
44    int numArgs;                /* Number of args expected */
45    Tcl_ValueType *argTypes;    /* Types of the args */
46    ClientData clientData;      /* Client data for the handler function */
47} OldMathFuncData;
48
49/*
50 * Static functions in this file:
51 */
52
53static char *   CallCommandTraces(Interp *iPtr, Command *cmdPtr,
54                    const char *oldName, const char *newName, int flags);
55static int      CheckDoubleResult(Tcl_Interp *interp, double dResult);
56static void     DeleteInterpProc(Tcl_Interp *interp);
57static void     DeleteOpCmdClientData(ClientData clientData);
58static Tcl_Obj *GetCommandSource(Interp *iPtr, const char *command,
59                    int numChars, int objc, Tcl_Obj *const objv[]);
60static void     ProcessUnexpectedResult(Tcl_Interp *interp, int returnCode);
61static int      OldMathFuncProc(ClientData clientData, Tcl_Interp *interp,
62                    int argc, Tcl_Obj *const *objv);
63static void     OldMathFuncDeleteProc(ClientData clientData);
64static int      ExprAbsFunc(ClientData clientData, Tcl_Interp *interp,
65                    int argc, Tcl_Obj *const *objv);
66static int      ExprBinaryFunc(ClientData clientData, Tcl_Interp *interp,
67                    int argc, Tcl_Obj *const *objv);
68static int      ExprBoolFunc(ClientData clientData, Tcl_Interp *interp,
69                    int argc, Tcl_Obj *const *objv);
70static int      ExprCeilFunc(ClientData clientData, Tcl_Interp *interp,
71                    int argc, Tcl_Obj *const *objv);
72static int      ExprDoubleFunc(ClientData clientData, Tcl_Interp *interp,
73                    int argc, Tcl_Obj *const *objv);
74static int      ExprEntierFunc(ClientData clientData, Tcl_Interp *interp,
75                    int argc, Tcl_Obj *const *objv);
76static int      ExprFloorFunc(ClientData clientData, Tcl_Interp *interp,
77                    int argc, Tcl_Obj *const *objv);
78static int      ExprIntFunc(ClientData clientData, Tcl_Interp *interp,
79                    int argc, Tcl_Obj *const *objv);
80static int      ExprIsqrtFunc(ClientData clientData, Tcl_Interp *interp,
81                    int argc, Tcl_Obj *const *objv);
82static int      ExprRandFunc(ClientData clientData, Tcl_Interp *interp,
83                    int argc, Tcl_Obj *const *objv);
84static int      ExprRoundFunc(ClientData clientData, Tcl_Interp *interp,
85                    int argc, Tcl_Obj *const *objv);
86static int      ExprSqrtFunc(ClientData clientData, Tcl_Interp *interp,
87                    int argc, Tcl_Obj *const *objv);
88static int      ExprSrandFunc(ClientData clientData, Tcl_Interp *interp,
89                    int argc, Tcl_Obj *const *objv);
90static int      ExprUnaryFunc(ClientData clientData, Tcl_Interp *interp,
91                    int argc, Tcl_Obj *const *objv);
92static int      ExprWideFunc(ClientData clientData, Tcl_Interp *interp,
93                    int argc, Tcl_Obj *const *objv);
94static void     MathFuncWrongNumArgs(Tcl_Interp *interp, int expected,
95                    int actual, Tcl_Obj *const *objv);
96#ifdef USE_DTRACE
97static int      DTraceObjCmd(ClientData dummy, Tcl_Interp *interp, int objc,
98                    Tcl_Obj *const objv[]);
99#endif
100
101extern TclStubs tclStubs;
102
103/*
104 * The following structure define the commands in the Tcl core.
105 */
106
107typedef struct {
108    const char *name;           /* Name of object-based command. */
109    Tcl_ObjCmdProc *objProc;    /* Object-based function for command. */
110    CompileProc *compileProc;   /* Function called to compile command. */
111    int isSafe;                 /* If non-zero, command will be present in
112                                 * safe interpreter. Otherwise it will be
113                                 * hidden. */
114} CmdInfo;
115
116/*
117 * The built-in commands, and the functions that implement them:
118 */
119
120static const CmdInfo builtInCmds[] = {
121    /*
122     * Commands in the generic core.
123     */
124
125    {"append",          Tcl_AppendObjCmd,       TclCompileAppendCmd,    1},
126    {"apply",           Tcl_ApplyObjCmd,        NULL,                   1},
127    {"array",           Tcl_ArrayObjCmd,        NULL,                   1},
128    {"binary",          Tcl_BinaryObjCmd,       NULL,                   1},
129    {"break",           Tcl_BreakObjCmd,        TclCompileBreakCmd,     1},
130#ifndef EXCLUDE_OBSOLETE_COMMANDS
131    {"case",            Tcl_CaseObjCmd,         NULL,                   1},
132#endif
133    {"catch",           Tcl_CatchObjCmd,        TclCompileCatchCmd,     1},
134    {"concat",          Tcl_ConcatObjCmd,       NULL,                   1},
135    {"continue",        Tcl_ContinueObjCmd,     TclCompileContinueCmd,  1},
136    {"error",           Tcl_ErrorObjCmd,        NULL,                   1},
137    {"eval",            Tcl_EvalObjCmd,         NULL,                   1},
138    {"expr",            Tcl_ExprObjCmd,         TclCompileExprCmd,      1},
139    {"for",             Tcl_ForObjCmd,          TclCompileForCmd,       1},
140    {"foreach",         Tcl_ForeachObjCmd,      TclCompileForeachCmd,   1},
141    {"format",          Tcl_FormatObjCmd,       NULL,                   1},
142    {"global",          Tcl_GlobalObjCmd,       TclCompileGlobalCmd,    1},
143    {"if",              Tcl_IfObjCmd,           TclCompileIfCmd,        1},
144    {"incr",            Tcl_IncrObjCmd,         TclCompileIncrCmd,      1},
145    {"join",            Tcl_JoinObjCmd,         NULL,                   1},
146    {"lappend",         Tcl_LappendObjCmd,      TclCompileLappendCmd,   1},
147    {"lassign",         Tcl_LassignObjCmd,      TclCompileLassignCmd,   1},
148    {"lindex",          Tcl_LindexObjCmd,       TclCompileLindexCmd,    1},
149    {"linsert",         Tcl_LinsertObjCmd,      NULL,                   1},
150    {"list",            Tcl_ListObjCmd,         TclCompileListCmd,      1},
151    {"llength",         Tcl_LlengthObjCmd,      TclCompileLlengthCmd,   1},
152    {"lrange",          Tcl_LrangeObjCmd,       NULL,                   1},
153    {"lrepeat",         Tcl_LrepeatObjCmd,      NULL,                   1},
154    {"lreplace",        Tcl_LreplaceObjCmd,     NULL,                   1},
155    {"lreverse",        Tcl_LreverseObjCmd,     NULL,                   1},
156    {"lsearch",         Tcl_LsearchObjCmd,      NULL,                   1},
157    {"lset",            Tcl_LsetObjCmd,         TclCompileLsetCmd,      1},
158    {"lsort",           Tcl_LsortObjCmd,        NULL,                   1},
159    {"namespace",       Tcl_NamespaceObjCmd,    TclCompileNamespaceCmd, 1},
160    {"package",         Tcl_PackageObjCmd,      NULL,                   1},
161    {"proc",            Tcl_ProcObjCmd,         NULL,                   1},
162    {"regexp",          Tcl_RegexpObjCmd,       TclCompileRegexpCmd,    1},
163    {"regsub",          Tcl_RegsubObjCmd,       NULL,                   1},
164    {"rename",          Tcl_RenameObjCmd,       NULL,                   1},
165    {"return",          Tcl_ReturnObjCmd,       TclCompileReturnCmd,    1},
166    {"scan",            Tcl_ScanObjCmd,         NULL,                   1},
167    {"set",             Tcl_SetObjCmd,          TclCompileSetCmd,       1},
168    {"split",           Tcl_SplitObjCmd,        NULL,                   1},
169    {"subst",           Tcl_SubstObjCmd,        NULL,                   1},
170    {"switch",          Tcl_SwitchObjCmd,       TclCompileSwitchCmd,    1},
171    {"trace",           Tcl_TraceObjCmd,        NULL,                   1},
172    {"unset",           Tcl_UnsetObjCmd,        NULL,                   1},
173    {"uplevel",         Tcl_UplevelObjCmd,      NULL,                   1},
174    {"upvar",           Tcl_UpvarObjCmd,        TclCompileUpvarCmd,     1},
175    {"variable",        Tcl_VariableObjCmd,     TclCompileVariableCmd,  1},
176    {"while",           Tcl_WhileObjCmd,        TclCompileWhileCmd,     1},
177
178    /*
179     * Commands in the OS-interface. Note that many of these are unsafe.
180     */
181
182    {"after",           Tcl_AfterObjCmd,        NULL,                   1},
183    {"cd",              Tcl_CdObjCmd,           NULL,                   0},
184    {"close",           Tcl_CloseObjCmd,        NULL,                   1},
185    {"eof",             Tcl_EofObjCmd,          NULL,                   1},
186    {"encoding",        Tcl_EncodingObjCmd,     NULL,                   0},
187    {"exec",            Tcl_ExecObjCmd,         NULL,                   0},
188    {"exit",            Tcl_ExitObjCmd,         NULL,                   0},
189    {"fblocked",        Tcl_FblockedObjCmd,     NULL,                   1},
190    {"fconfigure",      Tcl_FconfigureObjCmd,   NULL,                   0},
191    {"fcopy",           Tcl_FcopyObjCmd,        NULL,                   1},
192    {"file",            Tcl_FileObjCmd,         NULL,                   0},
193    {"fileevent",       Tcl_FileEventObjCmd,    NULL,                   1},
194    {"flush",           Tcl_FlushObjCmd,        NULL,                   1},
195    {"gets",            Tcl_GetsObjCmd,         NULL,                   1},
196    {"glob",            Tcl_GlobObjCmd,         NULL,                   0},
197    {"load",            Tcl_LoadObjCmd,         NULL,                   0},
198    {"open",            Tcl_OpenObjCmd,         NULL,                   0},
199    {"pid",             Tcl_PidObjCmd,          NULL,                   1},
200    {"puts",            Tcl_PutsObjCmd,         NULL,                   1},
201    {"pwd",             Tcl_PwdObjCmd,          NULL,                   0},
202    {"read",            Tcl_ReadObjCmd,         NULL,                   1},
203    {"seek",            Tcl_SeekObjCmd,         NULL,                   1},
204    {"socket",          Tcl_SocketObjCmd,       NULL,                   0},
205    {"source",          Tcl_SourceObjCmd,       NULL,                   0},
206    {"tell",            Tcl_TellObjCmd,         NULL,                   1},
207    {"time",            Tcl_TimeObjCmd,         NULL,                   1},
208    {"unload",          Tcl_UnloadObjCmd,       NULL,                   0},
209    {"update",          Tcl_UpdateObjCmd,       NULL,                   1},
210    {"vwait",           Tcl_VwaitObjCmd,        NULL,                   1},
211    {NULL,              NULL,                   NULL,                   0}
212};
213
214/*
215 * Math functions. All are safe.
216 */
217
218typedef struct {
219    const char *name;           /* Name of the function. The full name is
220                                 * "::tcl::mathfunc::<name>".  */
221    Tcl_ObjCmdProc *objCmdProc; /* Function that evaluates the function */
222    ClientData clientData;      /* Client data for the function */
223} BuiltinFuncDef;
224static const BuiltinFuncDef BuiltinFuncTable[] = {
225    { "abs",    ExprAbsFunc,    NULL                    },
226    { "acos",   ExprUnaryFunc,  (ClientData) acos       },
227    { "asin",   ExprUnaryFunc,  (ClientData) asin       },
228    { "atan",   ExprUnaryFunc,  (ClientData) atan       },
229    { "atan2",  ExprBinaryFunc, (ClientData) atan2      },
230    { "bool",   ExprBoolFunc,   NULL                    },
231    { "ceil",   ExprCeilFunc,   NULL                    },
232    { "cos",    ExprUnaryFunc,  (ClientData) cos        },
233    { "cosh",   ExprUnaryFunc,  (ClientData) cosh       },
234    { "double", ExprDoubleFunc, NULL                    },
235    { "entier", ExprEntierFunc, NULL                    },
236    { "exp",    ExprUnaryFunc,  (ClientData) exp        },
237    { "floor",  ExprFloorFunc,  NULL                    },
238    { "fmod",   ExprBinaryFunc, (ClientData) fmod       },
239    { "hypot",  ExprBinaryFunc, (ClientData) hypot      },
240    { "int",    ExprIntFunc,    NULL                    },
241    { "isqrt",  ExprIsqrtFunc,  NULL                    },
242    { "log",    ExprUnaryFunc,  (ClientData) log        },
243    { "log10",  ExprUnaryFunc,  (ClientData) log10      },
244    { "pow",    ExprBinaryFunc, (ClientData) pow        },
245    { "rand",   ExprRandFunc,   NULL                    },
246    { "round",  ExprRoundFunc,  NULL                    },
247    { "sin",    ExprUnaryFunc,  (ClientData) sin        },
248    { "sinh",   ExprUnaryFunc,  (ClientData) sinh       },
249    { "sqrt",   ExprSqrtFunc,   NULL                    },
250    { "srand",  ExprSrandFunc,  NULL                    },
251    { "tan",    ExprUnaryFunc,  (ClientData) tan        },
252    { "tanh",   ExprUnaryFunc,  (ClientData) tanh       },
253    { "wide",   ExprWideFunc,   NULL                    },
254    { NULL, NULL, NULL }
255};
256
257/*
258 * TIP#174's math operators. All are safe.
259 */
260
261typedef struct {
262    const char *name;           /* Name of object-based command. */
263    Tcl_ObjCmdProc *objProc;    /* Object-based function for command. */
264    CompileProc *compileProc;   /* Function called to compile command. */
265    union {
266        int numArgs;
267        int identity;
268    } i;
269    const char *expected;       /* For error message, what argument(s)
270                                 * were expected. */
271} OpCmdInfo;
272static const OpCmdInfo mathOpCmds[] = {
273    { "~",      TclSingleOpCmd,         TclCompileInvertOpCmd,
274                /* numArgs */ {1},      "integer"},
275    { "!",      TclSingleOpCmd,         TclCompileNotOpCmd,
276                /* numArgs */ {1},      "boolean"},
277    { "+",      TclVariadicOpCmd,       TclCompileAddOpCmd,
278                /* identity */ {0},     NULL},
279    { "*",      TclVariadicOpCmd,       TclCompileMulOpCmd,
280                /* identity */ {1},     NULL},
281    { "&",      TclVariadicOpCmd,       TclCompileAndOpCmd,
282                /* identity */ {-1},    NULL},
283    { "|",      TclVariadicOpCmd,       TclCompileOrOpCmd,
284                /* identity */ {0},     NULL},
285    { "^",      TclVariadicOpCmd,       TclCompileXorOpCmd,
286                /* identity */ {0},     NULL},
287    { "**",     TclVariadicOpCmd,       TclCompilePowOpCmd,
288                /* identity */ {1},     NULL},
289    { "<<",     TclSingleOpCmd,         TclCompileLshiftOpCmd,
290                /* numArgs */ {2},      "integer shift"},
291    { ">>",     TclSingleOpCmd,         TclCompileRshiftOpCmd,
292                /* numArgs */ {2},      "integer shift"},
293    { "%",      TclSingleOpCmd,         TclCompileModOpCmd,
294                /* numArgs */ {2},      "integer integer"},
295    { "!=",     TclSingleOpCmd,         TclCompileNeqOpCmd,
296                /* numArgs */ {2},      "value value"},
297    { "ne",     TclSingleOpCmd,         TclCompileStrneqOpCmd,
298                /* numArgs */ {2},      "value value"},
299    { "in",     TclSingleOpCmd,         TclCompileInOpCmd,
300                /* numArgs */ {2},      "value list"},
301    { "ni",     TclSingleOpCmd,         TclCompileNiOpCmd,
302                /* numArgs */ {2},      "value list"},
303    { "-",      TclNoIdentOpCmd,        TclCompileMinusOpCmd,
304                /* unused */ {0},       "value ?value ...?"},
305    { "/",      TclNoIdentOpCmd,        TclCompileDivOpCmd,
306                /* unused */ {0},       "value ?value ...?"},
307    { "<",      TclSortingOpCmd,        TclCompileLessOpCmd,
308                /* unused */ {0},       NULL},
309    { "<=",     TclSortingOpCmd,        TclCompileLeqOpCmd,
310                /* unused */ {0},       NULL},
311    { ">",      TclSortingOpCmd,        TclCompileGreaterOpCmd,
312                /* unused */ {0},       NULL},
313    { ">=",     TclSortingOpCmd,        TclCompileGeqOpCmd,
314                /* unused */ {0},       NULL},
315    { "==",     TclSortingOpCmd,        TclCompileEqOpCmd,
316                /* unused */ {0},       NULL},
317    { "eq",     TclSortingOpCmd,        TclCompileStreqOpCmd,
318                /* unused */ {0},       NULL},
319    { NULL,     NULL,                   NULL,
320                {0},                    NULL}
321};
322
323/*
324 * Macros for stack checks. The goal of these macros is to allow the size of
325 * the stack to be checked (so preventing overflow) in a *cheap* way. Note
326 * that the check needs to be (amortized) cheap since it is on the critical
327 * path for recursion.
328 */
329
330#if defined(TCL_NO_STACK_CHECK)
331/*
332 * Stack check disabled: make them noops.
333 */
334
335#   define CheckCStack(interp, localIntPtr)     1
336#   define GetCStackParams(iPtr)                /* do nothing */
337#elif defined(TCL_CROSS_COMPILE)
338
339/*
340 * This variable is static and only set *once*, during library initialization.
341 * It therefore needs no thread guards.
342 */
343
344static int stackGrowsDown = 1;
345#   define GetCStackParams(iPtr) \
346    stackGrowsDown = TclpGetCStackParams(&((iPtr)->stackBound))
347#   define CheckCStack(iPtr, localIntPtr) \
348    (stackGrowsDown \
349            ? ((localIntPtr) > (iPtr)->stackBound) \
350            : ((localIntPtr) < (iPtr)->stackBound) \
351    )
352#else /* !TCL_NO_STACK_CHECK && !TCL_CROSS_COMPILE */
353#   define GetCStackParams(iPtr) \
354    TclpGetCStackParams(&((iPtr)->stackBound))
355#   ifdef TCL_STACK_GROWS_UP
356#       define CheckCStack(iPtr, localIntPtr) \
357           (!(iPtr)->stackBound || (localIntPtr) < (iPtr)->stackBound)
358#    else /* TCL_STACK_GROWS_UP */
359#       define CheckCStack(iPtr, localIntPtr) \
360           ((localIntPtr) > (iPtr)->stackBound)
361#    endif /* TCL_STACK_GROWS_UP */
362#endif /* TCL_NO_STACK_CHECK/TCL_CROSS_COMPILE */
363
364/*
365 *----------------------------------------------------------------------
366 *
367 * Tcl_CreateInterp --
368 *
369 *      Create a new TCL command interpreter.
370 *
371 * Results:
372 *      The return value is a token for the interpreter, which may be used in
373 *      calls to functions like Tcl_CreateCmd, Tcl_Eval, or Tcl_DeleteInterp.
374 *
375 * Side effects:
376 *      The command interpreter is initialized with the built-in commands and
377 *      with the variables documented in tclvars(n).
378 *
379 *----------------------------------------------------------------------
380 */
381
382Tcl_Interp *
383Tcl_CreateInterp(void)
384{
385    Interp *iPtr;
386    Tcl_Interp *interp;
387    Command *cmdPtr;
388    const BuiltinFuncDef *builtinFuncPtr;
389    const OpCmdInfo *opcmdInfoPtr;
390    const CmdInfo *cmdInfoPtr;
391    Tcl_Namespace *mathfuncNSPtr, *mathopNSPtr;
392    union {
393        char c[sizeof(short)];
394        short s;
395    } order;
396#ifdef TCL_COMPILE_STATS
397    ByteCodeStats *statsPtr;
398#endif /* TCL_COMPILE_STATS */
399    char mathFuncName[32];
400    CallFrame *framePtr;
401    int result;
402
403    TclInitSubsystems();
404
405    /*
406     * Panic if someone updated the CallFrame structure without also updating
407     * the Tcl_CallFrame structure (or vice versa).
408     */
409
410    if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
411        /*NOTREACHED*/
412        Tcl_Panic("Tcl_CallFrame and CallFrame are not the same size");
413    }
414
415    /*
416     * Initialize support for namespaces and create the global namespace
417     * (whose name is ""; an alias is "::"). This also initializes the Tcl
418     * object type table and other object management code.
419     */
420
421    iPtr = (Interp *) ckalloc(sizeof(Interp));
422    interp = (Tcl_Interp *) iPtr;
423
424    iPtr->result = iPtr->resultSpace;
425    iPtr->freeProc = NULL;
426    iPtr->errorLine = 0;
427    iPtr->objResultPtr = Tcl_NewObj();
428    Tcl_IncrRefCount(iPtr->objResultPtr);
429    iPtr->handle = TclHandleCreate(iPtr);
430    iPtr->globalNsPtr = NULL;
431    iPtr->hiddenCmdTablePtr = NULL;
432    iPtr->interpInfo = NULL;
433
434    iPtr->numLevels = 0;
435    iPtr->maxNestingDepth = MAX_NESTING_DEPTH;
436    iPtr->framePtr = NULL;      /* Initialise as soon as :: is available */
437    iPtr->varFramePtr = NULL;   /* Initialise as soon as :: is available */
438
439    /*
440     * TIP #280 - Initialize the arrays used to extend the ByteCode and
441     * Proc structures.
442     */
443
444    iPtr->cmdFramePtr = NULL;
445    iPtr->linePBodyPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
446    iPtr->lineBCPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
447    Tcl_InitHashTable(iPtr->linePBodyPtr, TCL_ONE_WORD_KEYS);
448    Tcl_InitHashTable(iPtr->lineBCPtr, TCL_ONE_WORD_KEYS);
449
450    iPtr->activeVarTracePtr = NULL;
451
452    iPtr->returnOpts = NULL;
453    iPtr->errorInfo = NULL;
454    TclNewLiteralStringObj(iPtr->eiVar, "::errorInfo");
455    Tcl_IncrRefCount(iPtr->eiVar);
456    iPtr->errorCode = NULL;
457    TclNewLiteralStringObj(iPtr->ecVar, "::errorCode");
458    Tcl_IncrRefCount(iPtr->ecVar);
459    iPtr->returnLevel = 1;
460    iPtr->returnCode = TCL_OK;
461
462    iPtr->rootFramePtr = NULL;  /* Initialise as soon as :: is available */
463    iPtr->lookupNsPtr = NULL;
464
465    iPtr->appendResult = NULL;
466    iPtr->appendAvl = 0;
467    iPtr->appendUsed = 0;
468
469    Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
470    iPtr->packageUnknown = NULL;
471
472    /* TIP #268 */
473    if (getenv("TCL_PKG_PREFER_LATEST") == NULL) {
474        iPtr->packagePrefer = PKG_PREFER_STABLE;
475    } else {
476        iPtr->packagePrefer = PKG_PREFER_LATEST;
477    }
478
479    iPtr->cmdCount = 0;
480    TclInitLiteralTable(&(iPtr->literalTable));
481    iPtr->compileEpoch = 0;
482    iPtr->compiledProcPtr = NULL;
483    iPtr->resolverPtr = NULL;
484    iPtr->evalFlags = 0;
485    iPtr->scriptFile = NULL;
486    iPtr->flags = 0;
487    iPtr->tracePtr = NULL;
488    iPtr->tracesForbiddingInline = 0;
489    iPtr->activeCmdTracePtr = NULL;
490    iPtr->activeInterpTracePtr = NULL;
491    iPtr->assocData = NULL;
492    iPtr->execEnvPtr = NULL;    /* Set after namespaces initialized. */
493    iPtr->emptyObjPtr = Tcl_NewObj();
494                                /* Another empty object. */
495    Tcl_IncrRefCount(iPtr->emptyObjPtr);
496    iPtr->resultSpace[0] = 0;
497    iPtr->threadId = Tcl_GetCurrentThread();
498
499    /*
500     * Initialise the tables for variable traces and searches *before*
501     * creating the global ns - so that the trace on errorInfo can be
502     * recorded.
503     */
504
505    Tcl_InitHashTable(&iPtr->varTraces, TCL_ONE_WORD_KEYS);
506    Tcl_InitHashTable(&iPtr->varSearches, TCL_ONE_WORD_KEYS);
507
508    iPtr->globalNsPtr = NULL;   /* Force creation of global ns below. */
509    iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
510            NULL, NULL);
511    if (iPtr->globalNsPtr == NULL) {
512        Tcl_Panic("Tcl_CreateInterp: can't create global namespace");
513    }
514
515    /*
516     * Initialise the rootCallframe. It cannot be allocated on the stack, as
517     * it has to be in place before TclCreateExecEnv tries to use a variable.
518     */
519
520    /* This is needed to satisfy GCC 3.3's strict aliasing rules */
521    framePtr = (CallFrame *) ckalloc(sizeof(CallFrame));
522    result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
523            (Tcl_Namespace *) iPtr->globalNsPtr, /*isProcCallFrame*/ 0);
524    if (result != TCL_OK) {
525        Tcl_Panic("Tcl_CreateInterp: failed to push the root stack frame");
526    }
527    framePtr->objc = 0;
528
529    iPtr->framePtr = framePtr;
530    iPtr->varFramePtr = framePtr;
531    iPtr->rootFramePtr = framePtr;
532
533    /*
534     * Initialize support for code compilation and execution. We call
535     * TclCreateExecEnv after initializing namespaces since it tries to
536     * reference a Tcl variable (it links to the Tcl "tcl_traceExec"
537     * variable).
538     */
539
540    iPtr->execEnvPtr = TclCreateExecEnv(interp);
541
542    /*
543     * TIP #219, Tcl Channel Reflection API support.
544     */
545
546    iPtr->chanMsg = NULL;
547
548    /*
549     * Initialize the compilation and execution statistics kept for this
550     * interpreter.
551     */
552
553#ifdef TCL_COMPILE_STATS
554    statsPtr = &(iPtr->stats);
555    statsPtr->numExecutions = 0;
556    statsPtr->numCompilations = 0;
557    statsPtr->numByteCodesFreed = 0;
558    (void) memset(statsPtr->instructionCount, 0,
559            sizeof(statsPtr->instructionCount));
560
561    statsPtr->totalSrcBytes = 0.0;
562    statsPtr->totalByteCodeBytes = 0.0;
563    statsPtr->currentSrcBytes = 0.0;
564    statsPtr->currentByteCodeBytes = 0.0;
565    (void) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
566    (void) memset(statsPtr->byteCodeCount, 0, sizeof(statsPtr->byteCodeCount));
567    (void) memset(statsPtr->lifetimeCount, 0, sizeof(statsPtr->lifetimeCount));
568
569    statsPtr->currentInstBytes = 0.0;
570    statsPtr->currentLitBytes = 0.0;
571    statsPtr->currentExceptBytes = 0.0;
572    statsPtr->currentAuxBytes = 0.0;
573    statsPtr->currentCmdMapBytes = 0.0;
574
575    statsPtr->numLiteralsCreated = 0;
576    statsPtr->totalLitStringBytes = 0.0;
577    statsPtr->currentLitStringBytes = 0.0;
578    (void) memset(statsPtr->literalCount, 0, sizeof(statsPtr->literalCount));
579#endif /* TCL_COMPILE_STATS */
580
581    /*
582     * Initialise the stub table pointer.
583     */
584
585    iPtr->stubTable = &tclStubs;
586
587    /*
588     * Initialize the ensemble error message rewriting support.
589     */
590
591    iPtr->ensembleRewrite.sourceObjs = NULL;
592    iPtr->ensembleRewrite.numRemovedObjs = 0;
593    iPtr->ensembleRewrite.numInsertedObjs = 0;
594
595    /*
596     * TIP#143: Initialise the resource limit support.
597     */
598
599    TclInitLimitSupport(interp);
600
601    /*
602     * Initialise the thread-specific data ekeko.
603     */
604
605#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
606    iPtr->allocCache = TclpGetAllocCache();
607#else
608    iPtr->allocCache = NULL;
609#endif
610    iPtr->pendingObjDataPtr = NULL;
611    iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
612
613    /*
614     * Insure that the stack checking mechanism for this interp is
615     * initialized.
616     */
617
618    GetCStackParams(iPtr);
619
620    /*
621     * Create the core commands. Do it here, rather than calling
622     * Tcl_CreateCommand, because it's faster (there's no need to check for a
623     * pre-existing command by the same name). If a command has a Tcl_CmdProc
624     * but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
625     * TclInvokeStringCommand. This is an object-based wrapper function that
626     * extracts strings, calls the string function, and creates an object for
627     * the result. Similarly, if a command has a Tcl_ObjCmdProc but no
628     * Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
629     */
630
631    for (cmdInfoPtr = builtInCmds;  cmdInfoPtr->name != NULL; cmdInfoPtr++) {
632        int isNew;
633        Tcl_HashEntry *hPtr;
634
635        if ((cmdInfoPtr->objProc == NULL)
636                && (cmdInfoPtr->compileProc == NULL)) {
637            Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc");
638        }
639
640        hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
641                cmdInfoPtr->name, &isNew);
642        if (isNew) {
643            cmdPtr = (Command *) ckalloc(sizeof(Command));
644            cmdPtr->hPtr = hPtr;
645            cmdPtr->nsPtr = iPtr->globalNsPtr;
646            cmdPtr->refCount = 1;
647            cmdPtr->cmdEpoch = 0;
648            cmdPtr->compileProc = cmdInfoPtr->compileProc;
649            cmdPtr->proc = TclInvokeObjectCommand;
650            cmdPtr->clientData = cmdPtr;
651            cmdPtr->objProc = cmdInfoPtr->objProc;
652            cmdPtr->objClientData = NULL;
653            cmdPtr->deleteProc = NULL;
654            cmdPtr->deleteData = NULL;
655            cmdPtr->flags = 0;
656            cmdPtr->importRefPtr = NULL;
657            cmdPtr->tracePtr = NULL;
658            Tcl_SetHashValue(hPtr, cmdPtr);
659        }
660    }
661
662    /*
663     * Create the "chan", "dict", "info" and "string" ensembles. Note that all
664     * these commands (and their subcommands that are not present in the
665     * global namespace) are wholly safe.
666     */
667
668    TclInitChanCmd(interp);
669    TclInitDictCmd(interp);
670    TclInitInfoCmd(interp);
671    TclInitStringCmd(interp);
672
673    /*
674     * Register "clock" subcommands. These *do* go through
675     * Tcl_CreateObjCommand, since they aren't in the global namespace and
676     * involve ensembles.
677     */
678
679    TclClockInit(interp);
680
681    /*
682     * Register the built-in functions. This is empty now that they are
683     * implemented as commands in the ::tcl::mathfunc namespace.
684     */
685
686    /*
687     * Register the default [interp bgerror] handler.
688     */
689
690    Tcl_CreateObjCommand(interp, "::tcl::Bgerror",
691            TclDefaultBgErrorHandlerObjCmd, NULL, NULL);
692
693    /*
694     * Create an unsupported command for debugging bytecode.
695     */
696
697    Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble",
698            Tcl_DisassembleObjCmd, NULL, NULL);
699
700#ifdef USE_DTRACE
701    /*
702     * Register the tcl::dtrace command.
703     */
704
705    Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL);
706#endif /* USE_DTRACE */
707
708    /*
709     * Register the builtin math functions.
710     */
711
712    mathfuncNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc", NULL,NULL);
713    if (mathfuncNSPtr == NULL) {
714        Tcl_Panic("Can't create math function namespace");
715    }
716    strcpy(mathFuncName, "::tcl::mathfunc::");
717#define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */
718    for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL;
719            builtinFuncPtr++) {
720        strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
721        Tcl_CreateObjCommand(interp, mathFuncName,
722                builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData, NULL);
723        Tcl_Export(interp, mathfuncNSPtr, builtinFuncPtr->name, 0);
724    }
725
726    /*
727     * Register the mathematical "operator" commands. [TIP #174]
728     */
729
730    mathopNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL);
731#define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */
732    if (mathopNSPtr == NULL) {
733        Tcl_Panic("can't create math operator namespace");
734    }
735    (void) Tcl_Export(interp, mathopNSPtr, "*", 1);
736    strcpy(mathFuncName, "::tcl::mathop::");
737    for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){
738        TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)
739                ckalloc(sizeof(TclOpCmdClientData));
740
741        occdPtr->op = opcmdInfoPtr->name;
742        occdPtr->i.numArgs = opcmdInfoPtr->i.numArgs;
743        occdPtr->expected = opcmdInfoPtr->expected;
744        strcpy(mathFuncName + MATH_OP_PREFIX_LEN, opcmdInfoPtr->name);
745        cmdPtr = (Command *) Tcl_CreateObjCommand(interp, mathFuncName,
746                opcmdInfoPtr->objProc, occdPtr, DeleteOpCmdClientData);
747        if (cmdPtr == NULL) {
748            Tcl_Panic("failed to create math operator %s",
749                    opcmdInfoPtr->name);
750        } else if (opcmdInfoPtr->compileProc != NULL) {
751            cmdPtr->compileProc = opcmdInfoPtr->compileProc;
752        }
753    }
754
755    /*
756     * Do Multiple/Safe Interps Tcl init stuff
757     */
758
759    TclInterpInit(interp);
760    TclSetupEnv(interp);
761
762    /*
763     * TIP #59: Make embedded configuration information available.
764     */
765
766    TclInitEmbeddedConfigurationInformation(interp);
767
768    /*
769     * Compute the byte order of this machine.
770     */
771
772    order.s = 1;
773    Tcl_SetVar2(interp, "tcl_platform", "byteOrder",
774            ((order.c[0] == 1) ? "littleEndian" : "bigEndian"),
775            TCL_GLOBAL_ONLY);
776
777    Tcl_SetVar2Ex(interp, "tcl_platform", "wordSize",
778            Tcl_NewLongObj((long) sizeof(long)), TCL_GLOBAL_ONLY);
779
780    /* TIP #291 */
781    Tcl_SetVar2Ex(interp, "tcl_platform", "pointerSize",
782            Tcl_NewLongObj((long) sizeof(void *)), TCL_GLOBAL_ONLY);
783
784    /*
785     * Set up other variables such as tcl_version and tcl_library
786     */
787
788    Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
789    Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
790    Tcl_TraceVar2(interp, "tcl_precision", NULL,
791            TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
792            TclPrecTraceProc, NULL);
793    TclpSetVariables(interp);
794
795#ifdef TCL_THREADS
796    /*
797     * The existence of the "threaded" element of the tcl_platform array
798     * indicates that this particular Tcl shell has been compiled with threads
799     * turned on. Using "info exists tcl_platform(threaded)" a Tcl script can
800     * introspect on the interpreter level of thread safety.
801     */
802
803    Tcl_SetVar2(interp, "tcl_platform", "threaded", "1", TCL_GLOBAL_ONLY);
804#endif
805
806    /*
807     * Register Tcl's version number.
808     * TIP #268: Full patchlevel instead of just major.minor
809     */
810
811    Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs);
812
813#ifdef Tcl_InitStubs
814#undef Tcl_InitStubs
815#endif
816    Tcl_InitStubs(interp, TCL_VERSION, 1);
817
818    if (TclTommath_Init(interp) != TCL_OK) {
819        Tcl_Panic(Tcl_GetString(Tcl_GetObjResult(interp)));
820    }
821
822    return interp;
823}
824
825static void
826DeleteOpCmdClientData(
827    ClientData clientData)
828{
829    TclOpCmdClientData *occdPtr = clientData;
830
831    ckfree((char *) occdPtr);
832}
833
834/*
835 *----------------------------------------------------------------------
836 *
837 * TclHideUnsafeCommands --
838 *
839 *      Hides base commands that are not marked as safe from this interpreter.
840 *
841 * Results:
842 *      TCL_OK if it succeeds, TCL_ERROR else.
843 *
844 * Side effects:
845 *      Hides functionality in an interpreter.
846 *
847 *----------------------------------------------------------------------
848 */
849
850int
851TclHideUnsafeCommands(
852    Tcl_Interp *interp)         /* Hide commands in this interpreter. */
853{
854    register const CmdInfo *cmdInfoPtr;
855
856    if (interp == NULL) {
857        return TCL_ERROR;
858    }
859    for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
860        if (!cmdInfoPtr->isSafe) {
861            Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
862        }
863    }
864    return TCL_OK;
865}
866
867/*
868 *--------------------------------------------------------------
869 *
870 * Tcl_CallWhenDeleted --
871 *
872 *      Arrange for a function to be called before a given interpreter is
873 *      deleted. The function is called as soon as Tcl_DeleteInterp is called;
874 *      if Tcl_CallWhenDeleted is called on an interpreter that has already
875 *      been deleted, the function will be called when the last Tcl_Release is
876 *      done on the interpreter.
877 *
878 * Results:
879 *      None.
880 *
881 * Side effects:
882 *      When Tcl_DeleteInterp is invoked to delete interp, proc will be
883 *      invoked. See the manual entry for details.
884 *
885 *--------------------------------------------------------------
886 */
887
888void
889Tcl_CallWhenDeleted(
890    Tcl_Interp *interp,         /* Interpreter to watch. */
891    Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about
892                                 * to be deleted. */
893    ClientData clientData)      /* One-word value to pass to proc. */
894{
895    Interp *iPtr = (Interp *) interp;
896    static Tcl_ThreadDataKey assocDataCounterKey;
897    int *assocDataCounterPtr =
898            Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int));
899    int isNew;
900    char buffer[32 + TCL_INTEGER_SPACE];
901    AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));
902    Tcl_HashEntry *hPtr;
903
904    sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr);
905    (*assocDataCounterPtr)++;
906
907    if (iPtr->assocData == NULL) {
908        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
909        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
910    }
911    hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &isNew);
912    dPtr->proc = proc;
913    dPtr->clientData = clientData;
914    Tcl_SetHashValue(hPtr, dPtr);
915}
916
917/*
918 *--------------------------------------------------------------
919 *
920 * Tcl_DontCallWhenDeleted --
921 *
922 *      Cancel the arrangement for a function to be called when a given
923 *      interpreter is deleted.
924 *
925 * Results:
926 *      None.
927 *
928 * Side effects:
929 *      If proc and clientData were previously registered as a callback via
930 *      Tcl_CallWhenDeleted, they are unregistered. If they weren't previously
931 *      registered then nothing happens.
932 *
933 *--------------------------------------------------------------
934 */
935
936void
937Tcl_DontCallWhenDeleted(
938    Tcl_Interp *interp,         /* Interpreter to watch. */
939    Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about
940                                 * to be deleted. */
941    ClientData clientData)      /* One-word value to pass to proc. */
942{
943    Interp *iPtr = (Interp *) interp;
944    Tcl_HashTable *hTablePtr;
945    Tcl_HashSearch hSearch;
946    Tcl_HashEntry *hPtr;
947    AssocData *dPtr;
948
949    hTablePtr = iPtr->assocData;
950    if (hTablePtr == NULL) {
951        return;
952    }
953    for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
954            hPtr = Tcl_NextHashEntry(&hSearch)) {
955        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
956        if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
957            ckfree((char *) dPtr);
958            Tcl_DeleteHashEntry(hPtr);
959            return;
960        }
961    }
962}
963
964/*
965 *----------------------------------------------------------------------
966 *
967 * Tcl_SetAssocData --
968 *
969 *      Creates a named association between user-specified data, a delete
970 *      function and this interpreter. If the association already exists the
971 *      data is overwritten with the new data. The delete function will be
972 *      invoked when the interpreter is deleted.
973 *
974 * Results:
975 *      None.
976 *
977 * Side effects:
978 *      Sets the associated data, creates the association if needed.
979 *
980 *----------------------------------------------------------------------
981 */
982
983void
984Tcl_SetAssocData(
985    Tcl_Interp *interp,         /* Interpreter to associate with. */
986    const char *name,           /* Name for association. */
987    Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to
988                                 * be deleted. */
989    ClientData clientData)      /* One-word value to pass to proc. */
990{
991    Interp *iPtr = (Interp *) interp;
992    AssocData *dPtr;
993    Tcl_HashEntry *hPtr;
994    int isNew;
995
996    if (iPtr->assocData == NULL) {
997        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
998        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
999    }
1000    hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &isNew);
1001    if (isNew == 0) {
1002        dPtr = Tcl_GetHashValue(hPtr);
1003    } else {
1004        dPtr = (AssocData *) ckalloc(sizeof(AssocData));
1005    }
1006    dPtr->proc = proc;
1007    dPtr->clientData = clientData;
1008
1009    Tcl_SetHashValue(hPtr, dPtr);
1010}
1011
1012/*
1013 *----------------------------------------------------------------------
1014 *
1015 * Tcl_DeleteAssocData --
1016 *
1017 *      Deletes a named association of user-specified data with the specified
1018 *      interpreter.
1019 *
1020 * Results:
1021 *      None.
1022 *
1023 * Side effects:
1024 *      Deletes the association.
1025 *
1026 *----------------------------------------------------------------------
1027 */
1028
1029void
1030Tcl_DeleteAssocData(
1031    Tcl_Interp *interp,         /* Interpreter to associate with. */
1032    const char *name)           /* Name of association. */
1033{
1034    Interp *iPtr = (Interp *) interp;
1035    AssocData *dPtr;
1036    Tcl_HashEntry *hPtr;
1037
1038    if (iPtr->assocData == NULL) {
1039        return;
1040    }
1041    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
1042    if (hPtr == NULL) {
1043        return;
1044    }
1045    dPtr = Tcl_GetHashValue(hPtr);
1046    if (dPtr->proc != NULL) {
1047        dPtr->proc(dPtr->clientData, interp);
1048    }
1049    ckfree((char *) dPtr);
1050    Tcl_DeleteHashEntry(hPtr);
1051}
1052
1053/*
1054 *----------------------------------------------------------------------
1055 *
1056 * Tcl_GetAssocData --
1057 *
1058 *      Returns the client data associated with this name in the specified
1059 *      interpreter.
1060 *
1061 * Results:
1062 *      The client data in the AssocData record denoted by the named
1063 *      association, or NULL.
1064 *
1065 * Side effects:
1066 *      None.
1067 *
1068 *----------------------------------------------------------------------
1069 */
1070
1071ClientData
1072Tcl_GetAssocData(
1073    Tcl_Interp *interp,         /* Interpreter associated with. */
1074    const char *name,           /* Name of association. */
1075    Tcl_InterpDeleteProc **procPtr)
1076                                /* Pointer to place to store address of
1077                                 * current deletion callback. */
1078{
1079    Interp *iPtr = (Interp *) interp;
1080    AssocData *dPtr;
1081    Tcl_HashEntry *hPtr;
1082
1083    if (iPtr->assocData == NULL) {
1084        return NULL;
1085    }
1086    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
1087    if (hPtr == NULL) {
1088        return NULL;
1089    }
1090    dPtr = Tcl_GetHashValue(hPtr);
1091    if (procPtr != NULL) {
1092        *procPtr = dPtr->proc;
1093    }
1094    return dPtr->clientData;
1095}
1096
1097/*
1098 *----------------------------------------------------------------------
1099 *
1100 * Tcl_InterpDeleted --
1101 *
1102 *      Returns nonzero if the interpreter has been deleted with a call to
1103 *      Tcl_DeleteInterp.
1104 *
1105 * Results:
1106 *      Nonzero if the interpreter is deleted, zero otherwise.
1107 *
1108 * Side effects:
1109 *      None.
1110 *
1111 *----------------------------------------------------------------------
1112 */
1113
1114int
1115Tcl_InterpDeleted(
1116    Tcl_Interp *interp)
1117{
1118    return (((Interp *) interp)->flags & DELETED) ? 1 : 0;
1119}
1120
1121/*
1122 *----------------------------------------------------------------------
1123 *
1124 * Tcl_DeleteInterp --
1125 *
1126 *      Ensures that the interpreter will be deleted eventually. If there are
1127 *      no Tcl_Preserve calls in effect for this interpreter, it is deleted
1128 *      immediately, otherwise the interpreter is deleted when the last
1129 *      Tcl_Preserve is matched by a call to Tcl_Release. In either case, the
1130 *      function runs the currently registered deletion callbacks.
1131 *
1132 * Results:
1133 *      None.
1134 *
1135 * Side effects:
1136 *      The interpreter is marked as deleted. The caller may still use it
1137 *      safely if there are calls to Tcl_Preserve in effect for the
1138 *      interpreter, but further calls to Tcl_Eval etc in this interpreter
1139 *      will fail.
1140 *
1141 *----------------------------------------------------------------------
1142 */
1143
1144void
1145Tcl_DeleteInterp(
1146    Tcl_Interp *interp)         /* Token for command interpreter (returned by
1147                                 * a previous call to Tcl_CreateInterp). */
1148{
1149    Interp *iPtr = (Interp *) interp;
1150
1151    /*
1152     * If the interpreter has already been marked deleted, just punt.
1153     */
1154
1155    if (iPtr->flags & DELETED) {
1156        return;
1157    }
1158
1159    /*
1160     * Mark the interpreter as deleted. No further evals will be allowed.
1161     * Increase the compileEpoch as a signal to compiled bytecodes.
1162     */
1163
1164    iPtr->flags |= DELETED;
1165    iPtr->compileEpoch++;
1166
1167    /*
1168     * Ensure that the interpreter is eventually deleted.
1169     */
1170
1171    Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc);
1172}
1173
1174/*
1175 *----------------------------------------------------------------------
1176 *
1177 * DeleteInterpProc --
1178 *
1179 *      Helper function to delete an interpreter. This function is called when
1180 *      the last call to Tcl_Preserve on this interpreter is matched by a call
1181 *      to Tcl_Release. The function cleans up all resources used in the
1182 *      interpreter and calls all currently registered interpreter deletion
1183 *      callbacks.
1184 *
1185 * Results:
1186 *      None.
1187 *
1188 * Side effects:
1189 *      Whatever the interpreter deletion callbacks do. Frees resources used
1190 *      by the interpreter.
1191 *
1192 *----------------------------------------------------------------------
1193 */
1194
1195static void
1196DeleteInterpProc(
1197    Tcl_Interp *interp)         /* Interpreter to delete. */
1198{
1199    Interp *iPtr = (Interp *) interp;
1200    Tcl_HashEntry *hPtr;
1201    Tcl_HashSearch search;
1202    Tcl_HashTable *hTablePtr;
1203    ResolverScheme *resPtr, *nextResPtr;
1204
1205    /*
1206     * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
1207     */
1208
1209    if (iPtr->numLevels > 0) {
1210        Tcl_Panic("DeleteInterpProc called with active evals");
1211    }
1212
1213    /*
1214     * The interpreter should already be marked deleted; otherwise how did we
1215     * get here?
1216     */
1217
1218    if (!(iPtr->flags & DELETED)) {
1219        Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted");
1220    }
1221
1222    /*
1223     * TIP #219, Tcl Channel Reflection API. Discard a leftover state.
1224     */
1225
1226    if (iPtr->chanMsg != NULL) {
1227        Tcl_DecrRefCount(iPtr->chanMsg);
1228        iPtr->chanMsg = NULL;
1229    }
1230
1231    /*
1232     * Shut down all limit handler callback scripts that call back into this
1233     * interpreter. Then eliminate all limit handlers for this interpreter.
1234     */
1235
1236    TclRemoveScriptLimitCallbacks(interp);
1237    TclLimitRemoveAllHandlers(interp);
1238
1239    /*
1240     * Dismantle the namespace here, before we clear the assocData. If any
1241     * background errors occur here, they will be deleted below.
1242     *
1243     * Dismantle the namespace after freeing the iPtr->handle so that each
1244     * bytecode releases its literals without caring to update the literal
1245     * table, as it will be freed later in this function without further use.
1246     */
1247
1248    TclCleanupLiteralTable(interp, &(iPtr->literalTable));
1249    TclHandleFree(iPtr->handle);
1250    TclTeardownNamespace(iPtr->globalNsPtr);
1251
1252    /*
1253     * Delete all the hidden commands.
1254     */
1255
1256    hTablePtr = iPtr->hiddenCmdTablePtr;
1257    if (hTablePtr != NULL) {
1258        /*
1259         * Non-pernicious deletion. The deletion callbacks will not be allowed
1260         * to create any new hidden or non-hidden commands.
1261         * Tcl_DeleteCommandFromToken() will remove the entry from the
1262         * hiddenCmdTablePtr.
1263         */
1264
1265        hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
1266        for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
1267            Tcl_DeleteCommandFromToken(interp,
1268                    (Tcl_Command) Tcl_GetHashValue(hPtr));
1269        }
1270        Tcl_DeleteHashTable(hTablePtr);
1271        ckfree((char *) hTablePtr);
1272    }
1273
1274    /*
1275     * Invoke deletion callbacks; note that a callback can create new
1276     * callbacks, so we iterate.
1277     */
1278
1279    while (iPtr->assocData != NULL) {
1280        AssocData *dPtr;
1281
1282        hTablePtr = iPtr->assocData;
1283        iPtr->assocData = NULL;
1284        for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
1285                hPtr != NULL;
1286                hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
1287            dPtr = Tcl_GetHashValue(hPtr);
1288            Tcl_DeleteHashEntry(hPtr);
1289            if (dPtr->proc != NULL) {
1290                dPtr->proc(dPtr->clientData, interp);
1291            }
1292            ckfree((char *) dPtr);
1293        }
1294        Tcl_DeleteHashTable(hTablePtr);
1295        ckfree((char *) hTablePtr);
1296    }
1297
1298    /*
1299     * Pop the root frame pointer and finish deleting the global
1300     * namespace. The order is important [Bug 1658572].
1301     */
1302
1303    if (iPtr->framePtr != iPtr->rootFramePtr) {
1304        Tcl_Panic("DeleteInterpProc: popping rootCallFrame with other frames on top");
1305    }
1306    Tcl_PopCallFrame(interp);
1307    ckfree((char *) iPtr->rootFramePtr);
1308    iPtr->rootFramePtr = NULL;
1309    Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
1310
1311    /*
1312     * Free up the result *after* deleting variables, since variable deletion
1313     * could have transferred ownership of the result string to Tcl.
1314     */
1315
1316    Tcl_FreeResult(interp);
1317    interp->result = NULL;
1318    Tcl_DecrRefCount(iPtr->objResultPtr);
1319    iPtr->objResultPtr = NULL;
1320    Tcl_DecrRefCount(iPtr->ecVar);
1321    if (iPtr->errorCode) {
1322        Tcl_DecrRefCount(iPtr->errorCode);
1323        iPtr->errorCode = NULL;
1324    }
1325    Tcl_DecrRefCount(iPtr->eiVar);
1326    if (iPtr->errorInfo) {
1327        Tcl_DecrRefCount(iPtr->errorInfo);
1328        iPtr->errorInfo = NULL;
1329    }
1330    if (iPtr->returnOpts) {
1331        Tcl_DecrRefCount(iPtr->returnOpts);
1332    }
1333    if (iPtr->appendResult != NULL) {
1334        ckfree(iPtr->appendResult);
1335        iPtr->appendResult = NULL;
1336    }
1337    TclFreePackageInfo(iPtr);
1338    while (iPtr->tracePtr != NULL) {
1339        Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr);
1340    }
1341    if (iPtr->execEnvPtr != NULL) {
1342        TclDeleteExecEnv(iPtr->execEnvPtr);
1343    }
1344    Tcl_DecrRefCount(iPtr->emptyObjPtr);
1345    iPtr->emptyObjPtr = NULL;
1346
1347    resPtr = iPtr->resolverPtr;
1348    while (resPtr) {
1349        nextResPtr = resPtr->nextPtr;
1350        ckfree(resPtr->name);
1351        ckfree((char *) resPtr);
1352        resPtr = nextResPtr;
1353    }
1354
1355    /*
1356     * Free up literal objects created for scripts compiled by the
1357     * interpreter.
1358     */
1359
1360    TclDeleteLiteralTable(interp, &(iPtr->literalTable));
1361
1362    /*
1363     * TIP #280 - Release the arrays for ByteCode/Proc extension, and
1364     * contents.
1365     */
1366
1367    {
1368        Tcl_HashEntry *hPtr;
1369        Tcl_HashSearch hSearch;
1370        int i;
1371
1372        for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &hSearch);
1373                hPtr != NULL;
1374                hPtr = Tcl_NextHashEntry(&hSearch)) {
1375            CmdFrame *cfPtr = Tcl_GetHashValue(hPtr);
1376
1377            if (cfPtr->type == TCL_LOCATION_SOURCE) {
1378                Tcl_DecrRefCount(cfPtr->data.eval.path);
1379            }
1380            ckfree((char *) cfPtr->line);
1381            ckfree((char *) cfPtr);
1382            Tcl_DeleteHashEntry(hPtr);
1383        }
1384        Tcl_DeleteHashTable(iPtr->linePBodyPtr);
1385        ckfree((char *) iPtr->linePBodyPtr);
1386        iPtr->linePBodyPtr = NULL;
1387
1388        /*
1389         * See also tclCompile.c, TclCleanupByteCode
1390         */
1391
1392        for (hPtr = Tcl_FirstHashEntry(iPtr->lineBCPtr, &hSearch);
1393                hPtr != NULL;
1394                hPtr = Tcl_NextHashEntry(&hSearch)) {
1395            ExtCmdLoc *eclPtr = (ExtCmdLoc *) Tcl_GetHashValue(hPtr);
1396
1397            if (eclPtr->type == TCL_LOCATION_SOURCE) {
1398                Tcl_DecrRefCount(eclPtr->path);
1399            }
1400            for (i=0; i< eclPtr->nuloc; i++) {
1401                ckfree((char *) eclPtr->loc[i].line);
1402            }
1403
1404            if (eclPtr->loc != NULL) {
1405                ckfree((char *) eclPtr->loc);
1406            }
1407
1408            ckfree((char *) eclPtr);
1409            Tcl_DeleteHashEntry(hPtr);
1410        }
1411        Tcl_DeleteHashTable(iPtr->lineBCPtr);
1412        ckfree((char *) iPtr->lineBCPtr);
1413        iPtr->lineBCPtr = NULL;
1414    }
1415
1416    Tcl_DeleteHashTable(&iPtr->varTraces);
1417    Tcl_DeleteHashTable(&iPtr->varSearches);
1418
1419    ckfree((char *) iPtr);
1420}
1421
1422/*
1423 *---------------------------------------------------------------------------
1424 *
1425 * Tcl_HideCommand --
1426 *
1427 *      Makes a command hidden so that it cannot be invoked from within an
1428 *      interpreter, only from within an ancestor.
1429 *
1430 * Results:
1431 *      A standard Tcl result; also leaves a message in the interp's result if
1432 *      an error occurs.
1433 *
1434 * Side effects:
1435 *      Removes a command from the command table and create an entry into the
1436 *      hidden command table under the specified token name.
1437 *
1438 *---------------------------------------------------------------------------
1439 */
1440
1441int
1442Tcl_HideCommand(
1443    Tcl_Interp *interp,         /* Interpreter in which to hide command. */
1444    const char *cmdName,        /* Name of command to hide. */
1445    const char *hiddenCmdToken) /* Token name of the to-be-hidden command. */
1446{
1447    Interp *iPtr = (Interp *) interp;
1448    Tcl_Command cmd;
1449    Command *cmdPtr;
1450    Tcl_HashTable *hiddenCmdTablePtr;
1451    Tcl_HashEntry *hPtr;
1452    int isNew;
1453
1454    if (iPtr->flags & DELETED) {
1455        /*
1456         * The interpreter is being deleted. Do not create any new structures,
1457         * because it is not safe to modify the interpreter.
1458         */
1459
1460        return TCL_ERROR;
1461    }
1462
1463    /*
1464     * Disallow hiding of commands that are currently in a namespace or
1465     * renaming (as part of hiding) into a namespace (because the current
1466     * implementation with a single global table and the needed uniqueness of
1467     * names cause problems with namespaces).
1468     *
1469     * We don't need to check for "::" in cmdName because the real check is on
1470     * the nsPtr below.
1471     *
1472     * hiddenCmdToken is just a string which is not interpreted in any way. It
1473     * may contain :: but the string is not interpreted as a namespace
1474     * qualifier command name. Thus, hiding foo::bar to foo::bar and then
1475     * trying to expose or invoke ::foo::bar will NOT work; but if the
1476     * application always uses the same strings it will get consistent
1477     * behaviour.
1478     *
1479     * But as we currently limit ourselves to the global namespace only for
1480     * the source, in order to avoid potential confusion, lets prevent "::" in
1481     * the token too. - dl
1482     */
1483
1484    if (strstr(hiddenCmdToken, "::") != NULL) {
1485        Tcl_AppendResult(interp,
1486                "cannot use namespace qualifiers in hidden command"
1487                " token (rename)", NULL);
1488        return TCL_ERROR;
1489    }
1490
1491    /*
1492     * Find the command to hide. An error is returned if cmdName can't be
1493     * found. Look up the command only from the global namespace. Full path of
1494     * the command must be given if using namespaces.
1495     */
1496
1497    cmd = Tcl_FindCommand(interp, cmdName, NULL,
1498            /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1499    if (cmd == (Tcl_Command) NULL) {
1500        return TCL_ERROR;
1501    }
1502    cmdPtr = (Command *) cmd;
1503
1504    /*
1505     * Check that the command is really in global namespace
1506     */
1507
1508    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
1509        Tcl_AppendResult(interp, "can only hide global namespace commands"
1510                " (use rename then hide)", NULL);
1511        return TCL_ERROR;
1512    }
1513
1514    /*
1515     * Initialize the hidden command table if necessary.
1516     */
1517
1518    hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
1519    if (hiddenCmdTablePtr == NULL) {
1520        hiddenCmdTablePtr = (Tcl_HashTable *)
1521                ckalloc((unsigned) sizeof(Tcl_HashTable));
1522        Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
1523        iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr;
1524    }
1525
1526    /*
1527     * It is an error to move an exposed command to a hidden command with
1528     * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
1529     * exists.
1530     */
1531
1532    hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew);
1533    if (!isNew) {
1534        Tcl_AppendResult(interp, "hidden command named \"", hiddenCmdToken,
1535                "\" already exists", NULL);
1536        return TCL_ERROR;
1537    }
1538
1539    /*
1540     * NB: This code is currently 'like' a rename to a specialy set apart name
1541     * table. Changes here and in TclRenameCommand must be kept in synch until
1542     * the common parts are actually factorized out.
1543     */
1544
1545    /*
1546     * Remove the hash entry for the command from the interpreter command
1547     * table. This is like deleting the command, so bump its command epoch;
1548     * this invalidates any cached references that point to the command.
1549     */
1550
1551    if (cmdPtr->hPtr != NULL) {
1552        Tcl_DeleteHashEntry(cmdPtr->hPtr);
1553        cmdPtr->hPtr = NULL;
1554        cmdPtr->cmdEpoch++;
1555    }
1556
1557    /*
1558     * The list of command exported from the namespace might have changed.
1559     * However, we do not need to recompute this just yet; next time we need
1560     * the info will be soon enough.
1561     */
1562
1563    TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
1564
1565    /*
1566     * Now link the hash table entry with the command structure. We ensured
1567     * above that the nsPtr was right.
1568     */
1569
1570    cmdPtr->hPtr = hPtr;
1571    Tcl_SetHashValue(hPtr, cmdPtr);
1572
1573    /*
1574     * If the command being hidden has a compile function, increment the
1575     * interpreter's compileEpoch to invalidate its compiled code. This makes
1576     * sure that we don't later try to execute old code compiled with
1577     * command-specific (i.e., inline) bytecodes for the now-hidden command.
1578     * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose
1579     * compilation epoch doesn't match is recompiled.
1580     */
1581
1582    if (cmdPtr->compileProc != NULL) {
1583        iPtr->compileEpoch++;
1584    }
1585    return TCL_OK;
1586}
1587
1588/*
1589 *----------------------------------------------------------------------
1590 *
1591 * Tcl_ExposeCommand --
1592 *
1593 *      Makes a previously hidden command callable from inside the interpreter
1594 *      instead of only by its ancestors.
1595 *
1596 * Results:
1597 *      A standard Tcl result. If an error occurs, a message is left in the
1598 *      interp's result.
1599 *
1600 * Side effects:
1601 *      Moves commands from one hash table to another.
1602 *
1603 *----------------------------------------------------------------------
1604 */
1605
1606int
1607Tcl_ExposeCommand(
1608    Tcl_Interp *interp,         /* Interpreter in which to make command
1609                                 * callable. */
1610    const char *hiddenCmdToken, /* Name of hidden command. */
1611    const char *cmdName)        /* Name of to-be-exposed command. */
1612{
1613    Interp *iPtr = (Interp *) interp;
1614    Command *cmdPtr;
1615    Namespace *nsPtr;
1616    Tcl_HashEntry *hPtr;
1617    Tcl_HashTable *hiddenCmdTablePtr;
1618    int isNew;
1619
1620    if (iPtr->flags & DELETED) {
1621        /*
1622         * The interpreter is being deleted. Do not create any new structures,
1623         * because it is not safe to modify the interpreter.
1624         */
1625
1626        return TCL_ERROR;
1627    }
1628
1629    /*
1630     * Check that we have a regular name for the command (that the user is not
1631     * trying to do an expose and a rename (to another namespace) at the same
1632     * time).
1633     */
1634
1635    if (strstr(cmdName, "::") != NULL) {
1636        Tcl_AppendResult(interp, "cannot expose to a namespace "
1637                "(use expose to toplevel, then rename)", NULL);
1638        return TCL_ERROR;
1639    }
1640
1641    /*
1642     * Get the command from the hidden command table:
1643     */
1644
1645    hPtr = NULL;
1646    hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
1647    if (hiddenCmdTablePtr != NULL) {
1648        hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
1649    }
1650    if (hPtr == NULL) {
1651        Tcl_AppendResult(interp, "unknown hidden command \"", hiddenCmdToken,
1652                "\"", NULL);
1653        return TCL_ERROR;
1654    }
1655    cmdPtr = Tcl_GetHashValue(hPtr);
1656
1657    /*
1658     * Check that we have a true global namespace command (enforced by
1659     * Tcl_HideCommand() but let's double check. (If it was not, we would not
1660     * really know how to handle it).
1661     */
1662
1663    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
1664        /*
1665         * This case is theoritically impossible, we might rather Tcl_Panic()
1666         * than 'nicely' erroring out ?
1667         */
1668
1669        Tcl_AppendResult(interp,
1670                "trying to expose a non global command name space command",
1671                NULL);
1672        return TCL_ERROR;
1673    }
1674
1675    /*
1676     * This is the global table.
1677     */
1678
1679    nsPtr = cmdPtr->nsPtr;
1680
1681    /*
1682     * It is an error to overwrite an existing exposed command as a result of
1683     * exposing a previously hidden command.
1684     */
1685
1686    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew);
1687    if (!isNew) {
1688        Tcl_AppendResult(interp, "exposed command \"", cmdName,
1689                "\" already exists", NULL);
1690        return TCL_ERROR;
1691    }
1692
1693    /*
1694     * The list of command exported from the namespace might have changed.
1695     * However, we do not need to recompute this just yet; next time we need
1696     * the info will be soon enough.
1697     */
1698
1699    TclInvalidateNsCmdLookup(nsPtr);
1700
1701    /*
1702     * Remove the hash entry for the command from the interpreter hidden
1703     * command table.
1704     */
1705
1706    if (cmdPtr->hPtr != NULL) {
1707        Tcl_DeleteHashEntry(cmdPtr->hPtr);
1708        cmdPtr->hPtr = NULL;
1709    }
1710
1711    /*
1712     * Now link the hash table entry with the command structure. This is like
1713     * creating a new command, so deal with any shadowing of commands in the
1714     * global namespace.
1715     */
1716
1717    cmdPtr->hPtr = hPtr;
1718
1719    Tcl_SetHashValue(hPtr, cmdPtr);
1720
1721    /*
1722     * Not needed as we are only in the global namespace (but would be needed
1723     * again if we supported namespace command hiding)
1724     *
1725     * TclResetShadowedCmdRefs(interp, cmdPtr);
1726     */
1727
1728    /*
1729     * If the command being exposed has a compile function, increment
1730     * interpreter's compileEpoch to invalidate its compiled code. This makes
1731     * sure that we don't later try to execute old code compiled assuming the
1732     * command is hidden. This field is checked in Tcl_EvalObj and
1733     * ObjInterpProc, and code whose compilation epoch doesn't match is
1734     * recompiled.
1735     */
1736
1737    if (cmdPtr->compileProc != NULL) {
1738        iPtr->compileEpoch++;
1739    }
1740    return TCL_OK;
1741}
1742
1743/*
1744 *----------------------------------------------------------------------
1745 *
1746 * Tcl_CreateCommand --
1747 *
1748 *      Define a new command in a command table.
1749 *
1750 * Results:
1751 *      The return value is a token for the command, which can be used in
1752 *      future calls to Tcl_GetCommandName.
1753 *
1754 * Side effects:
1755 *      If a command named cmdName already exists for interp, it is deleted.
1756 *      In the future, when cmdName is seen as the name of a command by
1757 *      Tcl_Eval, proc will be called. To support the bytecode interpreter,
1758 *      the command is created with a wrapper Tcl_ObjCmdProc
1759 *      (TclInvokeStringCommand) that eventially calls proc. When the command
1760 *      is deleted from the table, deleteProc will be called. See the manual
1761 *      entry for details on the calling sequence.
1762 *
1763 *----------------------------------------------------------------------
1764 */
1765
1766Tcl_Command
1767Tcl_CreateCommand(
1768    Tcl_Interp *interp,         /* Token for command interpreter returned by a
1769                                 * previous call to Tcl_CreateInterp. */
1770    const char *cmdName,        /* Name of command. If it contains namespace
1771                                 * qualifiers, the new command is put in the
1772                                 * specified namespace; otherwise it is put in
1773                                 * the global namespace. */
1774    Tcl_CmdProc *proc,          /* Function to associate with cmdName. */
1775    ClientData clientData,      /* Arbitrary value passed to string proc. */
1776    Tcl_CmdDeleteProc *deleteProc)
1777                                /* If not NULL, gives a function to call when
1778                                 * this command is deleted. */
1779{
1780    Interp *iPtr = (Interp *) interp;
1781    ImportRef *oldRefPtr = NULL;
1782    Namespace *nsPtr, *dummy1, *dummy2;
1783    Command *cmdPtr, *refCmdPtr;
1784    Tcl_HashEntry *hPtr;
1785    const char *tail;
1786    int isNew;
1787    ImportedCmdData *dataPtr;
1788
1789    if (iPtr->flags & DELETED) {
1790        /*
1791         * The interpreter is being deleted. Don't create any new commands;
1792         * it's not safe to muck with the interpreter anymore.
1793         */
1794
1795        return (Tcl_Command) NULL;
1796    }
1797
1798    /*
1799     * Determine where the command should reside. If its name contains
1800     * namespace qualifiers, we put it in the specified namespace; otherwise,
1801     * we always put it in the global namespace.
1802     */
1803
1804    if (strstr(cmdName, "::") != NULL) {
1805        TclGetNamespaceForQualName(interp, cmdName, NULL,
1806                TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
1807        if ((nsPtr == NULL) || (tail == NULL)) {
1808            return (Tcl_Command) NULL;
1809        }
1810    } else {
1811        nsPtr = iPtr->globalNsPtr;
1812        tail = cmdName;
1813    }
1814
1815    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
1816    if (!isNew) {
1817        /*
1818         * Command already exists. Delete the old one. Be careful to preserve
1819         * any existing import links so we can restore them down below. That
1820         * way, you can redefine a command and its import status will remain
1821         * intact.
1822         */
1823
1824        cmdPtr = Tcl_GetHashValue(hPtr);
1825        oldRefPtr = cmdPtr->importRefPtr;
1826        cmdPtr->importRefPtr = NULL;
1827
1828        Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
1829        hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
1830        if (!isNew) {
1831            /*
1832             * If the deletion callback recreated the command, just throw away
1833             * the new command (if we try to delete it again, we could get
1834             * stuck in an infinite loop).
1835             */
1836
1837             ckfree((char *) Tcl_GetHashValue(hPtr));
1838        }
1839    } else {
1840        /*
1841         * The list of command exported from the namespace might have changed.
1842         * However, we do not need to recompute this just yet; next time we
1843         * need the info will be soon enough.
1844         */
1845
1846        TclInvalidateNsCmdLookup(nsPtr);
1847        TclInvalidateNsPath(nsPtr);
1848    }
1849    cmdPtr = (Command *) ckalloc(sizeof(Command));
1850    Tcl_SetHashValue(hPtr, cmdPtr);
1851    cmdPtr->hPtr = hPtr;
1852    cmdPtr->nsPtr = nsPtr;
1853    cmdPtr->refCount = 1;
1854    cmdPtr->cmdEpoch = 0;
1855    cmdPtr->compileProc = NULL;
1856    cmdPtr->objProc = TclInvokeStringCommand;
1857    cmdPtr->objClientData = cmdPtr;
1858    cmdPtr->proc = proc;
1859    cmdPtr->clientData = clientData;
1860    cmdPtr->deleteProc = deleteProc;
1861    cmdPtr->deleteData = clientData;
1862    cmdPtr->flags = 0;
1863    cmdPtr->importRefPtr = NULL;
1864    cmdPtr->tracePtr = NULL;
1865
1866    /*
1867     * Plug in any existing import references found above. Be sure to update
1868     * all of these references to point to the new command.
1869     */
1870
1871    if (oldRefPtr != NULL) {
1872        cmdPtr->importRefPtr = oldRefPtr;
1873        while (oldRefPtr != NULL) {
1874            refCmdPtr = oldRefPtr->importedCmdPtr;
1875            dataPtr = refCmdPtr->objClientData;
1876            dataPtr->realCmdPtr = cmdPtr;
1877            oldRefPtr = oldRefPtr->nextPtr;
1878        }
1879    }
1880
1881    /*
1882     * We just created a command, so in its namespace and all of its parent
1883     * namespaces, it may shadow global commands with the same name. If any
1884     * shadowed commands are found, invalidate all cached command references
1885     * in the affected namespaces.
1886     */
1887
1888    TclResetShadowedCmdRefs(interp, cmdPtr);
1889    return (Tcl_Command) cmdPtr;
1890}
1891
1892/*
1893 *----------------------------------------------------------------------
1894 *
1895 * Tcl_CreateObjCommand --
1896 *
1897 *      Define a new object-based command in a command table.
1898 *
1899 * Results:
1900 *      The return value is a token for the command, which can be used in
1901 *      future calls to Tcl_GetCommandName.
1902 *
1903 * Side effects:
1904 *      If no command named "cmdName" already exists for interp, one is
1905 *      created. Otherwise, if a command does exist, then if the object-based
1906 *      Tcl_ObjCmdProc is TclInvokeStringCommand, we assume Tcl_CreateCommand
1907 *      was called previously for the same command and just set its
1908 *      Tcl_ObjCmdProc to the argument "proc"; otherwise, we delete the old
1909 *      command.
1910 *
1911 *      In the future, during bytecode evaluation when "cmdName" is seen as
1912 *      the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
1913 *      Tcl_ObjCmdProc proc will be called. When the command is deleted from
1914 *      the table, deleteProc will be called. See the manual entry for details
1915 *      on the calling sequence.
1916 *
1917 *----------------------------------------------------------------------
1918 */
1919
1920Tcl_Command
1921Tcl_CreateObjCommand(
1922    Tcl_Interp *interp,         /* Token for command interpreter (returned by
1923                                 * previous call to Tcl_CreateInterp). */
1924    const char *cmdName,        /* Name of command. If it contains namespace
1925                                 * qualifiers, the new command is put in the
1926                                 * specified namespace; otherwise it is put in
1927                                 * the global namespace. */
1928    Tcl_ObjCmdProc *proc,       /* Object-based function to associate with
1929                                 * name. */
1930    ClientData clientData,      /* Arbitrary value to pass to object
1931                                 * function. */
1932    Tcl_CmdDeleteProc *deleteProc)
1933                                /* If not NULL, gives a function to call when
1934                                 * this command is deleted. */
1935{
1936    Interp *iPtr = (Interp *) interp;
1937    ImportRef *oldRefPtr = NULL;
1938    Namespace *nsPtr, *dummy1, *dummy2;
1939    Command *cmdPtr, *refCmdPtr;
1940    Tcl_HashEntry *hPtr;
1941    const char *tail;
1942    int isNew;
1943    ImportedCmdData *dataPtr;
1944
1945    if (iPtr->flags & DELETED) {
1946        /*
1947         * The interpreter is being deleted. Don't create any new commands;
1948         * it's not safe to muck with the interpreter anymore.
1949         */
1950
1951        return (Tcl_Command) NULL;
1952    }
1953
1954    /*
1955     * Determine where the command should reside. If its name contains
1956     * namespace qualifiers, we put it in the specified namespace; otherwise,
1957     * we always put it in the global namespace.
1958     */
1959
1960    if (strstr(cmdName, "::") != NULL) {
1961        TclGetNamespaceForQualName(interp, cmdName, NULL,
1962                TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
1963        if ((nsPtr == NULL) || (tail == NULL)) {
1964            return (Tcl_Command) NULL;
1965        }
1966    } else {
1967        nsPtr = iPtr->globalNsPtr;
1968        tail = cmdName;
1969    }
1970
1971    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
1972    TclInvalidateNsPath(nsPtr);
1973    if (!isNew) {
1974        cmdPtr = Tcl_GetHashValue(hPtr);
1975
1976        /*
1977         * Command already exists. If its object-based Tcl_ObjCmdProc is
1978         * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
1979         * argument "proc". Otherwise, we delete the old command.
1980         */
1981
1982        if (cmdPtr->objProc == TclInvokeStringCommand) {
1983            cmdPtr->objProc = proc;
1984            cmdPtr->objClientData = clientData;
1985            cmdPtr->deleteProc = deleteProc;
1986            cmdPtr->deleteData = clientData;
1987            return (Tcl_Command) cmdPtr;
1988        }
1989
1990        /*
1991         * Otherwise, we delete the old command. Be careful to preserve any
1992         * existing import links so we can restore them down below. That way,
1993         * you can redefine a command and its import status will remain
1994         * intact.
1995         */
1996
1997        oldRefPtr = cmdPtr->importRefPtr;
1998        cmdPtr->importRefPtr = NULL;
1999
2000        Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
2001        hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
2002        if (!isNew) {
2003            /*
2004             * If the deletion callback recreated the command, just throw away
2005             * the new command (if we try to delete it again, we could get
2006             * stuck in an infinite loop).
2007             */
2008
2009             ckfree(Tcl_GetHashValue(hPtr));
2010        }
2011    } else {
2012        /*
2013         * The list of command exported from the namespace might have changed.
2014         * However, we do not need to recompute this just yet; next time we
2015         * need the info will be soon enough.
2016         */
2017
2018        TclInvalidateNsCmdLookup(nsPtr);
2019    }
2020    cmdPtr = (Command *) ckalloc(sizeof(Command));
2021    Tcl_SetHashValue(hPtr, cmdPtr);
2022    cmdPtr->hPtr = hPtr;
2023    cmdPtr->nsPtr = nsPtr;
2024    cmdPtr->refCount = 1;
2025    cmdPtr->cmdEpoch = 0;
2026    cmdPtr->compileProc = NULL;
2027    cmdPtr->objProc = proc;
2028    cmdPtr->objClientData = clientData;
2029    cmdPtr->proc = TclInvokeObjectCommand;
2030    cmdPtr->clientData = cmdPtr;
2031    cmdPtr->deleteProc = deleteProc;
2032    cmdPtr->deleteData = clientData;
2033    cmdPtr->flags = 0;
2034    cmdPtr->importRefPtr = NULL;
2035    cmdPtr->tracePtr = NULL;
2036
2037    /*
2038     * Plug in any existing import references found above. Be sure to update
2039     * all of these references to point to the new command.
2040     */
2041
2042    if (oldRefPtr != NULL) {
2043        cmdPtr->importRefPtr = oldRefPtr;
2044        while (oldRefPtr != NULL) {
2045            refCmdPtr = oldRefPtr->importedCmdPtr;
2046            dataPtr = refCmdPtr->objClientData;
2047            dataPtr->realCmdPtr = cmdPtr;
2048            oldRefPtr = oldRefPtr->nextPtr;
2049        }
2050    }
2051
2052    /*
2053     * We just created a command, so in its namespace and all of its parent
2054     * namespaces, it may shadow global commands with the same name. If any
2055     * shadowed commands are found, invalidate all cached command references
2056     * in the affected namespaces.
2057     */
2058
2059    TclResetShadowedCmdRefs(interp, cmdPtr);
2060    return (Tcl_Command) cmdPtr;
2061}
2062
2063/*
2064 *----------------------------------------------------------------------
2065 *
2066 * TclInvokeStringCommand --
2067 *
2068 *      "Wrapper" Tcl_ObjCmdProc used to call an existing string-based
2069 *      Tcl_CmdProc if no object-based function exists for a command. A
2070 *      pointer to this function is stored as the Tcl_ObjCmdProc in a Command
2071 *      structure. It simply turns around and calls the string Tcl_CmdProc in
2072 *      the Command structure.
2073 *
2074 * Results:
2075 *      A standard Tcl object result value.
2076 *
2077 * Side effects:
2078 *      Besides those side effects of the called Tcl_CmdProc,
2079 *      TclInvokeStringCommand allocates and frees storage.
2080 *
2081 *----------------------------------------------------------------------
2082 */
2083
2084int
2085TclInvokeStringCommand(
2086    ClientData clientData,      /* Points to command's Command structure. */
2087    Tcl_Interp *interp,         /* Current interpreter. */
2088    register int objc,          /* Number of arguments. */
2089    Tcl_Obj *const objv[])      /* Argument objects. */
2090{
2091    Command *cmdPtr = clientData;
2092    int i, result;
2093    const char **argv = (const char **)
2094            TclStackAlloc(interp, (unsigned)(objc + 1) * sizeof(char *));
2095
2096    for (i = 0;  i < objc;  i++) {
2097        argv[i] = Tcl_GetString(objv[i]);
2098    }
2099    argv[objc] = 0;
2100
2101    /*
2102     * Invoke the command's string-based Tcl_CmdProc.
2103     */
2104
2105    result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv);
2106
2107    TclStackFree(interp, (void *) argv);
2108    return result;
2109}
2110
2111/*
2112 *----------------------------------------------------------------------
2113 *
2114 * TclInvokeObjectCommand --
2115 *
2116 *      "Wrapper" Tcl_CmdProc used to call an existing object-based
2117 *      Tcl_ObjCmdProc if no string-based function exists for a command. A
2118 *      pointer to this function is stored as the Tcl_CmdProc in a Command
2119 *      structure. It simply turns around and calls the object Tcl_ObjCmdProc
2120 *      in the Command structure.
2121 *
2122 * Results:
2123 *      A standard Tcl string result value.
2124 *
2125 * Side effects:
2126 *      Besides those side effects of the called Tcl_CmdProc,
2127 *      TclInvokeStringCommand allocates and frees storage.
2128 *
2129 *----------------------------------------------------------------------
2130 */
2131
2132int
2133TclInvokeObjectCommand(
2134    ClientData clientData,      /* Points to command's Command structure. */
2135    Tcl_Interp *interp,         /* Current interpreter. */
2136    int argc,                   /* Number of arguments. */
2137    register const char **argv) /* Argument strings. */
2138{
2139    Command *cmdPtr = (Command *) clientData;
2140    Tcl_Obj *objPtr;
2141    int i, length, result;
2142    Tcl_Obj **objv = (Tcl_Obj **)
2143            TclStackAlloc(interp, (unsigned)(argc * sizeof(Tcl_Obj *)));
2144
2145    for (i = 0;  i < argc;  i++) {
2146        length = strlen(argv[i]);
2147        TclNewStringObj(objPtr, argv[i], length);
2148        Tcl_IncrRefCount(objPtr);
2149        objv[i] = objPtr;
2150    }
2151
2152    /*
2153     * Invoke the command's object-based Tcl_ObjCmdProc.
2154     */
2155
2156    result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);
2157
2158    /*
2159     * Move the interpreter's object result to the string result, then reset
2160     * the object result.
2161     */
2162
2163    (void) Tcl_GetStringResult(interp);
2164
2165    /*
2166     * Decrement the ref counts for the argument objects created above, then
2167     * free the objv array if malloc'ed storage was used.
2168     */
2169
2170    for (i = 0;  i < argc;  i++) {
2171        objPtr = objv[i];
2172        Tcl_DecrRefCount(objPtr);
2173    }
2174    TclStackFree(interp, objv);
2175    return result;
2176}
2177
2178/*
2179 *----------------------------------------------------------------------
2180 *
2181 * TclRenameCommand --
2182 *
2183 *      Called to give an existing Tcl command a different name. Both the old
2184 *      command name and the new command name can have "::" namespace
2185 *      qualifiers. If the new command has a different namespace context, the
2186 *      command will be moved to that namespace and will execute in the
2187 *      context of that new namespace.
2188 *
2189 *      If the new command name is NULL or the null string, the command is
2190 *      deleted.
2191 *
2192 * Results:
2193 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2194 *
2195 * Side effects:
2196 *      If anything goes wrong, an error message is returned in the
2197 *      interpreter's result object.
2198 *
2199 *----------------------------------------------------------------------
2200 */
2201
2202int
2203TclRenameCommand(
2204    Tcl_Interp *interp,         /* Current interpreter. */
2205    const char *oldName,        /* Existing command name. */
2206    const char *newName)        /* New command name. */
2207{
2208    Interp *iPtr = (Interp *) interp;
2209    const char *newTail;
2210    Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2;
2211    Tcl_Command cmd;
2212    Command *cmdPtr;
2213    Tcl_HashEntry *hPtr, *oldHPtr;
2214    int isNew, result;
2215    Tcl_Obj *oldFullName;
2216    Tcl_DString newFullName;
2217
2218    /*
2219     * Find the existing command. An error is returned if cmdName can't be
2220     * found.
2221     */
2222
2223    cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0);
2224    cmdPtr = (Command *) cmd;
2225    if (cmdPtr == NULL) {
2226        Tcl_AppendResult(interp, "can't ",
2227                ((newName == NULL)||(*newName == '\0'))? "delete":"rename",
2228                " \"", oldName, "\": command doesn't exist", NULL);
2229        return TCL_ERROR;
2230    }
2231    cmdNsPtr = cmdPtr->nsPtr;
2232    oldFullName = Tcl_NewObj();
2233    Tcl_IncrRefCount(oldFullName);
2234    Tcl_GetCommandFullName(interp, cmd, oldFullName);
2235
2236    /*
2237     * If the new command name is NULL or empty, delete the command. Do this
2238     * with Tcl_DeleteCommandFromToken, since we already have the command.
2239     */
2240
2241    if ((newName == NULL) || (*newName == '\0')) {
2242        Tcl_DeleteCommandFromToken(interp, cmd);
2243        result = TCL_OK;
2244        goto done;
2245    }
2246
2247    /*
2248     * Make sure that the destination command does not already exist. The
2249     * rename operation is like creating a command, so we should automatically
2250     * create the containing namespaces just like Tcl_CreateCommand would.
2251     */
2252
2253    TclGetNamespaceForQualName(interp, newName, NULL,
2254            TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
2255
2256    if ((newNsPtr == NULL) || (newTail == NULL)) {
2257        Tcl_AppendResult(interp, "can't rename to \"", newName,
2258                "\": bad command name", NULL);
2259        result = TCL_ERROR;
2260        goto done;
2261    }
2262    if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) {
2263        Tcl_AppendResult(interp, "can't rename to \"", newName,
2264                 "\": command already exists", NULL);
2265        result = TCL_ERROR;
2266        goto done;
2267    }
2268
2269    /*
2270     * Warning: any changes done in the code here are likely to be needed in
2271     * Tcl_HideCommand() code too (until the common parts are extracted out).
2272     * - dl
2273     */
2274
2275    /*
2276     * Put the command in the new namespace so we can check for an alias loop.
2277     * Since we are adding a new command to a namespace, we must handle any
2278     * shadowing of the global commands that this might create.
2279     */
2280
2281    oldHPtr = cmdPtr->hPtr;
2282    hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &isNew);
2283    Tcl_SetHashValue(hPtr, cmdPtr);
2284    cmdPtr->hPtr = hPtr;
2285    cmdPtr->nsPtr = newNsPtr;
2286    TclResetShadowedCmdRefs(interp, cmdPtr);
2287
2288    /*
2289     * Now check for an alias loop. If we detect one, put everything back the
2290     * way it was and report the error.
2291     */
2292
2293    result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr);
2294    if (result != TCL_OK) {
2295        Tcl_DeleteHashEntry(cmdPtr->hPtr);
2296        cmdPtr->hPtr = oldHPtr;
2297        cmdPtr->nsPtr = cmdNsPtr;
2298        goto done;
2299    }
2300
2301    /*
2302     * The list of command exported from the namespace might have changed.
2303     * However, we do not need to recompute this just yet; next time we need
2304     * the info will be soon enough. These might refer to the same variable,
2305     * but that's no big deal.
2306     */
2307
2308    TclInvalidateNsCmdLookup(cmdNsPtr);
2309    TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
2310
2311    /*
2312     * Script for rename traces can delete the command "oldName". Therefore
2313     * increment the reference count for cmdPtr so that it's Command structure
2314     * is freed only towards the end of this function by calling
2315     * TclCleanupCommand.
2316     *
2317     * The trace function needs to get a fully qualified name for old and new
2318     * commands [Tcl bug #651271], or else there's no way for the trace
2319     * function to get the namespace from which the old command is being
2320     * renamed!
2321     */
2322
2323    Tcl_DStringInit(&newFullName);
2324    Tcl_DStringAppend(&newFullName, newNsPtr->fullName, -1);
2325    if (newNsPtr != iPtr->globalNsPtr) {
2326        Tcl_DStringAppend(&newFullName, "::", 2);
2327    }
2328    Tcl_DStringAppend(&newFullName, newTail, -1);
2329    cmdPtr->refCount++;
2330    CallCommandTraces(iPtr, cmdPtr, Tcl_GetString(oldFullName),
2331            Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME);
2332    Tcl_DStringFree(&newFullName);
2333
2334    /*
2335     * The new command name is okay, so remove the command from its current
2336     * namespace. This is like deleting the command, so bump the cmdEpoch to
2337     * invalidate any cached references to the command.
2338     */
2339
2340    Tcl_DeleteHashEntry(oldHPtr);
2341    cmdPtr->cmdEpoch++;
2342
2343    /*
2344     * If the command being renamed has a compile function, increment the
2345     * interpreter's compileEpoch to invalidate its compiled code. This makes
2346     * sure that we don't later try to execute old code compiled for the
2347     * now-renamed command.
2348     */
2349
2350    if (cmdPtr->compileProc != NULL) {
2351        iPtr->compileEpoch++;
2352    }
2353
2354    /*
2355     * Now free the Command structure, if the "oldName" command has been
2356     * deleted by invocation of rename traces.
2357     */
2358
2359    TclCleanupCommandMacro(cmdPtr);
2360    result = TCL_OK;
2361
2362  done:
2363    TclDecrRefCount(oldFullName);
2364    return result;
2365}
2366
2367/*
2368 *----------------------------------------------------------------------
2369 *
2370 * Tcl_SetCommandInfo --
2371 *
2372 *      Modifies various information about a Tcl command. Note that this
2373 *      function will not change a command's namespace; use TclRenameCommand
2374 *      to do that. Also, the isNativeObjectProc member of *infoPtr is
2375 *      ignored.
2376 *
2377 * Results:
2378 *      If cmdName exists in interp, then the information at *infoPtr is
2379 *      stored with the command in place of the current information and 1 is
2380 *      returned. If the command doesn't exist then 0 is returned.
2381 *
2382 * Side effects:
2383 *      None.
2384 *
2385 *----------------------------------------------------------------------
2386 */
2387
2388int
2389Tcl_SetCommandInfo(
2390    Tcl_Interp *interp,         /* Interpreter in which to look for
2391                                 * command. */
2392    const char *cmdName,        /* Name of desired command. */
2393    const Tcl_CmdInfo *infoPtr) /* Where to find information to store in the
2394                                 * command. */
2395{
2396    Tcl_Command cmd;
2397
2398    cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
2399    return Tcl_SetCommandInfoFromToken(cmd, infoPtr);
2400}
2401
2402/*
2403 *----------------------------------------------------------------------
2404 *
2405 * Tcl_SetCommandInfoFromToken --
2406 *
2407 *      Modifies various information about a Tcl command. Note that this
2408 *      function will not change a command's namespace; use TclRenameCommand
2409 *      to do that. Also, the isNativeObjectProc member of *infoPtr is
2410 *      ignored.
2411 *
2412 * Results:
2413 *      If cmdName exists in interp, then the information at *infoPtr is
2414 *      stored with the command in place of the current information and 1 is
2415 *      returned. If the command doesn't exist then 0 is returned.
2416 *
2417 * Side effects:
2418 *      None.
2419 *
2420 *----------------------------------------------------------------------
2421 */
2422
2423int
2424Tcl_SetCommandInfoFromToken(
2425    Tcl_Command cmd,
2426    const Tcl_CmdInfo *infoPtr)
2427{
2428    Command *cmdPtr;            /* Internal representation of the command */
2429
2430    if (cmd == (Tcl_Command) NULL) {
2431        return 0;
2432    }
2433
2434    /*
2435     * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
2436     */
2437
2438    cmdPtr = (Command *) cmd;
2439    cmdPtr->proc = infoPtr->proc;
2440    cmdPtr->clientData = infoPtr->clientData;
2441    if (infoPtr->objProc == NULL) {
2442        cmdPtr->objProc = TclInvokeStringCommand;
2443        cmdPtr->objClientData = cmdPtr;
2444    } else {
2445        cmdPtr->objProc = infoPtr->objProc;
2446        cmdPtr->objClientData = infoPtr->objClientData;
2447    }
2448    cmdPtr->deleteProc = infoPtr->deleteProc;
2449    cmdPtr->deleteData = infoPtr->deleteData;
2450    return 1;
2451}
2452
2453/*
2454 *----------------------------------------------------------------------
2455 *
2456 * Tcl_GetCommandInfo --
2457 *
2458 *      Returns various information about a Tcl command.
2459 *
2460 * Results:
2461 *      If cmdName exists in interp, then *infoPtr is modified to hold
2462 *      information about cmdName and 1 is returned. If the command doesn't
2463 *      exist then 0 is returned and *infoPtr isn't modified.
2464 *
2465 * Side effects:
2466 *      None.
2467 *
2468 *----------------------------------------------------------------------
2469 */
2470
2471int
2472Tcl_GetCommandInfo(
2473    Tcl_Interp *interp,         /* Interpreter in which to look for
2474                                 * command. */
2475    const char *cmdName,        /* Name of desired command. */
2476    Tcl_CmdInfo *infoPtr)       /* Where to store information about
2477                                 * command. */
2478{
2479    Tcl_Command cmd;
2480
2481    cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
2482    return Tcl_GetCommandInfoFromToken(cmd, infoPtr);
2483}
2484
2485/*
2486 *----------------------------------------------------------------------
2487 *
2488 * Tcl_GetCommandInfoFromToken --
2489 *
2490 *      Returns various information about a Tcl command.
2491 *
2492 * Results:
2493 *      Copies information from the command identified by 'cmd' into a
2494 *      caller-supplied structure and returns 1. If the 'cmd' is NULL, leaves
2495 *      the structure untouched and returns 0.
2496 *
2497 * Side effects:
2498 *      None.
2499 *
2500 *----------------------------------------------------------------------
2501 */
2502
2503int
2504Tcl_GetCommandInfoFromToken(
2505    Tcl_Command cmd,
2506    Tcl_CmdInfo *infoPtr)
2507{
2508    Command *cmdPtr;            /* Internal representation of the command */
2509
2510    if (cmd == (Tcl_Command) NULL) {
2511        return 0;
2512    }
2513
2514    /*
2515     * Set isNativeObjectProc 1 if objProc was registered by a call to
2516     * Tcl_CreateObjCommand. Otherwise set it to 0.
2517     */
2518
2519    cmdPtr = (Command *) cmd;
2520    infoPtr->isNativeObjectProc =
2521            (cmdPtr->objProc != TclInvokeStringCommand);
2522    infoPtr->objProc = cmdPtr->objProc;
2523    infoPtr->objClientData = cmdPtr->objClientData;
2524    infoPtr->proc = cmdPtr->proc;
2525    infoPtr->clientData = cmdPtr->clientData;
2526    infoPtr->deleteProc = cmdPtr->deleteProc;
2527    infoPtr->deleteData = cmdPtr->deleteData;
2528    infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
2529
2530    return 1;
2531}
2532
2533/*
2534 *----------------------------------------------------------------------
2535 *
2536 * Tcl_GetCommandName --
2537 *
2538 *      Given a token returned by Tcl_CreateCommand, this function returns the
2539 *      current name of the command (which may have changed due to renaming).
2540 *
2541 * Results:
2542 *      The return value is the name of the given command.
2543 *
2544 * Side effects:
2545 *      None.
2546 *
2547 *----------------------------------------------------------------------
2548 */
2549
2550const char *
2551Tcl_GetCommandName(
2552    Tcl_Interp *interp,         /* Interpreter containing the command. */
2553    Tcl_Command command)        /* Token for command returned by a previous
2554                                 * call to Tcl_CreateCommand. The command must
2555                                 * not have been deleted. */
2556{
2557    Command *cmdPtr = (Command *) command;
2558
2559    if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
2560        /*
2561         * This should only happen if command was "created" after the
2562         * interpreter began to be deleted, so there isn't really any command.
2563         * Just return an empty string.
2564         */
2565
2566        return "";
2567    }
2568
2569    return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
2570}
2571
2572/*
2573 *----------------------------------------------------------------------
2574 *
2575 * Tcl_GetCommandFullName --
2576 *
2577 *      Given a token returned by, e.g., Tcl_CreateCommand or Tcl_FindCommand,
2578 *      this function appends to an object the command's full name, qualified
2579 *      by a sequence of parent namespace names. The command's fully-qualified
2580 *      name may have changed due to renaming.
2581 *
2582 * Results:
2583 *      None.
2584 *
2585 * Side effects:
2586 *      The command's fully-qualified name is appended to the string
2587 *      representation of objPtr.
2588 *
2589 *----------------------------------------------------------------------
2590 */
2591
2592void
2593Tcl_GetCommandFullName(
2594    Tcl_Interp *interp,         /* Interpreter containing the command. */
2595    Tcl_Command command,        /* Token for command returned by a previous
2596                                 * call to Tcl_CreateCommand. The command must
2597                                 * not have been deleted. */
2598    Tcl_Obj *objPtr)            /* Points to the object onto which the
2599                                 * command's full name is appended. */
2600
2601{
2602    Interp *iPtr = (Interp *) interp;
2603    register Command *cmdPtr = (Command *) command;
2604    char *name;
2605
2606    /*
2607     * Add the full name of the containing namespace, followed by the "::"
2608     * separator, and the command name.
2609     */
2610
2611    if (cmdPtr != NULL) {
2612        if (cmdPtr->nsPtr != NULL) {
2613            Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1);
2614            if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
2615                Tcl_AppendToObj(objPtr, "::", 2);
2616            }
2617        }
2618        if (cmdPtr->hPtr != NULL) {
2619            name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
2620            Tcl_AppendToObj(objPtr, name, -1);
2621        }
2622    }
2623}
2624
2625/*
2626 *----------------------------------------------------------------------
2627 *
2628 * Tcl_DeleteCommand --
2629 *
2630 *      Remove the given command from the given interpreter.
2631 *
2632 * Results:
2633 *      0 is returned if the command was deleted successfully. -1 is returned
2634 *      if there didn't exist a command by that name.
2635 *
2636 * Side effects:
2637 *      cmdName will no longer be recognized as a valid command for interp.
2638 *
2639 *----------------------------------------------------------------------
2640 */
2641
2642int
2643Tcl_DeleteCommand(
2644    Tcl_Interp *interp,         /* Token for command interpreter (returned by
2645                                 * a previous Tcl_CreateInterp call). */
2646    const char *cmdName)        /* Name of command to remove. */
2647{
2648    Tcl_Command cmd;
2649
2650    /*
2651     * Find the desired command and delete it.
2652     */
2653
2654    cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
2655    if (cmd == (Tcl_Command) NULL) {
2656        return -1;
2657    }
2658    return Tcl_DeleteCommandFromToken(interp, cmd);
2659}
2660
2661/*
2662 *----------------------------------------------------------------------
2663 *
2664 * Tcl_DeleteCommandFromToken --
2665 *
2666 *      Removes the given command from the given interpreter. This function
2667 *      resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead of
2668 *      a command name for efficiency.
2669 *
2670 * Results:
2671 *      0 is returned if the command was deleted successfully. -1 is returned
2672 *      if there didn't exist a command by that name.
2673 *
2674 * Side effects:
2675 *      The command specified by "cmd" will no longer be recognized as a valid
2676 *      command for "interp".
2677 *
2678 *----------------------------------------------------------------------
2679 */
2680
2681int
2682Tcl_DeleteCommandFromToken(
2683    Tcl_Interp *interp,         /* Token for command interpreter returned by a
2684                                 * previous call to Tcl_CreateInterp. */
2685    Tcl_Command cmd)            /* Token for command to delete. */
2686{
2687    Interp *iPtr = (Interp *) interp;
2688    Command *cmdPtr = (Command *) cmd;
2689    ImportRef *refPtr, *nextRefPtr;
2690    Tcl_Command importCmd;
2691
2692    /*
2693     * Bump the command epoch counter. This will invalidate all cached
2694     * references that point to this command.
2695     */
2696
2697    cmdPtr->cmdEpoch++;
2698
2699    /*
2700     * The code here is tricky. We can't delete the hash table entry before
2701     * invoking the deletion callback because there are cases where the
2702     * deletion callback needs to invoke the command (e.g. object systems such
2703     * as OTcl). However, this means that the callback could try to delete or
2704     * rename the command. The deleted flag allows us to detect these cases
2705     * and skip nested deletes.
2706     */
2707
2708    if (cmdPtr->flags & CMD_IS_DELETED) {
2709        /*
2710         * Another deletion is already in progress. Remove the hash table
2711         * entry now, but don't invoke a callback or free the command
2712         * structure. Take care to only remove the hash entry if it has not
2713         * already been removed; otherwise if we manage to hit this function
2714         * three times, everything goes up in smoke. [Bug 1220058]
2715         */
2716
2717        if (cmdPtr->hPtr != NULL) {
2718            Tcl_DeleteHashEntry(cmdPtr->hPtr);
2719            cmdPtr->hPtr = NULL;
2720        }
2721        return 0;
2722    }
2723
2724    /*
2725     * We must delete this command, even though both traces and delete procs
2726     * may try to avoid this (renaming the command etc). Also traces and
2727     * delete procs may try to delete the command themsevles. This flag
2728     * declares that a delete is in progress and that recursive deletes should
2729     * be ignored.
2730     */
2731
2732    cmdPtr->flags |= CMD_IS_DELETED;
2733
2734    /*
2735     * Call trace functions for the command being deleted. Then delete its
2736     * traces.
2737     */
2738
2739    if (cmdPtr->tracePtr != NULL) {
2740        CommandTrace *tracePtr;
2741        CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);
2742
2743        /*
2744         * Now delete these traces.
2745         */
2746
2747        tracePtr = cmdPtr->tracePtr;
2748        while (tracePtr != NULL) {
2749            CommandTrace *nextPtr = tracePtr->nextPtr;
2750            if ((--tracePtr->refCount) <= 0) {
2751                ckfree((char *) tracePtr);
2752            }
2753            tracePtr = nextPtr;
2754        }
2755        cmdPtr->tracePtr = NULL;
2756    }
2757
2758    /*
2759     * The list of command exported from the namespace might have changed.
2760     * However, we do not need to recompute this just yet; next time we need
2761     * the info will be soon enough.
2762     */
2763
2764    TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
2765
2766    /*
2767     * If the command being deleted has a compile function, increment the
2768     * interpreter's compileEpoch to invalidate its compiled code. This makes
2769     * sure that we don't later try to execute old code compiled with
2770     * command-specific (i.e., inline) bytecodes for the now-deleted command.
2771     * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose
2772     * compilation epoch doesn't match is recompiled.
2773     */
2774
2775    if (cmdPtr->compileProc != NULL) {
2776        iPtr->compileEpoch++;
2777    }
2778
2779    if (cmdPtr->deleteProc != NULL) {
2780        /*
2781         * Delete the command's client data. If this was an imported command
2782         * created when a command was imported into a namespace, this client
2783         * data will be a pointer to a ImportedCmdData structure describing
2784         * the "real" command that this imported command refers to.
2785         */
2786
2787        /*
2788         * If you are getting a crash during the call to deleteProc and
2789         * cmdPtr->deleteProc is a pointer to the function free(), the most
2790         * likely cause is that your extension allocated memory for the
2791         * clientData argument to Tcl_CreateObjCommand() with the ckalloc()
2792         * macro and you are now trying to deallocate this memory with free()
2793         * instead of ckfree(). You should pass a pointer to your own method
2794         * that calls ckfree().
2795         */
2796
2797        (*cmdPtr->deleteProc)(cmdPtr->deleteData);
2798    }
2799
2800    /*
2801     * If this command was imported into other namespaces, then imported
2802     * commands were created that refer back to this command. Delete these
2803     * imported commands now.
2804     */
2805
2806    for (refPtr = cmdPtr->importRefPtr;  refPtr != NULL;
2807            refPtr = nextRefPtr) {
2808        nextRefPtr = refPtr->nextPtr;
2809        importCmd = (Tcl_Command) refPtr->importedCmdPtr;
2810        Tcl_DeleteCommandFromToken(interp, importCmd);
2811    }
2812
2813    /*
2814     * Don't use hPtr to delete the hash entry here, because it's possible
2815     * that the deletion callback renamed the command. Instead, use
2816     * cmdPtr->hptr, and make sure that no-one else has already deleted the
2817     * hash entry.
2818     */
2819
2820    if (cmdPtr->hPtr != NULL) {
2821        Tcl_DeleteHashEntry(cmdPtr->hPtr);
2822        cmdPtr->hPtr = NULL;
2823    }
2824
2825    /*
2826     * Mark the Command structure as no longer valid. This allows
2827     * TclExecuteByteCode to recognize when a Command has logically been
2828     * deleted and a pointer to this Command structure cached in a CmdName
2829     * object is invalid. TclExecuteByteCode will look up the command again in
2830     * the interpreter's command hashtable.
2831     */
2832
2833    cmdPtr->objProc = NULL;
2834
2835    /*
2836     * Now free the Command structure, unless there is another reference to it
2837     * from a CmdName Tcl object in some ByteCode code sequence. In that case,
2838     * delay the cleanup until all references are either discarded (when a
2839     * ByteCode is freed) or replaced by a new reference (when a cached
2840     * CmdName Command reference is found to be invalid and TclExecuteByteCode
2841     * looks up the command in the command hashtable).
2842     */
2843
2844    TclCleanupCommandMacro(cmdPtr);
2845    return 0;
2846}
2847
2848static char *
2849CallCommandTraces(
2850    Interp *iPtr,               /* Interpreter containing command. */
2851    Command *cmdPtr,            /* Command whose traces are to be invoked. */
2852    const char *oldName,        /* Command's old name, or NULL if we must get
2853                                 * the name from cmdPtr */
2854    const char *newName,        /* Command's new name, or NULL if the command
2855                                 * is not being renamed */
2856    int flags)                  /* Flags indicating the type of traces to
2857                                 * trigger, either TCL_TRACE_DELETE or
2858                                 * TCL_TRACE_RENAME. */
2859{
2860    register CommandTrace *tracePtr;
2861    ActiveCommandTrace active;
2862    char *result;
2863    Tcl_Obj *oldNamePtr = NULL;
2864    Tcl_InterpState state = NULL;
2865
2866    if (cmdPtr->flags & CMD_TRACE_ACTIVE) {
2867        /*
2868         * While a rename trace is active, we will not process any more rename
2869         * traces; while a delete trace is active we will never reach here -
2870         * because Tcl_DeleteCommandFromToken checks for the condition
2871         * (cmdPtr->flags & CMD_IS_DELETED) and returns immediately when a
2872         * command deletion is in progress. For all other traces, delete
2873         * traces will not be invoked but a call to TraceCommandProc will
2874         * ensure that tracePtr->clientData is freed whenever the command
2875         * "oldName" is deleted.
2876         */
2877
2878        if (cmdPtr->flags & TCL_TRACE_RENAME) {
2879            flags &= ~TCL_TRACE_RENAME;
2880        }
2881        if (flags == 0) {
2882            return NULL;
2883        }
2884    }
2885    cmdPtr->flags |= CMD_TRACE_ACTIVE;
2886    cmdPtr->refCount++;
2887
2888    result = NULL;
2889    active.nextPtr = iPtr->activeCmdTracePtr;
2890    active.reverseScan = 0;
2891    iPtr->activeCmdTracePtr = &active;
2892
2893    if (flags & TCL_TRACE_DELETE) {
2894        flags |= TCL_TRACE_DESTROYED;
2895    }
2896    active.cmdPtr = cmdPtr;
2897
2898    Tcl_Preserve(iPtr);
2899
2900    for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL;
2901            tracePtr = active.nextTracePtr) {
2902        active.nextTracePtr = tracePtr->nextPtr;
2903        if (!(tracePtr->flags & flags)) {
2904            continue;
2905        }
2906        cmdPtr->flags |= tracePtr->flags;
2907        if (oldName == NULL) {
2908            TclNewObj(oldNamePtr);
2909            Tcl_IncrRefCount(oldNamePtr);
2910            Tcl_GetCommandFullName((Tcl_Interp *) iPtr,
2911                    (Tcl_Command) cmdPtr, oldNamePtr);
2912            oldName = TclGetString(oldNamePtr);
2913        }
2914        tracePtr->refCount++;
2915        if (state == NULL) {
2916            state = Tcl_SaveInterpState((Tcl_Interp *) iPtr, TCL_OK);
2917        }
2918        (*tracePtr->traceProc)(tracePtr->clientData,
2919                (Tcl_Interp *) iPtr, oldName, newName, flags);
2920        cmdPtr->flags &= ~tracePtr->flags;
2921        if ((--tracePtr->refCount) <= 0) {
2922            ckfree((char *) tracePtr);
2923        }
2924    }
2925
2926    if (state) {
2927        Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state);
2928    }
2929
2930    /*
2931     * If a new object was created to hold the full oldName, free it now.
2932     */
2933
2934    if (oldNamePtr != NULL) {
2935        TclDecrRefCount(oldNamePtr);
2936    }
2937
2938    /*
2939     * Restore the variable's flags, remove the record of our active traces,
2940     * and then return.
2941     */
2942
2943    cmdPtr->flags &= ~CMD_TRACE_ACTIVE;
2944    cmdPtr->refCount--;
2945    iPtr->activeCmdTracePtr = active.nextPtr;
2946    Tcl_Release(iPtr);
2947    return result;
2948}
2949
2950/*
2951 *----------------------------------------------------------------------
2952 *
2953 * GetCommandSource --
2954 *
2955 *      This function returns a Tcl_Obj with the full source string for the
2956 *      command. This insures that traces get a correct NUL-terminated command
2957 *      string.
2958 *
2959 *----------------------------------------------------------------------
2960 */
2961
2962static Tcl_Obj *
2963GetCommandSource(
2964    Interp *iPtr,
2965    const char *command,
2966    int numChars,
2967    int objc,
2968    Tcl_Obj *const objv[])
2969{
2970    if (!command) {
2971        return Tcl_NewListObj(objc, objv);
2972    }
2973    if (command == (char *) -1) {
2974        command = TclGetSrcInfoForCmd(iPtr, &numChars);
2975    }
2976    return Tcl_NewStringObj(command, numChars);
2977}
2978
2979/*
2980 *----------------------------------------------------------------------
2981 *
2982 * TclCleanupCommand --
2983 *
2984 *      This function frees up a Command structure unless it is still
2985 *      referenced from an interpreter's command hashtable or from a CmdName
2986 *      Tcl object representing the name of a command in a ByteCode
2987 *      instruction sequence.
2988 *
2989 * Results:
2990 *      None.
2991 *
2992 * Side effects:
2993 *      Memory gets freed unless a reference to the Command structure still
2994 *      exists. In that case the cleanup is delayed until the command is
2995 *      deleted or when the last ByteCode referring to it is freed.
2996 *
2997 *----------------------------------------------------------------------
2998 */
2999
3000void
3001TclCleanupCommand(
3002    register Command *cmdPtr)   /* Points to the Command structure to
3003                                 * be freed. */
3004{
3005    cmdPtr->refCount--;
3006    if (cmdPtr->refCount <= 0) {
3007        ckfree((char *) cmdPtr);
3008    }
3009}
3010
3011/*
3012 *----------------------------------------------------------------------
3013 *
3014 * Tcl_CreateMathFunc --
3015 *
3016 *      Creates a new math function for expressions in a given interpreter.
3017 *
3018 * Results:
3019 *      None.
3020 *
3021 * Side effects:
3022 *      The Tcl function defined by "name" is created or redefined. If the
3023 *      function already exists then its definition is replaced; this includes
3024 *      the builtin functions. Redefining a builtin function forces all
3025 *      existing code to be invalidated since that code may be compiled using
3026 *      an instruction specific to the replaced function. In addition,
3027 *      redefioning a non-builtin function will force existing code to be
3028 *      invalidated if the number of arguments has changed.
3029 *
3030 *----------------------------------------------------------------------
3031 */
3032
3033void
3034Tcl_CreateMathFunc(
3035    Tcl_Interp *interp,         /* Interpreter in which function is to be
3036                                 * available. */
3037    const char *name,           /* Name of function (e.g. "sin"). */
3038    int numArgs,                /* Nnumber of arguments required by
3039                                 * function. */
3040    Tcl_ValueType *argTypes,    /* Array of types acceptable for each
3041                                 * argument. */
3042    Tcl_MathProc *proc,         /* C function that implements the math
3043                                 * function. */
3044    ClientData clientData)      /* Additional value to pass to the
3045                                 * function. */
3046{
3047    Tcl_DString bigName;
3048    OldMathFuncData *data = (OldMathFuncData *)
3049            ckalloc(sizeof(OldMathFuncData));
3050
3051    data->proc = proc;
3052    data->numArgs = numArgs;
3053    data->argTypes = (Tcl_ValueType *)
3054            ckalloc(numArgs * sizeof(Tcl_ValueType));
3055    memcpy(data->argTypes, argTypes, numArgs * sizeof(Tcl_ValueType));
3056    data->clientData = clientData;
3057
3058    Tcl_DStringInit(&bigName);
3059    Tcl_DStringAppend(&bigName, "::tcl::mathfunc::", -1);
3060    Tcl_DStringAppend(&bigName, name, -1);
3061
3062    Tcl_CreateObjCommand(interp, Tcl_DStringValue(&bigName),
3063            OldMathFuncProc, data, OldMathFuncDeleteProc);
3064    Tcl_DStringFree(&bigName);
3065}
3066
3067/*
3068 *----------------------------------------------------------------------
3069 *
3070 * OldMathFuncProc --
3071 *
3072 *      Dispatch to a math function created with Tcl_CreateMathFunc
3073 *
3074 * Results:
3075 *      Returns a standard Tcl result.
3076 *
3077 * Side effects:
3078 *      Whatever the math function does.
3079 *
3080 *----------------------------------------------------------------------
3081 */
3082
3083static int
3084OldMathFuncProc(
3085    ClientData clientData,      /* Ponter to OldMathFuncData describing the
3086                                 * function being called */
3087    Tcl_Interp *interp,         /* Tcl interpreter */
3088    int objc,                   /* Actual parameter count */
3089    Tcl_Obj *const *objv)       /* Parameter vector */
3090{
3091    Tcl_Obj *valuePtr;
3092    OldMathFuncData *dataPtr = clientData;
3093    Tcl_Value funcResult, *args;
3094    int result;
3095    int j, k;
3096    double d;
3097
3098    /*
3099     * Check argument count.
3100     */
3101
3102    if (objc != dataPtr->numArgs + 1) {
3103        MathFuncWrongNumArgs(interp, dataPtr->numArgs+1, objc, objv);
3104        return TCL_ERROR;
3105    }
3106
3107    /*
3108     * Convert arguments from Tcl_Obj's to Tcl_Value's.
3109     */
3110
3111    args = (Tcl_Value *) ckalloc(dataPtr->numArgs * sizeof(Tcl_Value));
3112    for (j = 1, k = 0; j < objc; ++j, ++k) {
3113
3114        /* TODO: Convert to TclGetNumberFromObj() ? */
3115        valuePtr = objv[j];
3116        result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d);
3117#ifdef ACCEPT_NAN
3118        if ((result != TCL_OK) && (valuePtr->typePtr == &tclDoubleType)) {
3119            d = valuePtr->internalRep.doubleValue;
3120            result = TCL_OK;
3121        }
3122#endif
3123        if (result != TCL_OK) {
3124            /*
3125             * We have a non-numeric argument.
3126             */
3127
3128            Tcl_SetObjResult(interp, Tcl_NewStringObj(
3129                    "argument to math function didn't have numeric value",-1));
3130            TclCheckBadOctal(interp, Tcl_GetString(valuePtr));
3131            ckfree((char *)args);
3132            return TCL_ERROR;
3133        }
3134
3135        /*
3136         * Copy the object's numeric value to the argument record, converting
3137         * it if necessary.
3138         *
3139         * NOTE: no bignum support; use the new mathfunc interface for that.
3140         */
3141
3142        args[k].type = dataPtr->argTypes[k];
3143        switch (args[k].type) {
3144        case TCL_EITHER:
3145            if (Tcl_GetLongFromObj(NULL, valuePtr, &(args[k].intValue))
3146                    == TCL_OK) {
3147                args[k].type = TCL_INT;
3148                break;
3149            }
3150            if (Tcl_GetWideIntFromObj(interp, valuePtr, &(args[k].wideValue))
3151                    == TCL_OK) {
3152                args[k].type = TCL_WIDE_INT;
3153                break;
3154            }
3155            args[k].type = TCL_DOUBLE;
3156            /* FALLTHROUGH */
3157
3158        case TCL_DOUBLE:
3159            args[k].doubleValue = d;
3160            break;
3161        case TCL_INT:
3162            if (ExprIntFunc(NULL, interp, 2, &(objv[j-1])) != TCL_OK) {
3163                ckfree((char *)args);
3164                return TCL_ERROR;
3165            }
3166            valuePtr = Tcl_GetObjResult(interp);
3167            Tcl_GetLongFromObj(NULL, valuePtr, &(args[k].intValue));
3168            Tcl_ResetResult(interp);
3169            break;
3170        case TCL_WIDE_INT:
3171            if (ExprWideFunc(NULL, interp, 2, &(objv[j-1])) != TCL_OK) {
3172                ckfree((char *)args);
3173                return TCL_ERROR;
3174            }
3175            valuePtr = Tcl_GetObjResult(interp);
3176            Tcl_GetWideIntFromObj(NULL, valuePtr, &(args[k].wideValue));
3177            Tcl_ResetResult(interp);
3178            break;
3179        }
3180    }
3181
3182    /*
3183     * Call the function.
3184     */
3185
3186    errno = 0;
3187    result = (*dataPtr->proc)(dataPtr->clientData, interp, args, &funcResult);
3188    ckfree((char *)args);
3189    if (result != TCL_OK) {
3190        return result;
3191    }
3192
3193    /*
3194     * Return the result of the call.
3195     */
3196
3197    if (funcResult.type == TCL_INT) {
3198        TclNewLongObj(valuePtr, funcResult.intValue);
3199    } else if (funcResult.type == TCL_WIDE_INT) {
3200        valuePtr = Tcl_NewWideIntObj(funcResult.wideValue);
3201    } else {
3202        return CheckDoubleResult(interp, funcResult.doubleValue);
3203    }
3204    Tcl_SetObjResult(interp, valuePtr);
3205    return TCL_OK;
3206}
3207
3208/*
3209 *----------------------------------------------------------------------
3210 *
3211 * OldMathFuncDeleteProc --
3212 *
3213 *      Cleans up after deleting a math function registered with
3214 *      Tcl_CreateMathFunc
3215 *
3216 * Results:
3217 *      None.
3218 *
3219 * Side effects:
3220 *      Frees allocated memory.
3221 *
3222 *----------------------------------------------------------------------
3223 */
3224
3225static void
3226OldMathFuncDeleteProc(
3227     ClientData clientData)
3228{
3229    OldMathFuncData *dataPtr = clientData;
3230
3231    ckfree((void *) dataPtr->argTypes);
3232    ckfree((void *) dataPtr);
3233}
3234
3235/*
3236 *----------------------------------------------------------------------
3237 *
3238 * Tcl_GetMathFuncInfo --
3239 *
3240 *      Discovers how a particular math function was created in a given
3241 *      interpreter.
3242 *
3243 * Results:
3244 *      TCL_OK if it succeeds, TCL_ERROR else (leaving an error message in the
3245 *      interpreter result if that happens.)
3246 *
3247 * Side effects:
3248 *      If this function succeeds, the variables pointed to by the numArgsPtr
3249 *      and argTypePtr arguments will be updated to detail the arguments
3250 *      allowed by the function. The variable pointed to by the procPtr
3251 *      argument will be set to NULL if the function is a builtin function,
3252 *      and will be set to the address of the C function used to implement the
3253 *      math function otherwise (in which case the variable pointed to by the
3254 *      clientDataPtr argument will also be updated.)
3255 *
3256 *----------------------------------------------------------------------
3257 */
3258
3259int
3260Tcl_GetMathFuncInfo(
3261    Tcl_Interp *interp,
3262    const char *name,
3263    int *numArgsPtr,
3264    Tcl_ValueType **argTypesPtr,
3265    Tcl_MathProc **procPtr,
3266    ClientData *clientDataPtr)
3267{
3268    Tcl_Obj *cmdNameObj;
3269    Command *cmdPtr;
3270
3271    /*
3272     * Get the command that implements the math function.
3273     */
3274
3275    TclNewLiteralStringObj(cmdNameObj, "tcl::mathfunc::");
3276    Tcl_AppendToObj(cmdNameObj, name, -1);
3277    Tcl_IncrRefCount(cmdNameObj);
3278    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdNameObj);
3279    Tcl_DecrRefCount(cmdNameObj);
3280
3281    /*
3282     * Report unknown functions.
3283     */
3284
3285    if (cmdPtr == NULL) {
3286        Tcl_Obj *message;
3287
3288        TclNewLiteralStringObj(message, "unknown math function \"");
3289        Tcl_AppendToObj(message, name, -1);
3290        Tcl_AppendToObj(message, "\"", 1);
3291        Tcl_SetObjResult(interp, message);
3292        *numArgsPtr = -1;
3293        *argTypesPtr = NULL;
3294        *procPtr = NULL;
3295        *clientDataPtr = NULL;
3296        return TCL_ERROR;
3297    }
3298
3299    /*
3300     * Retrieve function info for user defined functions; return dummy
3301     * information for builtins.
3302     */
3303
3304    if (cmdPtr->objProc == &OldMathFuncProc) {
3305        OldMathFuncData *dataPtr = cmdPtr->clientData;
3306
3307        *procPtr = dataPtr->proc;
3308        *numArgsPtr = dataPtr->numArgs;
3309        *argTypesPtr = dataPtr->argTypes;
3310        *clientDataPtr = dataPtr->clientData;
3311    } else {
3312        *procPtr = NULL;
3313        *numArgsPtr = -1;
3314        *argTypesPtr = NULL;
3315        *procPtr = NULL;
3316        *clientDataPtr = NULL;
3317    }
3318    return TCL_OK;
3319}
3320
3321/*
3322 *----------------------------------------------------------------------
3323 *
3324 * Tcl_ListMathFuncs --
3325 *
3326 *      Produces a list of all the math functions defined in a given
3327 *      interpreter.
3328 *
3329 * Results:
3330 *      A pointer to a Tcl_Obj structure with a reference count of zero, or
3331 *      NULL in the case of an error (in which case a suitable error message
3332 *      will be left in the interpreter result.)
3333 *
3334 * Side effects:
3335 *      None.
3336 *
3337 *----------------------------------------------------------------------
3338 */
3339
3340Tcl_Obj *
3341Tcl_ListMathFuncs(
3342    Tcl_Interp *interp,
3343    const char *pattern)
3344{
3345    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
3346    Namespace *nsPtr;
3347    Namespace *dummy1NsPtr;
3348    Namespace *dummy2NsPtr;
3349    const char *dummyNamePtr;
3350    Tcl_Obj *result = Tcl_NewObj();
3351
3352    TclGetNamespaceForQualName(interp, "::tcl::mathfunc",
3353            globalNsPtr, TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY,
3354            &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &dummyNamePtr);
3355    if (nsPtr == NULL) {
3356        return result;
3357    }
3358
3359    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
3360        if (Tcl_FindHashEntry(&nsPtr->cmdTable, pattern) != NULL) {
3361            Tcl_ListObjAppendElement(NULL, result,
3362                    Tcl_NewStringObj(pattern, -1));
3363        }
3364    } else {
3365        Tcl_HashSearch cmdHashSearch;
3366        Tcl_HashEntry *cmdHashEntry =
3367                Tcl_FirstHashEntry(&nsPtr->cmdTable,&cmdHashSearch);
3368
3369        for (; cmdHashEntry != NULL;
3370                cmdHashEntry = Tcl_NextHashEntry(&cmdHashSearch)) {
3371            const char *cmdNamePtr =
3372                    Tcl_GetHashKey(&nsPtr->cmdTable, cmdHashEntry);
3373
3374            if (pattern == NULL || Tcl_StringMatch(cmdNamePtr, pattern)) {
3375                Tcl_ListObjAppendElement(NULL, result,
3376                        Tcl_NewStringObj(cmdNamePtr, -1));
3377            }
3378        }
3379    }
3380    return result;
3381}
3382
3383/*
3384 *----------------------------------------------------------------------
3385 *
3386 * TclInterpReady --
3387 *
3388 *      Check if an interpreter is ready to eval commands or scripts, i.e., if
3389 *      it was not deleted and if the nesting level is not too high.
3390 *
3391 * Results:
3392 *      The return value is TCL_OK if it the interpreter is ready, TCL_ERROR
3393 *      otherwise.
3394 *
3395 * Side effects:
3396 *      The interpreters object and string results are cleared.
3397 *
3398 *----------------------------------------------------------------------
3399 */
3400
3401int
3402TclInterpReady(
3403    Tcl_Interp *interp)
3404{
3405    int localInt; /* used for checking the stack */
3406    register Interp *iPtr = (Interp *) interp;
3407
3408    /*
3409     * Reset both the interpreter's string and object results and clear out
3410     * any previous error information.
3411     */
3412
3413    Tcl_ResetResult(interp);
3414
3415    /*
3416     * If the interpreter has been deleted, return an error.
3417     */
3418
3419    if (iPtr->flags & DELETED) {
3420        Tcl_ResetResult(interp);
3421        Tcl_AppendResult(interp,
3422                "attempt to call eval in deleted interpreter", NULL);
3423        Tcl_SetErrorCode(interp, "TCL", "IDELETE",
3424                "attempt to call eval in deleted interpreter", NULL);
3425        return TCL_ERROR;
3426    }
3427
3428    /*
3429     * Check depth of nested calls to Tcl_Eval: if this gets too large, it's
3430     * probably because of an infinite loop somewhere.
3431     */
3432
3433    if (((iPtr->numLevels) <= iPtr->maxNestingDepth)
3434            && CheckCStack(iPtr, &localInt)) {
3435        return TCL_OK;
3436    }
3437
3438    if (!CheckCStack(iPtr, &localInt)) {
3439        Tcl_AppendResult(interp,
3440                "out of stack space (infinite loop?)", NULL);
3441    } else {
3442        Tcl_AppendResult(interp,
3443                "too many nested evaluations (infinite loop?)", NULL);
3444    }
3445    return TCL_ERROR;
3446}
3447
3448/*
3449 *----------------------------------------------------------------------
3450 *
3451 * TclEvalObjvInternal
3452 *
3453 *      This function evaluates a Tcl command that has already been parsed
3454 *      into words, with one Tcl_Obj holding each word. The caller is
3455 *      responsible for managing the iPtr->numLevels.
3456 *
3457 *      TclEvalObjvInternal is the backend for Tcl_EvalObjv, the bytecode
3458 *      engine also calls it directly.
3459 *
3460 * Results:
3461 *      The return value is a standard Tcl completion code such as TCL_OK or
3462 *      TCL_ERROR. A result or error message is left in interp's result. If an
3463 *      error occurs, this function does NOT add any information to the
3464 *      errorInfo variable.
3465 *
3466 * Side effects:
3467 *      Depends on the command.
3468 *
3469 *----------------------------------------------------------------------
3470 */
3471
3472int
3473TclEvalObjvInternal(
3474    Tcl_Interp *interp,         /* Interpreter in which to evaluate the
3475                                 * command. Also used for error reporting. */
3476    int objc,                   /* Number of words in command. */
3477    Tcl_Obj *const objv[],      /* An array of pointers to objects that are
3478                                 * the words that make up the command. */
3479    const char *command,        /* Points to the beginning of the string
3480                                 * representation of the command; this is used
3481                                 * for traces. NULL if the string
3482                                 * representation of the command is unknown is
3483                                 * to be generated from (objc,objv), -1 if it
3484                                 * is to be generated from bytecode
3485                                 * source. This is only needed the traces. */
3486    int length,                 /* Number of bytes in command; if -1, all
3487                                 * characters up to the first null byte are
3488                                 * used. */
3489    int flags)                  /* Collection of OR-ed bits that control the
3490                                 * evaluation of the script. Only
3491                                 * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
3492                                 * currently supported. */
3493{
3494    Command *cmdPtr;
3495    Interp *iPtr = (Interp *) interp;
3496    Tcl_Obj **newObjv;
3497    int i;
3498    CallFrame *savedVarFramePtr = NULL;
3499    CallFrame *varFramePtr = iPtr->varFramePtr;
3500    int code = TCL_OK;
3501    int traceCode = TCL_OK;
3502    int checkTraces = 1, traced;
3503    Namespace *savedNsPtr = NULL;
3504    Namespace *lookupNsPtr = iPtr->lookupNsPtr;
3505    Tcl_Obj *commandPtr = NULL;
3506
3507    if (TclInterpReady(interp) == TCL_ERROR) {
3508        return TCL_ERROR;
3509    }
3510
3511    if (objc == 0) {
3512        return TCL_OK;
3513    }
3514
3515    /*
3516     * If any execution traces rename or delete the current command, we may
3517     * need (at most) two passes here.
3518     */
3519
3520  reparseBecauseOfTraces:
3521
3522    /*
3523     * Configure evaluation context to match the requested flags.
3524     */
3525
3526    if (flags) {
3527        if (flags & TCL_EVAL_INVOKE) {
3528            savedNsPtr = varFramePtr->nsPtr;
3529            if (lookupNsPtr) {
3530                varFramePtr->nsPtr = lookupNsPtr;
3531                iPtr->lookupNsPtr = NULL;
3532            } else {
3533                varFramePtr->nsPtr = iPtr->globalNsPtr;
3534            }
3535        } else if ((flags & TCL_EVAL_GLOBAL)
3536                && (varFramePtr != iPtr->rootFramePtr) && !savedVarFramePtr) {
3537            varFramePtr = iPtr->rootFramePtr;
3538            savedVarFramePtr = iPtr->varFramePtr;
3539            iPtr->varFramePtr = varFramePtr;
3540        }
3541    }
3542
3543    /*
3544     * Find the function to execute this command. If there isn't one, then see
3545     * if there is an unknown command handler registered for this namespace.
3546     * If so, create a new word array with the handler as the first words and
3547     * the original command words as arguments. Then call ourselves
3548     * recursively to execute it.
3549     */
3550
3551    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
3552    if (!cmdPtr) {
3553        goto notFound;
3554    }
3555
3556    if (savedNsPtr) {
3557        varFramePtr->nsPtr = savedNsPtr;
3558    } else if (iPtr->ensembleRewrite.sourceObjs) {
3559        /*
3560         * TCL_EVAL_INVOKE was not set: clear rewrite rules
3561         */
3562
3563        iPtr->ensembleRewrite.sourceObjs = NULL;
3564    }
3565
3566    /*
3567     * Call trace functions if needed.
3568     */
3569
3570    traced = (iPtr->tracePtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES));
3571    if (traced && checkTraces) {
3572        int cmdEpoch = cmdPtr->cmdEpoch;
3573        int newEpoch;
3574
3575        /*
3576         * Insure that we have a correct nul-terminated command string for the
3577         * trace code.
3578         */
3579
3580        commandPtr = GetCommandSource(iPtr, command, length, objc, objv);
3581        command = TclGetStringFromObj(commandPtr, &length);
3582
3583        /*
3584         * Execute any command or execution traces. Note that we bump up the
3585         * command's reference count for the duration of the calling of the
3586         * traces so that the structure doesn't go away underneath our feet.
3587         */
3588
3589        cmdPtr->refCount++;
3590        if (iPtr->tracePtr && (traceCode == TCL_OK)) {
3591            traceCode = TclCheckInterpTraces(interp, command, length,
3592                    cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
3593        }
3594        if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
3595            traceCode = TclCheckExecutionTraces(interp, command, length,
3596                    cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
3597        }
3598        newEpoch = cmdPtr->cmdEpoch;
3599        TclCleanupCommandMacro(cmdPtr);
3600
3601        /*
3602         * If the traces modified/deleted the command or any existing traces,
3603         * they will update the command's epoch. When that happens, set
3604         * checkTraces is set to 0 to prevent the re-calling of traces (and
3605         * any possible infinite loop) and we go back to re-find the command
3606         * implementation.
3607         */
3608
3609        if (cmdEpoch != newEpoch) {
3610            checkTraces = 0;
3611            if (commandPtr) {
3612                Tcl_DecrRefCount(commandPtr);
3613            }
3614            goto reparseBecauseOfTraces;
3615        }
3616    }
3617
3618    if (TCL_DTRACE_CMD_ARGS_ENABLED()) {
3619        char *a[10];
3620        int i = 0;
3621
3622        while (i < 10) {
3623            a[i] = i < objc ? TclGetString(objv[i]) : NULL; i++;
3624        }
3625        TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
3626                a[8], a[9]);
3627    }
3628    if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) {
3629        Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
3630        char *a[4]; int i[2];
3631
3632        TclDTraceInfo(info, a, i);
3633        TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1]);
3634        TclDecrRefCount(info);
3635    }
3636
3637    /*
3638     * Finally, invoke the command's Tcl_ObjCmdProc.
3639     */
3640
3641    cmdPtr->refCount++;
3642    iPtr->cmdCount++;
3643    if (code == TCL_OK && traceCode == TCL_OK
3644            && !TclLimitExceeded(iPtr->limit)) {
3645        if (TCL_DTRACE_CMD_ENTRY_ENABLED()) {
3646            TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1,
3647                    (Tcl_Obj **)(objv + 1));
3648        }
3649        code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
3650        if (TCL_DTRACE_CMD_RETURN_ENABLED()) {
3651            TCL_DTRACE_CMD_RETURN(TclGetString(objv[0]), code);
3652        }
3653    }
3654
3655    if (TclAsyncReady(iPtr)) {
3656        code = Tcl_AsyncInvoke(interp, code);
3657    }
3658    if (code == TCL_OK && TclLimitReady(iPtr->limit)) {
3659        code = Tcl_LimitCheck(interp);
3660    }
3661
3662    /*
3663     * Call 'leave' command traces
3664     */
3665
3666    if (traced) {
3667        if (!(cmdPtr->flags & CMD_IS_DELETED)) {
3668            if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && traceCode == TCL_OK){
3669                traceCode = TclCheckExecutionTraces(interp, command, length,
3670                        cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
3671            }
3672            if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
3673                traceCode = TclCheckInterpTraces(interp, command, length,
3674                        cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
3675            }
3676        }
3677
3678        /*
3679         * If one of the trace invocation resulted in error, then change the
3680         * result code accordingly. Note, that the interp->result should
3681         * already be set correctly by the call to TraceExecutionProc.
3682         */
3683
3684        if (traceCode != TCL_OK) {
3685            code = traceCode;
3686        }
3687        if (commandPtr) {
3688            Tcl_DecrRefCount(commandPtr);
3689        }
3690    }
3691
3692    /*
3693     * Decrement the reference count of cmdPtr and deallocate it if it has
3694     * dropped to zero.
3695     */
3696
3697    TclCleanupCommandMacro(cmdPtr);
3698
3699    /*
3700     * If the interpreter has a non-empty string result, the result object is
3701     * either empty or stale because some function set interp->result
3702     * directly. If so, move the string result to the result object, then
3703     * reset the string result.
3704     */
3705
3706    if (*(iPtr->result) != 0) {
3707        (void) Tcl_GetObjResult(interp);
3708    }
3709
3710    if (TCL_DTRACE_CMD_RESULT_ENABLED()) {
3711        Tcl_Obj *r;
3712
3713        r = Tcl_GetObjResult(interp);
3714        TCL_DTRACE_CMD_RESULT(TclGetString(objv[0]), code, TclGetString(r),r);
3715    }
3716
3717  done:
3718    if (savedVarFramePtr) {
3719        iPtr->varFramePtr = savedVarFramePtr;
3720    }
3721    return code;
3722
3723  notFound:
3724    {
3725        Namespace *currNsPtr = NULL;    /* Used to check for and invoke any
3726                                         * registered unknown command handler
3727                                         * for the current namespace (TIP
3728                                         * 181). */
3729        int newObjc, handlerObjc;
3730        Tcl_Obj **handlerObjv;
3731
3732        currNsPtr = varFramePtr->nsPtr;
3733        if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) {
3734            currNsPtr = iPtr->globalNsPtr;
3735            if (currNsPtr == NULL) {
3736                Tcl_Panic("TclEvalObjvInternal: NULL global namespace pointer");
3737            }
3738        }
3739
3740        /*
3741         * Check to see if the resolution namespace has lost its unknown
3742         * handler. If so, reset it to "::unknown".
3743         */
3744
3745        if (currNsPtr->unknownHandlerPtr == NULL) {
3746            TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown");
3747            Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr);
3748        }
3749
3750        /*
3751         * Get the list of words for the unknown handler and allocate enough
3752         * space to hold both the handler prefix and all words of the command
3753         * invokation itself.
3754         */
3755
3756        Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr,
3757                &handlerObjc, &handlerObjv);
3758        newObjc = objc + handlerObjc;
3759        newObjv = (Tcl_Obj **) TclStackAlloc(interp,
3760                (int) sizeof(Tcl_Obj *) * newObjc);
3761
3762        /*
3763         * Copy command prefix from unknown handler and add on the real
3764         * command's full argument list. Note that we only use memcpy() once
3765         * because we have to increment the reference count of all the handler
3766         * arguments anyway.
3767         */
3768
3769        for (i = 0; i < handlerObjc; ++i) {
3770            newObjv[i] = handlerObjv[i];
3771            Tcl_IncrRefCount(newObjv[i]);
3772        }
3773        memcpy(newObjv+handlerObjc, objv, sizeof(Tcl_Obj *) * (unsigned)objc);
3774
3775        /*
3776         * Look up and invoke the handler (by recursive call to this
3777         * function). If there is no handler at all, instead of doing the
3778         * recursive call we just generate a generic error message; it would
3779         * be an infinite-recursion nightmare otherwise.
3780         */
3781
3782        cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
3783        if (cmdPtr == NULL) {
3784            Tcl_AppendResult(interp, "invalid command name \"",
3785                    TclGetString(objv[0]), "\"", NULL);
3786            code = TCL_ERROR;
3787        } else {
3788            iPtr->numLevels++;
3789            code = TclEvalObjvInternal(interp, newObjc, newObjv, command,
3790                    length, 0);
3791            iPtr->numLevels--;
3792        }
3793
3794        /*
3795         * Release any resources we locked and allocated during the handler
3796         * call.
3797         */
3798
3799        for (i = 0; i < handlerObjc; ++i) {
3800            Tcl_DecrRefCount(newObjv[i]);
3801        }
3802        TclStackFree(interp, newObjv);
3803        if (savedNsPtr) {
3804            varFramePtr->nsPtr = savedNsPtr;
3805        }
3806        goto done;
3807    }
3808}
3809
3810/*
3811 *----------------------------------------------------------------------
3812 *
3813 * Tcl_EvalObjv --
3814 *
3815 *      This function evaluates a Tcl command that has already been parsed
3816 *      into words, with one Tcl_Obj holding each word.
3817 *
3818 * Results:
3819 *      The return value is a standard Tcl completion code such as TCL_OK or
3820 *      TCL_ERROR. A result or error message is left in interp's result.
3821 *
3822 * Side effects:
3823 *      Depends on the command.
3824 *
3825 *----------------------------------------------------------------------
3826 */
3827
3828int
3829Tcl_EvalObjv(
3830    Tcl_Interp *interp,         /* Interpreter in which to evaluate the
3831                                 * command. Also used for error reporting. */
3832    int objc,                   /* Number of words in command. */
3833    Tcl_Obj *const objv[],      /* An array of pointers to objects that are
3834                                 * the words that make up the command. */
3835    int flags)                  /* Collection of OR-ed bits that control the
3836                                 * evaluation of the script. Only
3837                                 * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
3838                                 * currently supported. */
3839{
3840    Interp *iPtr = (Interp *) interp;
3841    int code = TCL_OK;
3842
3843    iPtr->numLevels++;
3844    code = TclEvalObjvInternal(interp, objc, objv, NULL, 0, flags);
3845    iPtr->numLevels--;
3846
3847    if (code == TCL_OK) {
3848        return code;
3849    } else {
3850        int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
3851
3852        /*
3853         * If we are again at the top level, process any unusual return code
3854         * returned by the evaluated code.
3855         */
3856
3857        if (iPtr->numLevels == 0) {
3858            if (code == TCL_RETURN) {
3859                code = TclUpdateReturnInfo(iPtr);
3860            }
3861            if ((code != TCL_ERROR) && !allowExceptions) {
3862                ProcessUnexpectedResult(interp, code);
3863                code = TCL_ERROR;
3864            }
3865        }
3866
3867        if ((code == TCL_ERROR) && !(flags & TCL_EVAL_INVOKE)) {
3868            /*
3869             * If there was an error, a command string will be needed for the
3870             * error log: generate it now. Do not worry too much about doing
3871             * it expensively.
3872             */
3873
3874            Tcl_Obj *listPtr;
3875            char *cmdString;
3876            int cmdLen;
3877
3878            listPtr = Tcl_NewListObj(objc, objv);
3879            cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen);
3880            Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
3881            Tcl_DecrRefCount(listPtr);
3882        }
3883
3884        return code;
3885    }
3886}
3887
3888/*
3889 *----------------------------------------------------------------------
3890 *
3891 * Tcl_EvalTokensStandard --
3892 *
3893 *      Given an array of tokens parsed from a Tcl command (e.g., the tokens
3894 *      that make up a word or the index for an array variable) this function
3895 *      evaluates the tokens and concatenates their values to form a single
3896 *      result value.
3897 *
3898 * Results:
3899 *      The return value is a standard Tcl completion code such as TCL_OK or
3900 *      TCL_ERROR. A result or error message is left in interp's result.
3901 *
3902 * Side effects:
3903 *      Depends on the array of tokens being evaled.
3904 *
3905 *----------------------------------------------------------------------
3906 */
3907
3908int
3909Tcl_EvalTokensStandard(
3910    Tcl_Interp *interp,         /* Interpreter in which to lookup variables,
3911                                 * execute nested commands, and report
3912                                 * errors. */
3913    Tcl_Token *tokenPtr,        /* Pointer to first in an array of tokens to
3914                                 * evaluate and concatenate. */
3915    int count)                  /* Number of tokens to consider at tokenPtr.
3916                                 * Must be at least 1. */
3917{
3918    return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1);
3919}
3920
3921/*
3922 *----------------------------------------------------------------------
3923 *
3924 * Tcl_EvalTokens --
3925 *
3926 *      Given an array of tokens parsed from a Tcl command (e.g., the tokens
3927 *      that make up a word or the index for an array variable) this function
3928 *      evaluates the tokens and concatenates their values to form a single
3929 *      result value.
3930 *
3931 * Results:
3932 *      The return value is a pointer to a newly allocated Tcl_Obj containing
3933 *      the value of the array of tokens. The reference count of the returned
3934 *      object has been incremented. If an error occurs in evaluating the
3935 *      tokens then a NULL value is returned and an error message is left in
3936 *      interp's result.
3937 *
3938 * Side effects:
3939 *      A new object is allocated to hold the result.
3940 *
3941 *----------------------------------------------------------------------
3942 *
3943 * This uses a non-standard return convention; its use is now deprecated. It
3944 * is a wrapper for the new function Tcl_EvalTokensStandard, and is not used
3945 * in the core any longer. It is only kept for backward compatibility.
3946 */
3947
3948Tcl_Obj *
3949Tcl_EvalTokens(
3950    Tcl_Interp *interp,         /* Interpreter in which to lookup variables,
3951                                 * execute nested commands, and report
3952                                 * errors. */
3953    Tcl_Token *tokenPtr,        /* Pointer to first in an array of tokens to
3954                                 * evaluate and concatenate. */
3955    int count)                  /* Number of tokens to consider at tokenPtr.
3956                                 * Must be at least 1. */
3957{
3958    Tcl_Obj *resPtr;
3959
3960    if (Tcl_EvalTokensStandard(interp, tokenPtr, count) != TCL_OK) {
3961        return NULL;
3962    }
3963    resPtr = Tcl_GetObjResult(interp);
3964    Tcl_IncrRefCount(resPtr);
3965    Tcl_ResetResult(interp);
3966    return resPtr;
3967}
3968
3969/*
3970 *----------------------------------------------------------------------
3971 *
3972 * Tcl_EvalEx, TclEvalEx --
3973 *
3974 *      This function evaluates a Tcl script without using the compiler or
3975 *      byte-code interpreter. It just parses the script, creates values for
3976 *      each word of each command, then calls EvalObjv to execute each
3977 *      command.
3978 *
3979 * Results:
3980 *      The return value is a standard Tcl completion code such as TCL_OK or
3981 *      TCL_ERROR. A result or error message is left in interp's result.
3982 *
3983 * Side effects:
3984 *      Depends on the script.
3985 *
3986 * TIP #280 : Keep public API, internally extended API.
3987 *----------------------------------------------------------------------
3988 */
3989
3990int
3991Tcl_EvalEx(
3992    Tcl_Interp *interp,         /* Interpreter in which to evaluate the
3993                                 * script. Also used for error reporting. */
3994    const char *script,         /* First character of script to evaluate. */
3995    int numBytes,               /* Number of bytes in script. If < 0, the
3996                                 * script consists of all bytes up to the
3997                                 * first null character. */
3998    int flags)                  /* Collection of OR-ed bits that control the
3999                                 * evaluation of the script. Only
4000                                 * TCL_EVAL_GLOBAL is currently supported. */
4001{
4002  return TclEvalEx(interp, script, numBytes, flags, 1);
4003}
4004
4005int
4006TclEvalEx(
4007    Tcl_Interp *interp,         /* Interpreter in which to evaluate the
4008                                 * script. Also used for error reporting. */
4009    const char *script,         /* First character of script to evaluate. */
4010    int numBytes,               /* Number of bytes in script. If < 0, the
4011                                 * script consists of all bytes up to the
4012                                 * first NUL character. */
4013    int flags,                  /* Collection of OR-ed bits that control the
4014                                 * evaluation of the script. Only
4015                                 * TCL_EVAL_GLOBAL is currently supported. */
4016    int line)                   /* The line the script starts on. */
4017{
4018    Interp *iPtr = (Interp *) interp;
4019    const char *p, *next;
4020    const unsigned int minObjs = 20;
4021    Tcl_Obj **objv, **objvSpace;
4022    int *expand, *lines, *lineSpace;
4023    Tcl_Token *tokenPtr;
4024    int commandLength, bytesLeft, expandRequested, code = TCL_OK;
4025    CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
4026                                 * TCL_EVAL_GLOBAL was set. */
4027    int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
4028    int gotParse = 0;
4029    unsigned int i, objectsUsed = 0;
4030                                /* These variables keep track of how much
4031                                 * state has been allocated while evaluating
4032                                 * the script, so that it can be freed
4033                                 * properly if an error occurs. */
4034    Tcl_Parse *parsePtr = (Tcl_Parse *)
4035            TclStackAlloc(interp, sizeof(Tcl_Parse));
4036    CmdFrame *eeFramePtr = (CmdFrame *)
4037            TclStackAlloc(interp, sizeof(CmdFrame));
4038    Tcl_Obj **stackObjArray = (Tcl_Obj **)
4039            TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
4040    int *expandStack = (int *) TclStackAlloc(interp, minObjs * sizeof(int));
4041    int *linesStack = (int *) TclStackAlloc(interp, minObjs * sizeof(int));
4042                                /* TIP #280 Structures for tracking of command
4043                                 * locations. */
4044
4045    if (numBytes < 0) {
4046        numBytes = strlen(script);
4047    }
4048    Tcl_ResetResult(interp);
4049
4050    savedVarFramePtr = iPtr->varFramePtr;
4051    if (flags & TCL_EVAL_GLOBAL) {
4052        iPtr->varFramePtr = iPtr->rootFramePtr;
4053    }
4054
4055    /*
4056     * Each iteration through the following loop parses the next command from
4057     * the script and then executes it.
4058     */
4059
4060    objv = objvSpace = stackObjArray;
4061    lines = lineSpace = linesStack;
4062    expand = expandStack;
4063    p = script;
4064    bytesLeft = numBytes;
4065
4066    /*
4067     * TIP #280 Initialize tracking. Do not push on the frame stack yet.
4068     *
4069     * We may cont. counting based on a specific context (CTX), or open a new
4070     * context, either for a sourced script, or 'eval'. For sourced files we
4071     * always have a path object, even if nothing was specified in the interp
4072     * itself. That makes code using it simpler as NULL checks can be left
4073     * out. Sourced file without path in the 'scriptFile' is possible during
4074     * Tcl initialization.
4075     */
4076
4077    if (iPtr->evalFlags & TCL_EVAL_CTX) {
4078        /*
4079         * Path information comes out of the context.
4080         */
4081
4082        eeFramePtr->type = TCL_LOCATION_SOURCE;
4083        eeFramePtr->data.eval.path = iPtr->invokeCmdFramePtr->data.eval.path;
4084        Tcl_IncrRefCount(eeFramePtr->data.eval.path);
4085    } else if (iPtr->evalFlags & TCL_EVAL_FILE) {
4086        /*
4087         * Set up for a sourced file.
4088         */
4089
4090        eeFramePtr->type = TCL_LOCATION_SOURCE;
4091
4092        if (iPtr->scriptFile) {
4093            /*
4094             * Normalization here, to have the correct pwd. Should have
4095             * negligible impact on performance, as the norm should have been
4096             * done already by the 'source' invoking us, and it caches the
4097             * result.
4098             */
4099
4100            Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile);
4101
4102            if (norm == NULL) {
4103                /*
4104                 * Error message in the interp result.
4105                 */
4106                code = TCL_ERROR;
4107                goto error;
4108            }
4109            eeFramePtr->data.eval.path = norm;
4110            Tcl_IncrRefCount(eeFramePtr->data.eval.path);
4111        } else {
4112            TclNewLiteralStringObj(eeFramePtr->data.eval.path, "");
4113        }
4114    } else {
4115        /*
4116         * Set up for plain eval.
4117         */
4118
4119        eeFramePtr->type = TCL_LOCATION_EVAL;
4120        eeFramePtr->data.eval.path = NULL;
4121    }
4122
4123    eeFramePtr->level = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level + 1 : 1;
4124    eeFramePtr->framePtr = iPtr->framePtr;
4125    eeFramePtr->nextPtr = iPtr->cmdFramePtr;
4126    eeFramePtr->nline = 0;
4127    eeFramePtr->line = NULL;
4128
4129    iPtr->evalFlags = 0;
4130    do {
4131        if (Tcl_ParseCommand(interp, p, bytesLeft, 0, parsePtr) != TCL_OK) {
4132            code = TCL_ERROR;
4133            goto error;
4134        }
4135
4136        /*
4137         * TIP #280 Track lines. The parser may have skipped text till it
4138         * found the command we are now at. We have to count the lines in this
4139         * block.
4140         */
4141
4142        TclAdvanceLines(&line, p, parsePtr->commandStart);
4143
4144        gotParse = 1;
4145        if (parsePtr->numWords > 0) {
4146            /*
4147             * TIP #280. Track lines within the words of the current command.
4148             */
4149
4150            int wordLine  = line;
4151            const char *wordStart = parsePtr->commandStart;
4152
4153            /*
4154             * Generate an array of objects for the words of the command.
4155             */
4156
4157            unsigned int objectsNeeded = 0;
4158            unsigned int numWords = parsePtr->numWords;
4159
4160            if (numWords > minObjs) {
4161                expand = (int *) ckalloc(numWords * sizeof(int));
4162                objvSpace = (Tcl_Obj **)
4163                        ckalloc(numWords * sizeof(Tcl_Obj *));
4164                lineSpace = (int *) ckalloc(numWords * sizeof(int));
4165            }
4166            expandRequested = 0;
4167            objv = objvSpace;
4168            lines = lineSpace;
4169
4170            for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
4171                    objectsUsed < numWords;
4172                    objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {
4173                /*
4174                 * TIP #280. Track lines to current word. Save the information
4175                 * on a per-word basis, signaling dynamic words as needed.
4176                 * Make the information available to the recursively called
4177                 * evaluator as well, including the type of context (source
4178                 * vs. eval).
4179                 */
4180
4181                TclAdvanceLines(&wordLine, wordStart, tokenPtr->start);
4182                wordStart = tokenPtr->start;
4183
4184                lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL)
4185                        ? wordLine : -1;
4186
4187                if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
4188                    iPtr->evalFlags |= TCL_EVAL_FILE;
4189                }
4190
4191                code = TclSubstTokens(interp, tokenPtr+1,
4192                        tokenPtr->numComponents, NULL, wordLine);
4193
4194                iPtr->evalFlags = 0;
4195
4196                if (code != TCL_OK) {
4197                    goto error;
4198                }
4199                objv[objectsUsed] = Tcl_GetObjResult(interp);
4200                Tcl_IncrRefCount(objv[objectsUsed]);
4201                if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
4202                    int numElements;
4203
4204                    code = TclListObjLength(interp, objv[objectsUsed],
4205                            &numElements);
4206                    if (code == TCL_ERROR) {
4207                        /*
4208                         * Attempt to expand a non-list.
4209                         */
4210
4211                        Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
4212                                "\n    (expanding word %d)", objectsUsed));
4213                        Tcl_DecrRefCount(objv[objectsUsed]);
4214                        goto error;
4215                    }
4216                    expandRequested = 1;
4217                    expand[objectsUsed] = 1;
4218
4219                    objectsNeeded += (numElements ? numElements : 1);
4220                } else {
4221                    expand[objectsUsed] = 0;
4222                    objectsNeeded++;
4223                }
4224            } /* for loop */
4225            if (expandRequested) {
4226                /*
4227                 * Some word expansion was requested. Check for objv resize.
4228                 */
4229
4230                Tcl_Obj **copy = objvSpace;
4231                int *lcopy = lineSpace;
4232                int wordIdx = numWords;
4233                int objIdx = objectsNeeded - 1;
4234
4235                if ((numWords > minObjs) || (objectsNeeded >  minObjs)) {
4236                    objv = objvSpace = (Tcl_Obj **)
4237                            ckalloc(objectsNeeded * sizeof(Tcl_Obj *));
4238                    lines = lineSpace = (int *)
4239                            ckalloc(objectsNeeded * sizeof(int));
4240                }
4241
4242                objectsUsed = 0;
4243                while (wordIdx--) {
4244                    if (expand[wordIdx]) {
4245                        int numElements;
4246                        Tcl_Obj **elements, *temp = copy[wordIdx];
4247
4248                        Tcl_ListObjGetElements(NULL, temp, &numElements,
4249                                &elements);
4250                        objectsUsed += numElements;
4251                        while (numElements--) {
4252                            lines[objIdx] = -1;
4253                            objv[objIdx--] = elements[numElements];
4254                            Tcl_IncrRefCount(elements[numElements]);
4255                        }
4256                        Tcl_DecrRefCount(temp);
4257                    } else {
4258                        lines[objIdx] = lcopy[wordIdx];
4259                        objv[objIdx--] = copy[wordIdx];
4260                        objectsUsed++;
4261                    }
4262                }
4263                objv += objIdx+1;
4264
4265                if (copy != stackObjArray) {
4266                    ckfree((char *) copy);
4267                }
4268                if (lcopy != linesStack) {
4269                    ckfree((char *) lcopy);
4270                }
4271            }
4272
4273            /*
4274             * Execute the command and free the objects for its words.
4275             *
4276             * TIP #280: Remember the command itself for 'info frame'. We
4277             * shorten the visible command by one char to exclude the
4278             * termination character, if necessary. Here is where we put our
4279             * frame on the stack of frames too. _After_ the nested commands
4280             * have been executed.
4281             */
4282
4283            eeFramePtr->cmd.str.cmd = parsePtr->commandStart;
4284            eeFramePtr->cmd.str.len = parsePtr->commandSize;
4285
4286            if (parsePtr->term ==
4287                    parsePtr->commandStart + parsePtr->commandSize - 1) {
4288                eeFramePtr->cmd.str.len--;
4289            }
4290
4291            eeFramePtr->nline = objectsUsed;
4292            eeFramePtr->line = lines;
4293
4294            iPtr->cmdFramePtr = eeFramePtr;
4295            iPtr->numLevels++;
4296            code = TclEvalObjvInternal(interp, objectsUsed, objv,
4297                    parsePtr->commandStart, parsePtr->commandSize, 0);
4298            iPtr->numLevels--;
4299            iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
4300
4301            eeFramePtr->line = NULL;
4302            eeFramePtr->nline = 0;
4303
4304            if (code != TCL_OK) {
4305                goto error;
4306            }
4307            for (i = 0; i < objectsUsed; i++) {
4308                Tcl_DecrRefCount(objv[i]);
4309            }
4310            objectsUsed = 0;
4311            if (objvSpace != stackObjArray) {
4312                ckfree((char *) objvSpace);
4313                objvSpace = stackObjArray;
4314                ckfree((char *) lineSpace);
4315                lineSpace = linesStack;
4316            }
4317
4318            /*
4319             * Free expand separately since objvSpace could have been
4320             * reallocated above.
4321             */
4322
4323            if (expand != expandStack) {
4324                ckfree((char *) expand);
4325                expand = expandStack;
4326            }
4327        }
4328
4329        /*
4330         * Advance to the next command in the script.
4331         *
4332         * TIP #280 Track Lines. Now we track how many lines were in the
4333         * executed command.
4334         */
4335
4336        next = parsePtr->commandStart + parsePtr->commandSize;
4337        bytesLeft -= next - p;
4338        p = next;
4339        TclAdvanceLines(&line, parsePtr->commandStart, p);
4340        Tcl_FreeParse(parsePtr);
4341        gotParse = 0;
4342    } while (bytesLeft > 0);
4343    iPtr->varFramePtr = savedVarFramePtr;
4344    code = TCL_OK;
4345    goto cleanup_return;
4346
4347  error:
4348    /*
4349     * Generate and log various pieces of error information.
4350     */
4351
4352    if (iPtr->numLevels == 0) {
4353        if (code == TCL_RETURN) {
4354            code = TclUpdateReturnInfo(iPtr);
4355        }
4356        if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) {
4357            ProcessUnexpectedResult(interp, code);
4358            code = TCL_ERROR;
4359        }
4360    }
4361    if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
4362        commandLength = parsePtr->commandSize;
4363        if (parsePtr->term == parsePtr->commandStart + commandLength - 1) {
4364            /*
4365             * The terminator character (such as ; or ]) of the command where
4366             * the error occurred is the last character in the parsed command.
4367             * Reduce the length by one so that the error message doesn't
4368             * include the terminator character.
4369             */
4370
4371            commandLength -= 1;
4372        }
4373        Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
4374                commandLength);
4375    }
4376    iPtr->flags &= ~ERR_ALREADY_LOGGED;
4377
4378    /*
4379     * Then free resources that had been allocated to the command.
4380     */
4381
4382    for (i = 0; i < objectsUsed; i++) {
4383        Tcl_DecrRefCount(objv[i]);
4384    }
4385    if (gotParse) {
4386        Tcl_FreeParse(parsePtr);
4387    }
4388    if (objvSpace != stackObjArray) {
4389        ckfree((char *) objvSpace);
4390        ckfree((char *) lineSpace);
4391    }
4392    if (expand != expandStack) {
4393        ckfree((char *) expand);
4394    }
4395    iPtr->varFramePtr = savedVarFramePtr;
4396
4397 cleanup_return:
4398    /*
4399     * TIP #280. Release the local CmdFrame, and its contents.
4400     */
4401
4402    if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
4403        Tcl_DecrRefCount(eeFramePtr->data.eval.path);
4404    }
4405    TclStackFree(interp, linesStack);
4406    TclStackFree(interp, expandStack);
4407    TclStackFree(interp, stackObjArray);
4408    TclStackFree(interp, eeFramePtr);
4409    TclStackFree(interp, parsePtr);
4410
4411    return code;
4412}
4413
4414/*
4415 *----------------------------------------------------------------------
4416 *
4417 * TclAdvanceLines --
4418 *
4419 *      This function is a helper which counts the number of lines in a block
4420 *      of text and advances an external counter.
4421 *
4422 * Results:
4423 *      None.
4424 *
4425 * Side effects:
4426 *      The specified counter is advanced per the number of lines found.
4427 *
4428 * TIP #280
4429 *----------------------------------------------------------------------
4430 */
4431
4432void
4433TclAdvanceLines(
4434    int *line,
4435    const char *start,
4436    const char *end)
4437{
4438    register const char *p;
4439
4440    for (p = start; p < end; p++) {
4441        if (*p == '\n') {
4442            (*line)++;
4443        }
4444    }
4445}
4446
4447/*
4448 *----------------------------------------------------------------------
4449 *
4450 * Tcl_Eval --
4451 *
4452 *      Execute a Tcl command in a string. This function executes the script
4453 *      directly, rather than compiling it to bytecodes. Before the arrival of
4454 *      the bytecode compiler in Tcl 8.0 Tcl_Eval was the main function used
4455 *      for executing Tcl commands, but nowadays it isn't used much.
4456 *
4457 * Results:
4458 *      The return value is one of the return codes defined in tcl.h (such as
4459 *      TCL_OK), and interp's result contains a value to supplement the return
4460 *      code. The value of the result will persist only until the next call to
4461 *      Tcl_Eval or Tcl_EvalObj: you must copy it or lose it!
4462 *
4463 * Side effects:
4464 *      Can be almost arbitrary, depending on the commands in the script.
4465 *
4466 *----------------------------------------------------------------------
4467 */
4468
4469int
4470Tcl_Eval(
4471    Tcl_Interp *interp,         /* Token for command interpreter (returned by
4472                                 * previous call to Tcl_CreateInterp). */
4473    const char *script)         /* Pointer to TCL command to execute. */
4474{
4475    int code = Tcl_EvalEx(interp, script, -1, 0);
4476
4477    /*
4478     * For backwards compatibility with old C code that predates the object
4479     * system in Tcl 8.0, we have to mirror the object result back into the
4480     * string result (some callers may expect it there).
4481     */
4482
4483    (void) Tcl_GetStringResult(interp);
4484    return code;
4485}
4486
4487/*
4488 *----------------------------------------------------------------------
4489 *
4490 * Tcl_EvalObj, Tcl_GlobalEvalObj --
4491 *
4492 *      These functions are deprecated but we keep them around for backwards
4493 *      compatibility reasons.
4494 *
4495 * Results:
4496 *      See the functions they call.
4497 *
4498 * Side effects:
4499 *      See the functions they call.
4500 *
4501 *----------------------------------------------------------------------
4502 */
4503
4504#undef Tcl_EvalObj
4505int
4506Tcl_EvalObj(
4507    Tcl_Interp *interp,
4508    Tcl_Obj *objPtr)
4509{
4510    return Tcl_EvalObjEx(interp, objPtr, 0);
4511}
4512
4513#undef Tcl_GlobalEvalObj
4514int
4515Tcl_GlobalEvalObj(
4516    Tcl_Interp *interp,
4517    Tcl_Obj *objPtr)
4518{
4519    return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
4520}
4521
4522/*
4523 *----------------------------------------------------------------------
4524 *
4525 * Tcl_EvalObjEx, TclEvalObjEx --
4526 *
4527 *      Execute Tcl commands stored in a Tcl object. These commands are
4528 *      compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT is
4529 *      specified.
4530 *
4531 * Results:
4532 *      The return value is one of the return codes defined in tcl.h (such as
4533 *      TCL_OK), and the interpreter's result contains a value to supplement
4534 *      the return code.
4535 *
4536 * Side effects:
4537 *      The object is converted, if necessary, to a ByteCode object that holds
4538 *      the bytecode instructions for the commands. Executing the commands
4539 *      will almost certainly have side effects that depend on those commands.
4540 *
4541 * TIP #280 : Keep public API, internally extended API.
4542 *----------------------------------------------------------------------
4543 */
4544
4545int
4546Tcl_EvalObjEx(
4547    Tcl_Interp *interp,         /* Token for command interpreter (returned by
4548                                 * a previous call to Tcl_CreateInterp). */
4549    register Tcl_Obj *objPtr,   /* Pointer to object containing commands to
4550                                 * execute. */
4551    int flags)                  /* Collection of OR-ed bits that control the
4552                                 * evaluation of the script. Supported values
4553                                 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
4554{
4555    return TclEvalObjEx(interp, objPtr, flags, NULL, 0);
4556}
4557
4558int
4559TclEvalObjEx(
4560    Tcl_Interp *interp,         /* Token for command interpreter (returned by
4561                                 * a previous call to Tcl_CreateInterp). */
4562    register Tcl_Obj *objPtr,   /* Pointer to object containing commands to
4563                                 * execute. */
4564    int flags,                  /* Collection of OR-ed bits that control the
4565                                 * evaluation of the script. Supported values
4566                                 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
4567    const CmdFrame *invoker,    /* Frame of the command doing the eval. */
4568    int word)                   /* Index of the word which is in objPtr. */
4569{
4570    register Interp *iPtr = (Interp *) interp;
4571    char *script;
4572    int numSrcBytes;
4573    int result;
4574    CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
4575                                 * TCL_EVAL_GLOBAL was set. */
4576    int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
4577
4578    Tcl_IncrRefCount(objPtr);
4579
4580    if (flags & TCL_EVAL_DIRECT) {
4581        /*
4582         * We're not supposed to use the compiler or byte-code interpreter.
4583         * Let Tcl_EvalEx evaluate the command directly (and probably more
4584         * slowly).
4585         *
4586         * Pure List Optimization (no string representation). In this case, we
4587         * can safely use Tcl_EvalObjv instead and get an appreciable
4588         * improvement in execution speed. This is because it allows us to
4589         * avoid a setFromAny step that would just pack everything into a
4590         * string and back out again.
4591         *
4592         * This restriction has been relaxed a bit by storing in lists whether
4593         * they are "canonical" or not (a canonical list being one that is
4594         * either pure or that has its string rep derived by
4595         * UpdateStringOfList from the internal rep).
4596         */
4597
4598        if (objPtr->typePtr == &tclListType) {  /* is a list... */
4599            List *listRepPtr = objPtr->internalRep.twoPtrValue.ptr1;
4600
4601            if (objPtr->bytes == NULL ||        /* ...without a string rep */
4602                    listRepPtr->canonicalFlag) {/* ...or that is canonical */
4603                /*
4604                 * TIP #280 Structures for tracking lines. As we know that
4605                 * this is dynamic execution we ignore the invoker, even if
4606                 * known.
4607                 */
4608
4609                int line, i;
4610                char *w;
4611                Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
4612                CmdFrame *eoFramePtr = (CmdFrame *)
4613                        TclStackAlloc(interp, sizeof(CmdFrame));
4614
4615                eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
4616                eoFramePtr->level = (iPtr->cmdFramePtr == NULL?
4617                        1 : iPtr->cmdFramePtr->level + 1);
4618                eoFramePtr->framePtr = iPtr->framePtr;
4619                eoFramePtr->nextPtr = iPtr->cmdFramePtr;
4620
4621                Tcl_ListObjGetElements(NULL, copyPtr,
4622                        &(eoFramePtr->nline), &elements);
4623                eoFramePtr->line = (int *)
4624                        ckalloc(eoFramePtr->nline * sizeof(int));
4625
4626                eoFramePtr->cmd.listPtr  = objPtr;
4627                Tcl_IncrRefCount(eoFramePtr->cmd.listPtr);
4628                eoFramePtr->data.eval.path = NULL;
4629
4630                /*
4631                 * TIP #280 Computes all the line numbers for the words in the
4632                 * command.
4633                 */
4634
4635                line = 1;
4636                for (i=0; i < eoFramePtr->nline; i++) {
4637                    eoFramePtr->line[i] = line;
4638                    w = TclGetString(elements[i]);
4639                    TclAdvanceLines(&line, w, w + strlen(w));
4640                }
4641
4642                iPtr->cmdFramePtr = eoFramePtr;
4643                result = Tcl_EvalObjv(interp, eoFramePtr->nline, elements,
4644                        flags);
4645
4646                Tcl_DecrRefCount(copyPtr);
4647                iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
4648                Tcl_DecrRefCount(eoFramePtr->cmd.listPtr);
4649                ckfree((char *) eoFramePtr->line);
4650                eoFramePtr->line = NULL;
4651                eoFramePtr->nline = 0;
4652                TclStackFree(interp, eoFramePtr);
4653
4654                goto done;
4655            }
4656        }
4657
4658        /*
4659         * TIP #280. Propagate context as much as we can. Especially if the
4660         * script to evaluate is a single literal it makes sense to look if
4661         * our context is one with absolute line numbers we can then track
4662         * into the literal itself too.
4663         *
4664         * See also tclCompile.c, TclInitCompileEnv, for the equivalent code
4665         * in the bytecode compiler.
4666         */
4667
4668        if (invoker == NULL) {
4669            /*
4670             * No context, force opening of our own.
4671             */
4672
4673            script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
4674            result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
4675        } else {
4676            /*
4677             * We have an invoker, describing the command asking for the
4678             * evaluation of a subordinate script. This script may originate
4679             * in a literal word, or from a variable, etc. Using the line
4680             * array we now check if we have good line information for the
4681             * relevant word. The type of context is relevant as well. In a
4682             * non-'source' context we don't have to try tracking lines.
4683             *
4684             * First see if the word exists and is a literal. If not we go
4685             * through the easy dynamic branch. No need to perform more
4686             * complex invokations.
4687             */
4688
4689            if ((invoker->nline <= word) || (invoker->line[word] < 0)) {
4690                /*
4691                 * Dynamic script, or dynamic context, force our own
4692                 * context.
4693                 */
4694
4695                script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
4696                result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
4697
4698            } else {
4699                /*
4700                 * Try to get an absolute context for the evaluation.
4701                 */
4702
4703                int pc = 0;
4704                CmdFrame *ctxPtr = (CmdFrame *)
4705                        TclStackAlloc(interp, sizeof(CmdFrame));
4706
4707                *ctxPtr = *invoker;
4708                if (invoker->type == TCL_LOCATION_BC) {
4709                    /*
4710                     * Note: Type BC => ctxPtr->data.eval.path is not used.
4711                     * ctxPtr->data.tebc.codePtr is used instead.
4712                     */
4713
4714                    TclGetSrcInfoForPc(ctxPtr);
4715                    pc = 1;
4716                }
4717
4718                if (ctxPtr->type == TCL_LOCATION_SOURCE) {
4719                    /*
4720                     * Absolute context to reuse.
4721                     */
4722
4723                    iPtr->invokeCmdFramePtr = ctxPtr;
4724                    iPtr->evalFlags |= TCL_EVAL_CTX;
4725
4726                    script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
4727                    result = TclEvalEx(interp, script, numSrcBytes, flags,
4728                            ctxPtr->line[word]);
4729
4730                    if (pc) {
4731                        /*
4732                         * Death of SrcInfo reference.
4733                         */
4734
4735                        Tcl_DecrRefCount(ctxPtr->data.eval.path);
4736                    }
4737                } else {
4738                    /*
4739                     * Dynamic context or script, easier to make our own as
4740                     * well.
4741                     */
4742
4743                    script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
4744                    result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
4745                }
4746
4747                TclStackFree(interp, ctxPtr);
4748            }
4749        }
4750    } else {
4751        /*
4752         * Let the compiler/engine subsystem do the evaluation.
4753         *
4754         * TIP #280 The invoker provides us with the context for the script.
4755         * We transfer this to the byte code compiler.
4756         */
4757
4758        savedVarFramePtr = iPtr->varFramePtr;
4759        if (flags & TCL_EVAL_GLOBAL) {
4760            iPtr->varFramePtr = iPtr->rootFramePtr;
4761        }
4762
4763        result = TclCompEvalObj(interp, objPtr, invoker, word);
4764
4765        /*
4766         * If we are again at the top level, process any unusual return code
4767         * returned by the evaluated code.
4768         */
4769
4770        if (iPtr->numLevels == 0) {
4771            if (result == TCL_RETURN) {
4772                result = TclUpdateReturnInfo(iPtr);
4773            }
4774            if ((result != TCL_OK) && (result != TCL_ERROR)
4775                    && !allowExceptions) {
4776                ProcessUnexpectedResult(interp, result);
4777                result = TCL_ERROR;
4778                script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
4779                Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
4780            }
4781        }
4782        iPtr->evalFlags = 0;
4783        iPtr->varFramePtr = savedVarFramePtr;
4784    }
4785
4786  done:
4787    TclDecrRefCount(objPtr);
4788    return result;
4789}
4790
4791/*
4792 *----------------------------------------------------------------------
4793 *
4794 * ProcessUnexpectedResult --
4795 *
4796 *      Function called by Tcl_EvalObj to set the interpreter's result value
4797 *      to an appropriate error message when the code it evaluates returns an
4798 *      unexpected result code (not TCL_OK and not TCL_ERROR) to the topmost
4799 *      evaluation level.
4800 *
4801 * Results:
4802 *      None.
4803 *
4804 * Side effects:
4805 *      The interpreter result is set to an error message appropriate to the
4806 *      result code.
4807 *
4808 *----------------------------------------------------------------------
4809 */
4810
4811static void
4812ProcessUnexpectedResult(
4813    Tcl_Interp *interp,         /* The interpreter in which the unexpected
4814                                 * result code was returned. */
4815    int returnCode)             /* The unexpected result code. */
4816{
4817    Tcl_ResetResult(interp);
4818    if (returnCode == TCL_BREAK) {
4819        Tcl_AppendResult(interp,
4820                "invoked \"break\" outside of a loop", NULL);
4821    } else if (returnCode == TCL_CONTINUE) {
4822        Tcl_AppendResult(interp,
4823                "invoked \"continue\" outside of a loop", NULL);
4824    } else {
4825        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4826                "command returned bad code: %d", returnCode));
4827    }
4828}
4829
4830/*
4831 *---------------------------------------------------------------------------
4832 *
4833 * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
4834 *
4835 *      Functions to evaluate an expression and return its value in a
4836 *      particular form.
4837 *
4838 * Results:
4839 *      Each of the functions below returns a standard Tcl result. If an error
4840 *      occurs then an error message is left in the interp's result. Otherwise
4841 *      the value of the expression, in the appropriate form, is stored at
4842 *      *ptr. If the expression had a result that was incompatible with the
4843 *      desired form then an error is returned.
4844 *
4845 * Side effects:
4846 *      None.
4847 *
4848 *---------------------------------------------------------------------------
4849 */
4850
4851int
4852Tcl_ExprLong(
4853    Tcl_Interp *interp,         /* Context in which to evaluate the
4854                                 * expression. */
4855    const char *exprstring,     /* Expression to evaluate. */
4856    long *ptr)                  /* Where to store result. */
4857{
4858    register Tcl_Obj *exprPtr;
4859    int result = TCL_OK;
4860    if (*exprstring == '\0') {
4861        /*
4862         * Legacy compatibility - return 0 for the zero-length string.
4863         */
4864
4865        *ptr = 0;
4866    } else {
4867        exprPtr = Tcl_NewStringObj(exprstring, -1);
4868        Tcl_IncrRefCount(exprPtr);
4869        result = Tcl_ExprLongObj(interp, exprPtr, ptr);
4870        Tcl_DecrRefCount(exprPtr);
4871        if (result != TCL_OK) {
4872            (void) Tcl_GetStringResult(interp);
4873        }
4874    }
4875    return result;
4876}
4877
4878int
4879Tcl_ExprDouble(
4880    Tcl_Interp *interp,         /* Context in which to evaluate the
4881                                 * expression. */
4882    const char *exprstring,     /* Expression to evaluate. */
4883    double *ptr)                /* Where to store result. */
4884{
4885    register Tcl_Obj *exprPtr;
4886    int result = TCL_OK;
4887
4888    if (*exprstring == '\0') {
4889        /*
4890         * Legacy compatibility - return 0 for the zero-length string.
4891         */
4892
4893        *ptr = 0.0;
4894    } else {
4895        exprPtr = Tcl_NewStringObj(exprstring, -1);
4896        Tcl_IncrRefCount(exprPtr);
4897        result = Tcl_ExprDoubleObj(interp, exprPtr, ptr);
4898        Tcl_DecrRefCount(exprPtr);
4899                                /* Discard the expression object. */
4900        if (result != TCL_OK) {
4901            (void) Tcl_GetStringResult(interp);
4902        }
4903    }
4904    return result;
4905}
4906
4907int
4908Tcl_ExprBoolean(
4909    Tcl_Interp *interp,         /* Context in which to evaluate the
4910                                 * expression. */
4911    const char *exprstring,     /* Expression to evaluate. */
4912    int *ptr)                   /* Where to store 0/1 result. */
4913{
4914    if (*exprstring == '\0') {
4915        /*
4916         * An empty string. Just set the result boolean to 0 (false).
4917         */
4918
4919        *ptr = 0;
4920        return TCL_OK;
4921    } else {
4922        int result;
4923        Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, -1);
4924
4925        Tcl_IncrRefCount(exprPtr);
4926        result = Tcl_ExprBooleanObj(interp, exprPtr, ptr);
4927        Tcl_DecrRefCount(exprPtr);
4928        if (result != TCL_OK) {
4929            /*
4930             * Move the interpreter's object result to the string result, then
4931             * reset the object result.
4932             */
4933
4934            (void) Tcl_GetStringResult(interp);
4935        }
4936        return result;
4937    }
4938}
4939
4940/*
4941 *--------------------------------------------------------------
4942 *
4943 * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
4944 *
4945 *      Functions to evaluate an expression in an object and return its value
4946 *      in a particular form.
4947 *
4948 * Results:
4949 *      Each of the functions below returns a standard Tcl result object. If
4950 *      an error occurs then an error message is left in the interpreter's
4951 *      result. Otherwise the value of the expression, in the appropriate
4952 *      form, is stored at *ptr. If the expression had a result that was
4953 *      incompatible with the desired form then an error is returned.
4954 *
4955 * Side effects:
4956 *      None.
4957 *
4958 *--------------------------------------------------------------
4959 */
4960
4961int
4962Tcl_ExprLongObj(
4963    Tcl_Interp *interp,         /* Context in which to evaluate the
4964                                 * expression. */
4965    register Tcl_Obj *objPtr,   /* Expression to evaluate. */
4966    long *ptr)                  /* Where to store long result. */
4967{
4968    Tcl_Obj *resultPtr;
4969    int result, type;
4970    double d;
4971    ClientData internalPtr;
4972
4973    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
4974    if (result != TCL_OK) {
4975        return TCL_ERROR;
4976    }
4977
4978    if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type) != TCL_OK){
4979        return TCL_ERROR;
4980    }
4981
4982    switch (type) {
4983    case TCL_NUMBER_DOUBLE: {
4984        mp_int big;
4985
4986        d = *((const double *) internalPtr);
4987        Tcl_DecrRefCount(resultPtr);
4988        if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
4989            return TCL_ERROR;
4990        }
4991        resultPtr = Tcl_NewBignumObj(&big);
4992        /* FALLTHROUGH */
4993    }
4994    case TCL_NUMBER_LONG:
4995    case TCL_NUMBER_WIDE:
4996    case TCL_NUMBER_BIG:
4997        result = TclGetLongFromObj(interp, resultPtr, ptr);
4998        break;
4999
5000    case TCL_NUMBER_NAN:
5001        Tcl_GetDoubleFromObj(interp, resultPtr, &d);
5002        result = TCL_ERROR;
5003    }
5004
5005    Tcl_DecrRefCount(resultPtr);/* Discard the result object. */
5006    return result;
5007}
5008
5009int
5010Tcl_ExprDoubleObj(
5011    Tcl_Interp *interp,         /* Context in which to evaluate the
5012                                 * expression. */
5013    register Tcl_Obj *objPtr,   /* Expression to evaluate. */
5014    double *ptr)                /* Where to store double result. */
5015{
5016    Tcl_Obj *resultPtr;
5017    int result, type;
5018    ClientData internalPtr;
5019
5020    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
5021    if (result != TCL_OK) {
5022        return TCL_ERROR;
5023    }
5024
5025    result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type);
5026    if (result == TCL_OK) {
5027        switch (type) {
5028        case TCL_NUMBER_NAN:
5029#ifndef ACCEPT_NAN
5030            result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
5031            break;
5032#endif
5033        case TCL_NUMBER_DOUBLE:
5034            *ptr = *((const double *) internalPtr);
5035            result = TCL_OK;
5036            break;
5037        default:
5038            result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
5039        }
5040    }
5041    Tcl_DecrRefCount(resultPtr);/* Discard the result object. */
5042    return result;
5043}
5044
5045int
5046Tcl_ExprBooleanObj(
5047    Tcl_Interp *interp,         /* Context in which to evaluate the
5048                                 * expression. */
5049    register Tcl_Obj *objPtr,   /* Expression to evaluate. */
5050    int *ptr)                   /* Where to store 0/1 result. */
5051{
5052    Tcl_Obj *resultPtr;
5053    int result;
5054
5055    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
5056    if (result == TCL_OK) {
5057        result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
5058        Tcl_DecrRefCount(resultPtr);
5059                                /* Discard the result object. */
5060    }
5061    return result;
5062}
5063
5064/*
5065 *----------------------------------------------------------------------
5066 *
5067 * TclObjInvokeNamespace --
5068 *
5069 *      Object version: Invokes a Tcl command, given an objv/objc, from either
5070 *      the exposed or hidden set of commands in the given interpreter.
5071 *      NOTE: The command is invoked in the global stack frame of the
5072 *      interpreter or namespace, thus it cannot see any current state on the
5073 *      stack of that interpreter.
5074 *
5075 * Results:
5076 *      A standard Tcl result.
5077 *
5078 * Side effects:
5079 *      Whatever the command does.
5080 *
5081 *----------------------------------------------------------------------
5082 */
5083
5084int
5085TclObjInvokeNamespace(
5086    Tcl_Interp *interp,         /* Interpreter in which command is to be
5087                                 * invoked. */
5088    int objc,                   /* Count of arguments. */
5089    Tcl_Obj *const objv[],      /* Argument objects; objv[0] points to the
5090                                 * name of the command to invoke. */
5091    Tcl_Namespace *nsPtr,       /* The namespace to use. */
5092    int flags)                  /* Combination of flags controlling the call:
5093                                 * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
5094                                 * or TCL_INVOKE_NO_TRACEBACK. */
5095{
5096    int result;
5097    Tcl_CallFrame *framePtr;
5098
5099    /*
5100     * Make the specified namespace the current namespace and invoke the
5101     * command.
5102     */
5103
5104    result = TclPushStackFrame(interp, &framePtr, nsPtr, /*isProcFrame*/0);
5105    if (result != TCL_OK) {
5106        return TCL_ERROR;
5107    }
5108
5109    result = TclObjInvoke(interp, objc, objv, flags);
5110
5111    TclPopStackFrame(interp);
5112    return result;
5113}
5114
5115/*
5116 *----------------------------------------------------------------------
5117 *
5118 * TclObjInvoke --
5119 *
5120 *      Invokes a Tcl command, given an objv/objc, from either the exposed or
5121 *      the hidden sets of commands in the given interpreter.
5122 *
5123 * Results:
5124 *      A standard Tcl object result.
5125 *
5126 * Side effects:
5127 *      Whatever the command does.
5128 *
5129 *----------------------------------------------------------------------
5130 */
5131
5132int
5133TclObjInvoke(
5134    Tcl_Interp *interp,         /* Interpreter in which command is to be
5135                                 * invoked. */
5136    int objc,                   /* Count of arguments. */
5137    Tcl_Obj *const objv[],      /* Argument objects; objv[0] points to the
5138                                 * name of the command to invoke. */
5139    int flags)                  /* Combination of flags controlling the call:
5140                                 * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
5141                                 * or TCL_INVOKE_NO_TRACEBACK. */
5142{
5143    register Interp *iPtr = (Interp *) interp;
5144    Tcl_HashTable *hTblPtr;     /* Table of hidden commands. */
5145    char *cmdName;              /* Name of the command from objv[0]. */
5146    Tcl_HashEntry *hPtr = NULL;
5147    Command *cmdPtr;
5148    int result;
5149
5150    if (interp == NULL) {
5151        return TCL_ERROR;
5152    }
5153
5154    if ((objc < 1) || (objv == NULL)) {
5155        Tcl_AppendResult(interp, "illegal argument vector", NULL);
5156        return TCL_ERROR;
5157    }
5158
5159    if ((flags & TCL_INVOKE_HIDDEN) == 0) {
5160        Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN");
5161    }
5162
5163    if (TclInterpReady(interp) == TCL_ERROR) {
5164        return TCL_ERROR;
5165    }
5166
5167    cmdName = TclGetString(objv[0]);
5168    hTblPtr = iPtr->hiddenCmdTablePtr;
5169    if (hTblPtr != NULL) {
5170        hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
5171    }
5172    if (hPtr == NULL) {
5173        Tcl_AppendResult(interp, "invalid hidden command name \"",
5174                cmdName, "\"", NULL);
5175        return TCL_ERROR;
5176    }
5177    cmdPtr = Tcl_GetHashValue(hPtr);
5178
5179    /*
5180     * Invoke the command function.
5181     */
5182
5183    iPtr->cmdCount++;
5184    result = cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
5185
5186    /*
5187     * If an error occurred, record information about what was being executed
5188     * when the error occurred.
5189     */
5190
5191    if ((result == TCL_ERROR)
5192            && ((flags & TCL_INVOKE_NO_TRACEBACK) == 0)
5193            && ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
5194        int length;
5195        Tcl_Obj *command = Tcl_NewListObj(objc, objv);
5196        const char *cmdString;
5197
5198        Tcl_IncrRefCount(command);
5199        cmdString = Tcl_GetStringFromObj(command, &length);
5200        Tcl_LogCommandInfo(interp, cmdString, cmdString, length);
5201        Tcl_DecrRefCount(command);
5202        iPtr->flags &= ~ERR_ALREADY_LOGGED;
5203    }
5204    return result;
5205}
5206
5207/*
5208 *---------------------------------------------------------------------------
5209 *
5210 * Tcl_ExprString --
5211 *
5212 *      Evaluate an expression in a string and return its value in string
5213 *      form.
5214 *
5215 * Results:
5216 *      A standard Tcl result. If the result is TCL_OK, then the interp's
5217 *      result is set to the string value of the expression. If the result is
5218 *      TCL_ERROR, then the interp's result contains an error message.
5219 *
5220 * Side effects:
5221 *      A Tcl object is allocated to hold a copy of the expression string.
5222 *      This expression object is passed to Tcl_ExprObj and then deallocated.
5223 *
5224 *---------------------------------------------------------------------------
5225 */
5226
5227int
5228Tcl_ExprString(
5229    Tcl_Interp *interp,         /* Context in which to evaluate the
5230                                 * expression. */
5231    const char *expr)           /* Expression to evaluate. */
5232{
5233    int code = TCL_OK;
5234
5235    if (expr[0] == '\0') {
5236        /*
5237         * An empty string. Just set the interpreter's result to 0.
5238         */
5239
5240        Tcl_SetResult(interp, "0", TCL_VOLATILE);
5241    } else {
5242        Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, -1);
5243
5244        Tcl_IncrRefCount(exprObj);
5245        code = Tcl_ExprObj(interp, exprObj, &resultPtr);
5246        Tcl_DecrRefCount(exprObj);
5247        if (code == TCL_OK) {
5248            Tcl_SetObjResult(interp, resultPtr);
5249            Tcl_DecrRefCount(resultPtr);
5250        }
5251
5252        /*
5253         * Force the string rep of the interp result.
5254         */
5255
5256        (void) Tcl_GetStringResult(interp);
5257    }
5258    return code;
5259}
5260
5261/*
5262 *----------------------------------------------------------------------
5263 *
5264 * Tcl_AppendObjToErrorInfo --
5265 *
5266 *      Add a Tcl_Obj value to the errorInfo field that describes the current
5267 *      error.
5268 *
5269 * Results:
5270 *      None.
5271 *
5272 * Side effects:
5273 *      The value of the Tcl_obj is appended to the errorInfo field. If we are
5274 *      just starting to log an error, errorInfo is initialized from the error
5275 *      message in the interpreter's result.
5276 *
5277 *----------------------------------------------------------------------
5278 */
5279
5280void
5281Tcl_AppendObjToErrorInfo(
5282    Tcl_Interp *interp,         /* Interpreter to which error information
5283                                 * pertains. */
5284    Tcl_Obj *objPtr)            /* Message to record. */
5285{
5286    int length;
5287    const char *message = TclGetStringFromObj(objPtr, &length);
5288
5289    Tcl_IncrRefCount(objPtr);
5290    Tcl_AddObjErrorInfo(interp, message, length);
5291    Tcl_DecrRefCount(objPtr);
5292}
5293
5294/*
5295 *----------------------------------------------------------------------
5296 *
5297 * Tcl_AddErrorInfo --
5298 *
5299 *      Add information to the errorInfo field that describes the current
5300 *      error.
5301 *
5302 * Results:
5303 *      None.
5304 *
5305 * Side effects:
5306 *      The contents of message are appended to the errorInfo field. If we are
5307 *      just starting to log an error, errorInfo is initialized from the error
5308 *      message in the interpreter's result.
5309 *
5310 *----------------------------------------------------------------------
5311 */
5312
5313void
5314Tcl_AddErrorInfo(
5315    Tcl_Interp *interp,         /* Interpreter to which error information
5316                                 * pertains. */
5317    const char *message)        /* Message to record. */
5318{
5319    Tcl_AddObjErrorInfo(interp, message, -1);
5320}
5321
5322/*
5323 *----------------------------------------------------------------------
5324 *
5325 * Tcl_AddObjErrorInfo --
5326 *
5327 *      Add information to the errorInfo field that describes the current
5328 *      error. This routine differs from Tcl_AddErrorInfo by taking a byte
5329 *      pointer and length.
5330 *
5331 * Results:
5332 *      None.
5333 *
5334 * Side effects:
5335 *      "length" bytes from "message" are appended to the errorInfo field. If
5336 *      "length" is negative, use bytes up to the first NULL byte. If we are
5337 *      just starting to log an error, errorInfo is initialized from the error
5338 *      message in the interpreter's result.
5339 *
5340 *----------------------------------------------------------------------
5341 */
5342
5343void
5344Tcl_AddObjErrorInfo(
5345    Tcl_Interp *interp,         /* Interpreter to which error information
5346                                 * pertains. */
5347    const char *message,        /* Points to the first byte of an array of
5348                                 * bytes of the message. */
5349    int length)                 /* The number of bytes in the message. If < 0,
5350                                 * then append all bytes up to a NULL byte. */
5351{
5352    register Interp *iPtr = (Interp *) interp;
5353
5354    /*
5355     * If we are just starting to log an error, errorInfo is initialized from
5356     * the error message in the interpreter's result.
5357     */
5358
5359    iPtr->flags |= ERR_LEGACY_COPY;
5360    if (iPtr->errorInfo == NULL) {
5361        if (iPtr->result[0] != 0) {
5362            /*
5363             * The interp's string result is set, apparently by some extension
5364             * making a deprecated direct write to it. That extension may
5365             * expect interp->result to continue to be set, so we'll take
5366             * special pains to avoid clearing it, until we drop support for
5367             * interp->result completely.
5368             */
5369
5370            iPtr->errorInfo = Tcl_NewStringObj(interp->result, -1);
5371        } else {
5372            iPtr->errorInfo = iPtr->objResultPtr;
5373        }
5374        Tcl_IncrRefCount(iPtr->errorInfo);
5375        if (!iPtr->errorCode) {
5376            Tcl_SetErrorCode(interp, "NONE", NULL);
5377        }
5378    }
5379
5380    /*
5381     * Now append "message" to the end of errorInfo.
5382     */
5383
5384    if (length != 0) {
5385        if (Tcl_IsShared(iPtr->errorInfo)) {
5386            Tcl_DecrRefCount(iPtr->errorInfo);
5387            iPtr->errorInfo = Tcl_DuplicateObj(iPtr->errorInfo);
5388            Tcl_IncrRefCount(iPtr->errorInfo);
5389        }
5390        Tcl_AppendToObj(iPtr->errorInfo, message, length);
5391    }
5392}
5393
5394/*
5395 *---------------------------------------------------------------------------
5396 *
5397 * Tcl_VarEvalVA --
5398 *
5399 *      Given a variable number of string arguments, concatenate them all
5400 *      together and execute the result as a Tcl command.
5401 *
5402 * Results:
5403 *      A standard Tcl return result. An error message or other result may be
5404 *      left in the interp's result.
5405 *
5406 * Side effects:
5407 *      Depends on what was done by the command.
5408 *
5409 *---------------------------------------------------------------------------
5410 */
5411
5412int
5413Tcl_VarEvalVA(
5414    Tcl_Interp *interp,         /* Interpreter in which to evaluate command. */
5415    va_list argList)            /* Variable argument list. */
5416{
5417    Tcl_DString buf;
5418    char *string;
5419    int result;
5420
5421    /*
5422     * Copy the strings one after the other into a single larger string. Use
5423     * stack-allocated space for small commands, but if the command gets too
5424     * large than call ckalloc to create the space.
5425     */
5426
5427    Tcl_DStringInit(&buf);
5428    while (1) {
5429        string = va_arg(argList, char *);
5430        if (string == NULL) {
5431            break;
5432        }
5433        Tcl_DStringAppend(&buf, string, -1);
5434    }
5435
5436    result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
5437    Tcl_DStringFree(&buf);
5438    return result;
5439}
5440
5441/*
5442 *----------------------------------------------------------------------
5443 *
5444 * Tcl_VarEval --
5445 *
5446 *      Given a variable number of string arguments, concatenate them all
5447 *      together and execute the result as a Tcl command.
5448 *
5449 * Results:
5450 *      A standard Tcl return result. An error message or other result may be
5451 *      left in interp->result.
5452 *
5453 * Side effects:
5454 *      Depends on what was done by the command.
5455 *
5456 *----------------------------------------------------------------------
5457 */
5458        /* ARGSUSED */
5459int
5460Tcl_VarEval(
5461    Tcl_Interp *interp,
5462    ...)
5463{
5464    va_list argList;
5465    int result;
5466
5467    va_start(argList, interp);
5468    result = Tcl_VarEvalVA(interp, argList);
5469    va_end(argList);
5470
5471    return result;
5472}
5473
5474/*
5475 *----------------------------------------------------------------------
5476 *
5477 * Tcl_GlobalEval --
5478 *
5479 *      Evaluate a command at global level in an interpreter.
5480 *
5481 * Results:
5482 *      A standard Tcl result is returned, and the interp's result is modified
5483 *      accordingly.
5484 *
5485 * Side effects:
5486 *      The command string is executed in interp, and the execution is carried
5487 *      out in the variable context of global level (no functions active),
5488 *      just as if an "uplevel #0" command were being executed.
5489 *
5490 *----------------------------------------------------------------------
5491 */
5492
5493int
5494Tcl_GlobalEval(
5495    Tcl_Interp *interp,         /* Interpreter in which to evaluate command. */
5496    const char *command)        /* Command to evaluate. */
5497{
5498    register Interp *iPtr = (Interp *) interp;
5499    int result;
5500    CallFrame *savedVarFramePtr;
5501
5502    savedVarFramePtr = iPtr->varFramePtr;
5503    iPtr->varFramePtr = iPtr->rootFramePtr;
5504    result = Tcl_Eval(interp, command);
5505    iPtr->varFramePtr = savedVarFramePtr;
5506    return result;
5507}
5508
5509/*
5510 *----------------------------------------------------------------------
5511 *
5512 * Tcl_SetRecursionLimit --
5513 *
5514 *      Set the maximum number of recursive calls that may be active for an
5515 *      interpreter at once.
5516 *
5517 * Results:
5518 *      The return value is the old limit on nesting for interp.
5519 *
5520 * Side effects:
5521 *      None.
5522 *
5523 *----------------------------------------------------------------------
5524 */
5525
5526int
5527Tcl_SetRecursionLimit(
5528    Tcl_Interp *interp,         /* Interpreter whose nesting limit is to be
5529                                 * set. */
5530    int depth)                  /* New value for maximimum depth. */
5531{
5532    Interp *iPtr = (Interp *) interp;
5533    int old;
5534
5535    old = iPtr->maxNestingDepth;
5536    if (depth > 0) {
5537        iPtr->maxNestingDepth = depth;
5538    }
5539    return old;
5540}
5541
5542/*
5543 *----------------------------------------------------------------------
5544 *
5545 * Tcl_AllowExceptions --
5546 *
5547 *      Sets a flag in an interpreter so that exceptions can occur in the next
5548 *      call to Tcl_Eval without them being turned into errors.
5549 *
5550 * Results:
5551 *      None.
5552 *
5553 * Side effects:
5554 *      The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's evalFlags
5555 *      structure. See the reference documentation for more details.
5556 *
5557 *----------------------------------------------------------------------
5558 */
5559
5560void
5561Tcl_AllowExceptions(
5562    Tcl_Interp *interp)         /* Interpreter in which to set flag. */
5563{
5564    Interp *iPtr = (Interp *) interp;
5565
5566    iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS;
5567}
5568
5569/*
5570 *----------------------------------------------------------------------
5571 *
5572 * Tcl_GetVersion --
5573 *
5574 *      Get the Tcl major, minor, and patchlevel version numbers and the
5575 *      release type. A patch is a release type TCL_FINAL_RELEASE with a
5576 *      patchLevel > 0.
5577 *
5578 * Results:
5579 *      None.
5580 *
5581 * Side effects:
5582 *      None.
5583 *
5584 *----------------------------------------------------------------------
5585 */
5586
5587void
5588Tcl_GetVersion(
5589    int *majorV,
5590    int *minorV,
5591    int *patchLevelV,
5592    int *type)
5593{
5594    if (majorV != NULL) {
5595        *majorV = TCL_MAJOR_VERSION;
5596    }
5597    if (minorV != NULL) {
5598        *minorV = TCL_MINOR_VERSION;
5599    }
5600    if (patchLevelV != NULL) {
5601        *patchLevelV = TCL_RELEASE_SERIAL;
5602    }
5603    if (type != NULL) {
5604        *type = TCL_RELEASE_LEVEL;
5605    }
5606}
5607
5608/*
5609 *----------------------------------------------------------------------
5610 *
5611 * Math Functions --
5612 *
5613 *      This page contains the functions that implement all of the built-in
5614 *      math functions for expressions.
5615 *
5616 * Results:
5617 *      Each function returns TCL_OK if it succeeds and pushes an Tcl object
5618 *      holding the result. If it fails it returns TCL_ERROR and leaves an
5619 *      error message in the interpreter's result.
5620 *
5621 * Side effects:
5622 *      None.
5623 *
5624 *----------------------------------------------------------------------
5625 */
5626
5627static int
5628ExprCeilFunc(
5629    ClientData clientData,      /* Ignored */
5630    Tcl_Interp *interp,         /* The interpreter in which to execute the
5631                                 * function. */
5632    int objc,                   /* Actual parameter count. */
5633    Tcl_Obj *const *objv)       /* Actual parameter list. */
5634{
5635    int code;
5636    double d;
5637    mp_int big;
5638
5639    if (objc != 2) {
5640        MathFuncWrongNumArgs(interp, 2, objc, objv);
5641        return TCL_ERROR;
5642    }
5643    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
5644#ifdef ACCEPT_NAN
5645    if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
5646        Tcl_SetObjResult(interp, objv[1]);
5647        return TCL_OK;
5648    }
5649#endif
5650    if (code != TCL_OK) {
5651        return TCL_ERROR;
5652    }
5653    if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) {
5654        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclCeil(&big)));
5655        mp_clear(&big);
5656    } else {
5657        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ceil(d)));
5658    }
5659    return TCL_OK;
5660}
5661
5662static int
5663ExprFloorFunc(
5664    ClientData clientData,      /* Ignored */
5665    Tcl_Interp *interp,         /* The interpreter in which to execute the
5666                                 * function. */
5667    int objc,                   /* Actual parameter count. */
5668    Tcl_Obj *const *objv)       /* Actual parameter list. */
5669{
5670    int code;
5671    double d;
5672    mp_int big;
5673
5674    if (objc != 2) {
5675        MathFuncWrongNumArgs(interp, 2, objc, objv);
5676        return TCL_ERROR;
5677    }
5678    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
5679#ifdef ACCEPT_NAN
5680    if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
5681        Tcl_SetObjResult(interp, objv[1]);
5682        return TCL_OK;
5683    }
5684#endif
5685    if (code != TCL_OK) {
5686        return TCL_ERROR;
5687    }
5688    if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) {
5689        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclFloor(&big)));
5690        mp_clear(&big);
5691    } else {
5692        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(floor(d)));
5693    }
5694    return TCL_OK;
5695}
5696
5697static int
5698ExprIsqrtFunc(
5699    ClientData clientData,      /* Ignored */
5700    Tcl_Interp *interp,         /* The interpreter in which to execute. */
5701    int objc,                   /* Actual parameter count. */
5702    Tcl_Obj *const *objv)       /* Actual parameter list. */
5703{
5704    ClientData ptr;
5705    int type;
5706    double d;
5707    Tcl_WideInt w;
5708    mp_int big;
5709    int exact = 0;              /* Flag == 1 if the argument can be
5710                                 * represented in a double as an exact
5711                                 * integer. */
5712
5713    /*
5714     * Check syntax.
5715     */
5716
5717    if (objc != 2) {
5718        MathFuncWrongNumArgs(interp, 2, objc, objv);
5719        return TCL_ERROR;
5720    }
5721
5722    /*
5723     * Make sure that the arg is a number.
5724     */
5725
5726    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
5727        return TCL_ERROR;
5728    }
5729
5730    switch (type) {
5731    case TCL_NUMBER_NAN:
5732        Tcl_GetDoubleFromObj(interp, objv[1], &d);
5733        return TCL_ERROR;
5734    case TCL_NUMBER_DOUBLE:
5735        d = *((const double *) ptr);
5736        if (d < 0) {
5737            goto negarg;
5738        }
5739#ifdef IEEE_FLOATING_POINT
5740        if (d <= MAX_EXACT) {
5741            exact = 1;
5742        }
5743#endif
5744        if (!exact) {
5745            if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
5746                return TCL_ERROR;
5747            }
5748        }
5749        break;
5750    case TCL_NUMBER_BIG:
5751        if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
5752            return TCL_ERROR;
5753        }
5754        if (SIGN(&big) == MP_NEG) {
5755            mp_clear(&big);
5756            goto negarg;
5757        }
5758        break;
5759    default:
5760        if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
5761            return TCL_ERROR;
5762        }
5763        if (w < 0) {
5764            goto negarg;
5765        }
5766        d = (double) w;
5767#ifdef IEEE_FLOATING_POINT
5768        if (d < MAX_EXACT) {
5769            exact = 1;
5770        }
5771#endif
5772        if (!exact) {
5773            Tcl_GetBignumFromObj(interp, objv[1], &big);
5774        }
5775        break;
5776    }
5777
5778    if (exact) {
5779        Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d)));
5780    } else {
5781        mp_int root;
5782
5783        mp_init(&root);
5784        mp_sqrt(&big, &root);
5785        mp_clear(&big);
5786        Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root));
5787    }
5788
5789    return TCL_OK;
5790
5791  negarg:
5792    Tcl_SetObjResult(interp,
5793            Tcl_NewStringObj("square root of negative argument", -1));
5794    return TCL_ERROR;
5795}
5796
5797static int
5798ExprSqrtFunc(
5799    ClientData clientData,      /* Ignored */
5800    Tcl_Interp *interp,         /* The interpreter in which to execute the
5801                                 * function. */
5802    int objc,                   /* Actual parameter count. */
5803    Tcl_Obj *const *objv)       /* Actual parameter list. */
5804{
5805    int code;
5806    double d;
5807    mp_int big;
5808
5809    if (objc != 2) {
5810        MathFuncWrongNumArgs(interp, 2, objc, objv);
5811        return TCL_ERROR;
5812    }
5813    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
5814#ifdef ACCEPT_NAN
5815    if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
5816        Tcl_SetObjResult(interp, objv[1]);
5817        return TCL_OK;
5818    }
5819#endif
5820    if (code != TCL_OK) {
5821        return TCL_ERROR;
5822    }
5823    if ((d >= 0.0) && TclIsInfinite(d)
5824            && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) {
5825        mp_int root;
5826
5827        mp_init(&root);
5828        mp_sqrt(&big, &root);
5829        mp_clear(&big);
5830        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclBignumToDouble(&root)));
5831        mp_clear(&root);
5832    } else {
5833        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
5834    }
5835    return TCL_OK;
5836}
5837
5838static int
5839ExprUnaryFunc(
5840    ClientData clientData,      /* Contains the address of a function that
5841                                 * takes one double argument and returns a
5842                                 * double result. */
5843    Tcl_Interp *interp,         /* The interpreter in which to execute the
5844                                 * function. */
5845    int objc,                   /* Actual parameter count */
5846    Tcl_Obj *const *objv)       /* Actual parameter list */
5847{
5848    int code;
5849    double d;
5850    double (*func)(double) = (double (*)(double)) clientData;
5851
5852    if (objc != 2) {
5853        MathFuncWrongNumArgs(interp, 2, objc, objv);
5854        return TCL_ERROR;
5855    }
5856    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
5857#ifdef ACCEPT_NAN
5858    if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
5859        d = objv[1]->internalRep.doubleValue;
5860        Tcl_ResetResult(interp);
5861        code = TCL_OK;
5862    }
5863#endif
5864    if (code != TCL_OK) {
5865        return TCL_ERROR;
5866    }
5867    errno = 0;
5868    return CheckDoubleResult(interp, (*func)(d));
5869}
5870
5871static int
5872CheckDoubleResult(
5873    Tcl_Interp *interp,
5874    double dResult)
5875{
5876#ifndef ACCEPT_NAN
5877    if (TclIsNaN(dResult)) {
5878        TclExprFloatError(interp, dResult);
5879        return TCL_ERROR;
5880    }
5881#endif
5882    if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(dResult))) {
5883        /*
5884         * When ERANGE signals under/overflow, just accept 0.0 or +/-Inf
5885         */
5886    } else if (errno != 0) {
5887        /*
5888         * Report other errno values as errors.
5889         */
5890
5891        TclExprFloatError(interp, dResult);
5892        return TCL_ERROR;
5893    }
5894    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
5895    return TCL_OK;
5896}
5897
5898static int
5899ExprBinaryFunc(
5900    ClientData clientData,      /* Contains the address of a function that
5901                                 * takes two double arguments and returns a
5902                                 * double result. */
5903    Tcl_Interp *interp,         /* The interpreter in which to execute the
5904                                 * function. */
5905    int objc,                   /* Actual parameter count. */
5906    Tcl_Obj *const *objv)       /* Parameter vector. */
5907{
5908    int code;
5909    double d1, d2;
5910    double (*func)(double, double) = (double (*)(double, double)) clientData;
5911
5912    if (objc != 3) {
5913        MathFuncWrongNumArgs(interp, 3, objc, objv);
5914        return TCL_ERROR;
5915    }
5916    code = Tcl_GetDoubleFromObj(interp, objv[1], &d1);
5917#ifdef ACCEPT_NAN
5918    if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
5919        d1 = objv[1]->internalRep.doubleValue;
5920        Tcl_ResetResult(interp);
5921        code = TCL_OK;
5922    }
5923#endif
5924    if (code != TCL_OK) {
5925        return TCL_ERROR;
5926    }
5927    code = Tcl_GetDoubleFromObj(interp, objv[2], &d2);
5928#ifdef ACCEPT_NAN
5929    if ((code != TCL_OK) && (objv[2]->typePtr == &tclDoubleType)) {
5930        d2 = objv[2]->internalRep.doubleValue;
5931        Tcl_ResetResult(interp);
5932        code = TCL_OK;
5933    }
5934#endif
5935    if (code != TCL_OK) {
5936        return TCL_ERROR;
5937    }
5938    errno = 0;
5939    return CheckDoubleResult(interp, (*func)(d1, d2));
5940}
5941
5942static int
5943ExprAbsFunc(
5944    ClientData clientData,      /* Ignored. */
5945    Tcl_Interp *interp,         /* The interpreter in which to execute the
5946                                 * function. */
5947    int objc,                   /* Actual parameter count. */
5948    Tcl_Obj *const *objv)       /* Parameter vector. */
5949{
5950    ClientData ptr;
5951    int type;
5952    mp_int big;
5953
5954    if (objc != 2) {
5955        MathFuncWrongNumArgs(interp, 2, objc, objv);
5956        return TCL_ERROR;
5957    }
5958
5959    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
5960        return TCL_ERROR;
5961    }
5962
5963    if (type == TCL_NUMBER_LONG) {
5964        long l = *((const long *) ptr);
5965        if (l <= (long)0) {
5966            if (l == LONG_MIN) {
5967                TclBNInitBignumFromLong(&big, l);
5968                goto tooLarge;
5969            }
5970            Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
5971        } else {
5972            Tcl_SetObjResult(interp, objv[1]);
5973        }
5974        return TCL_OK;
5975    }
5976
5977    if (type == TCL_NUMBER_DOUBLE) {
5978        double d = *((const double *) ptr);
5979        if (d <= 0.0) {
5980            Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
5981        } else {
5982            Tcl_SetObjResult(interp, objv[1]);
5983        }
5984        return TCL_OK;
5985    }
5986
5987#ifndef NO_WIDE_TYPE
5988    if (type == TCL_NUMBER_WIDE) {
5989        Tcl_WideInt w = *((const Tcl_WideInt *) ptr);
5990        if (w < (Tcl_WideInt)0) {
5991            if (w == LLONG_MIN) {
5992                TclBNInitBignumFromWideInt(&big, w);
5993                goto tooLarge;
5994            }
5995            Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
5996        } else {
5997            Tcl_SetObjResult(interp, objv[1]);
5998        }
5999        return TCL_OK;
6000    }
6001#endif
6002
6003    if (type == TCL_NUMBER_BIG) {
6004        /* TODO: const correctness ? */
6005        if (mp_cmp_d((mp_int *) ptr, 0) == MP_LT) {
6006            Tcl_GetBignumFromObj(NULL, objv[1], &big);
6007        tooLarge:
6008            mp_neg(&big, &big);
6009            Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
6010        } else {
6011            Tcl_SetObjResult(interp, objv[1]);
6012        }
6013        return TCL_OK;
6014    }
6015
6016    if (type == TCL_NUMBER_NAN) {
6017#ifdef ACCEPT_NAN
6018        Tcl_SetObjResult(interp, objv[1]);
6019        return TCL_OK;
6020#else
6021        double d;
6022        Tcl_GetDoubleFromObj(interp, objv[1], &d);
6023        return TCL_ERROR;
6024#endif
6025    }
6026    return TCL_OK;
6027}
6028
6029static int
6030ExprBoolFunc(
6031    ClientData clientData,      /* Ignored. */
6032    Tcl_Interp *interp,         /* The interpreter in which to execute the
6033                                 * function. */
6034    int objc,                   /* Actual parameter count. */
6035    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6036{
6037    int value;
6038
6039    if (objc != 2) {
6040        MathFuncWrongNumArgs(interp, 2, objc, objv);
6041        return TCL_ERROR;
6042    }
6043    if (Tcl_GetBooleanFromObj(interp, objv[1], &value) != TCL_OK) {
6044        return TCL_ERROR;
6045    }
6046    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
6047    return TCL_OK;
6048}
6049
6050static int
6051ExprDoubleFunc(
6052    ClientData clientData,      /* Ignored. */
6053    Tcl_Interp *interp,         /* The interpreter in which to execute the
6054                                 * function. */
6055    int objc,                   /* Actual parameter count. */
6056    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6057{
6058    double dResult;
6059    if (objc != 2) {
6060        MathFuncWrongNumArgs(interp, 2, objc, objv);
6061        return TCL_ERROR;
6062    }
6063    if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
6064#ifdef ACCEPT_NAN
6065        if (objv[1]->typePtr == &tclDoubleType) {
6066            Tcl_SetObjResult(interp, objv[1]);
6067            return TCL_OK;
6068        }
6069#endif
6070        return TCL_ERROR;
6071    }
6072    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
6073    return TCL_OK;
6074}
6075
6076static int
6077ExprEntierFunc(
6078    ClientData clientData,      /* Ignored. */
6079    Tcl_Interp *interp,         /* The interpreter in which to execute the
6080                                 * function. */
6081    int objc,                   /* Actual parameter count. */
6082    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6083{
6084    double d;
6085    int type;
6086    ClientData ptr;
6087
6088    if (objc != 2) {
6089        MathFuncWrongNumArgs(interp, 2, objc, objv);
6090        return TCL_ERROR;
6091    }
6092    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
6093        return TCL_ERROR;
6094    }
6095
6096    if (type == TCL_NUMBER_DOUBLE) {
6097        d = *((const double *) ptr);
6098        if ((d >= (double)LONG_MAX) || (d <= (double)LONG_MIN)) {
6099            mp_int big;
6100
6101            if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
6102                /* Infinity */
6103                return TCL_ERROR;
6104            }
6105            Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
6106            return TCL_OK;
6107        } else {
6108            long result = (long) d;
6109
6110            Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
6111            return TCL_OK;
6112        }
6113    }
6114
6115    if (type != TCL_NUMBER_NAN) {
6116        /*
6117         * All integers are already of integer type.
6118         */
6119
6120        Tcl_SetObjResult(interp, objv[1]);
6121        return TCL_OK;
6122    }
6123
6124    /*
6125     * Get the error message for NaN.
6126     */
6127
6128    Tcl_GetDoubleFromObj(interp, objv[1], &d);
6129    return TCL_ERROR;
6130}
6131
6132static int
6133ExprIntFunc(
6134    ClientData clientData,      /* Ignored. */
6135    Tcl_Interp *interp,         /* The interpreter in which to execute the
6136                                 * function. */
6137    int objc,                   /* Actual parameter count. */
6138    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6139{
6140    long iResult;
6141    Tcl_Obj *objPtr;
6142    if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) {
6143        return TCL_ERROR;
6144    }
6145    objPtr = Tcl_GetObjResult(interp);
6146    if (TclGetLongFromObj(NULL, objPtr, &iResult) != TCL_OK) {
6147        /*
6148         * Truncate the bignum; keep only bits in long range.
6149         */
6150
6151        mp_int big;
6152
6153        Tcl_GetBignumFromObj(NULL, objPtr, &big);
6154        mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
6155        objPtr = Tcl_NewBignumObj(&big);
6156        Tcl_IncrRefCount(objPtr);
6157        TclGetLongFromObj(NULL, objPtr, &iResult);
6158        Tcl_DecrRefCount(objPtr);
6159    }
6160    Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
6161    return TCL_OK;
6162}
6163
6164static int
6165ExprWideFunc(
6166    ClientData clientData,      /* Ignored. */
6167    Tcl_Interp *interp,         /* The interpreter in which to execute the
6168                                 * function. */
6169    int objc,                   /* Actual parameter count. */
6170    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6171{
6172    Tcl_WideInt wResult;
6173    Tcl_Obj *objPtr;
6174    if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) {
6175        return TCL_ERROR;
6176    }
6177    objPtr = Tcl_GetObjResult(interp);
6178    if (Tcl_GetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
6179        /*
6180         * Truncate the bignum; keep only bits in wide int range.
6181         */
6182
6183        mp_int big;
6184
6185        Tcl_GetBignumFromObj(NULL, objPtr, &big);
6186        mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
6187        objPtr = Tcl_NewBignumObj(&big);
6188        Tcl_IncrRefCount(objPtr);
6189        Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
6190        Tcl_DecrRefCount(objPtr);
6191    }
6192    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
6193    return TCL_OK;
6194}
6195
6196static int
6197ExprRandFunc(
6198    ClientData clientData,      /* Ignored. */
6199    Tcl_Interp *interp,         /* The interpreter in which to execute the
6200                                 * function. */
6201    int objc,                   /* Actual parameter count. */
6202    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6203{
6204    Interp *iPtr = (Interp *) interp;
6205    double dResult;
6206    long tmp;                   /* Algorithm assumes at least 32 bits. Only
6207                                 * long guarantees that. See below. */
6208    Tcl_Obj *oResult;
6209
6210    if (objc != 1) {
6211        MathFuncWrongNumArgs(interp, 1, objc, objv);
6212        return TCL_ERROR;
6213    }
6214
6215    if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
6216        iPtr->flags |= RAND_SEED_INITIALIZED;
6217
6218        /*
6219         * Take into consideration the thread this interp is running in order
6220         * to insure different seeds in different threads (bug #416643)
6221         */
6222
6223        iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
6224
6225        /*
6226         * Make sure 1 <= randSeed <= (2^31) - 2. See below.
6227         */
6228
6229        iPtr->randSeed &= (unsigned long) 0x7fffffff;
6230        if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
6231            iPtr->randSeed ^= 123459876;
6232        }
6233    }
6234
6235    /*
6236     * Generate the random number using the linear congruential generator
6237     * defined by the following recurrence:
6238     *          seed = ( IA * seed ) mod IM
6239     * where IA is 16807 and IM is (2^31) - 1. The recurrence maps a seed in
6240     * the range [1, IM - 1] to a new seed in that same range. The recurrence
6241     * maps IM to 0, and maps 0 back to 0, so those two values must not be
6242     * allowed as initial values of seed.
6243     *
6244     * In order to avoid potential problems with integer overflow, the
6245     * recurrence is implemented in terms of additional constants IQ and IR
6246     * such that
6247     *          IM = IA*IQ + IR
6248     * None of the operations in the implementation overflows a 32-bit signed
6249     * integer, and the C type long is guaranteed to be at least 32 bits wide.
6250     *
6251     * For more details on how this algorithm works, refer to the following
6252     * papers:
6253     *
6254     *  S.K. Park & K.W. Miller, "Random number generators: good ones are hard
6255     *  to find," Comm ACM 31(10):1192-1201, Oct 1988
6256     *
6257     *  W.H. Press & S.A. Teukolsky, "Portable random number generators,"
6258     *  Computers in Physics 6(5):522-524, Sep/Oct 1992.
6259     */
6260
6261#define RAND_IA         16807
6262#define RAND_IM         2147483647
6263#define RAND_IQ         127773
6264#define RAND_IR         2836
6265#define RAND_MASK       123459876
6266
6267    tmp = iPtr->randSeed/RAND_IQ;
6268    iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
6269    if (iPtr->randSeed < 0) {
6270        iPtr->randSeed += RAND_IM;
6271    }
6272
6273    /*
6274     * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
6275     * dividing by RAND_IM yields a double in the range (0, 1).
6276     */
6277
6278    dResult = iPtr->randSeed * (1.0/RAND_IM);
6279
6280    /*
6281     * Push a Tcl object with the result.
6282     */
6283
6284    TclNewDoubleObj(oResult, dResult);
6285    Tcl_SetObjResult(interp, oResult);
6286    return TCL_OK;
6287}
6288
6289static int
6290ExprRoundFunc(
6291    ClientData clientData,      /* Ignored. */
6292    Tcl_Interp *interp,         /* The interpreter in which to execute the
6293                                 * function. */
6294    int objc,                   /* Actual parameter count. */
6295    Tcl_Obj *const *objv)       /* Parameter vector. */
6296{
6297    double d;
6298    ClientData ptr;
6299    int type;
6300
6301    if (objc != 2) {
6302        MathFuncWrongNumArgs(interp, 1, objc, objv);
6303        return TCL_ERROR;
6304    }
6305
6306    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
6307        return TCL_ERROR;
6308    }
6309
6310    if (type == TCL_NUMBER_DOUBLE) {
6311        double fractPart, intPart;
6312        long max = LONG_MAX, min = LONG_MIN;
6313
6314        fractPart = modf(*((const double *) ptr), &intPart);
6315        if (fractPart <= -0.5) {
6316            min++;
6317        } else if (fractPart >= 0.5) {
6318            max--;
6319        }
6320        if ((intPart >= (double)max) || (intPart <= (double)min)) {
6321            mp_int big;
6322
6323            if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) {
6324                /* Infinity */
6325                return TCL_ERROR;
6326            }
6327            if (fractPart <= -0.5) {
6328                mp_sub_d(&big, 1, &big);
6329            } else if (fractPart >= 0.5) {
6330                mp_add_d(&big, 1, &big);
6331            }
6332            Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
6333            return TCL_OK;
6334        } else {
6335            long result = (long)intPart;
6336
6337            if (fractPart <= -0.5) {
6338                result--;
6339            } else if (fractPart >= 0.5) {
6340                result++;
6341            }
6342            Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
6343            return TCL_OK;
6344        }
6345    }
6346
6347    if (type != TCL_NUMBER_NAN) {
6348        /*
6349         * All integers are already rounded
6350         */
6351
6352        Tcl_SetObjResult(interp, objv[1]);
6353        return TCL_OK;
6354    }
6355
6356    /*
6357     * Get the error message for NaN.
6358     */
6359
6360    Tcl_GetDoubleFromObj(interp, objv[1], &d);
6361    return TCL_ERROR;
6362}
6363
6364static int
6365ExprSrandFunc(
6366    ClientData clientData,      /* Ignored. */
6367    Tcl_Interp *interp,         /* The interpreter in which to execute the
6368                                 * function. */
6369    int objc,                   /* Actual parameter count. */
6370    Tcl_Obj *const *objv)       /* Parameter vector. */
6371{
6372    Interp *iPtr = (Interp *) interp;
6373    long i = 0;                 /* Initialized to avoid compiler warning. */
6374
6375    /*
6376     * Convert argument and use it to reset the seed.
6377     */
6378
6379    if (objc != 2) {
6380        MathFuncWrongNumArgs(interp, 2, objc, objv);
6381        return TCL_ERROR;
6382    }
6383
6384    if (TclGetLongFromObj(NULL, objv[1], &i) != TCL_OK) {
6385        Tcl_Obj *objPtr;
6386        mp_int big;
6387
6388        if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
6389            /* TODO: more ::errorInfo here? or in caller? */
6390            return TCL_ERROR;
6391        }
6392
6393        mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
6394        objPtr = Tcl_NewBignumObj(&big);
6395        Tcl_IncrRefCount(objPtr);
6396        TclGetLongFromObj(NULL, objPtr, &i);
6397        Tcl_DecrRefCount(objPtr);
6398    }
6399
6400    /*
6401     * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2. See comments in
6402     * ExprRandFunc() for more details.
6403     */
6404
6405    iPtr->flags |= RAND_SEED_INITIALIZED;
6406    iPtr->randSeed = i;
6407    iPtr->randSeed &= (unsigned long) 0x7fffffff;
6408    if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
6409        iPtr->randSeed ^= 123459876;
6410    }
6411
6412    /*
6413     * To avoid duplicating the random number generation code we simply clean
6414     * up our state and call the real random number function. That function
6415     * will always succeed.
6416     */
6417
6418    return ExprRandFunc(clientData, interp, 1, objv);
6419}
6420
6421/*
6422 *----------------------------------------------------------------------
6423 *
6424 * MathFuncWrongNumArgs --
6425 *
6426 *      Generate an error message when a math function presents the wrong
6427 *      number of arguments.
6428 *
6429 * Results:
6430 *      None.
6431 *
6432 * Side effects:
6433 *      An error message is stored in the interpreter result.
6434 *
6435 *----------------------------------------------------------------------
6436 */
6437
6438static void
6439MathFuncWrongNumArgs(
6440    Tcl_Interp *interp,         /* Tcl interpreter */
6441    int expected,               /* Formal parameter count. */
6442    int found,                  /* Actual parameter count. */
6443    Tcl_Obj *const *objv)       /* Actual parameter vector. */
6444{
6445    const char *name = Tcl_GetString(objv[0]);
6446    const char *tail = name + strlen(name);
6447
6448    while (tail > name+1) {
6449        --tail;
6450        if (*tail == ':' && tail[-1] == ':') {
6451            name = tail+1;
6452            break;
6453        }
6454    }
6455    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
6456            "too %s arguments for math function \"%s\"",
6457            (found < expected ? "few" : "many"), name));
6458}
6459#ifdef USE_DTRACE
6460
6461/*
6462 *----------------------------------------------------------------------
6463 *
6464 * DTraceObjCmd --
6465 *
6466 *      This function is invoked to process the "::tcl::dtrace" Tcl command.
6467 *
6468 * Results:
6469 *      A standard Tcl object result.
6470 *
6471 * Side effects:
6472 *      The 'tcl-probe' DTrace probe is triggered (if it is enabled).
6473 *
6474 *----------------------------------------------------------------------
6475 */
6476
6477static int
6478DTraceObjCmd(
6479    ClientData dummy,           /* Not used. */
6480    Tcl_Interp *interp,         /* Current interpreter. */
6481    int objc,                   /* Number of arguments. */
6482    Tcl_Obj *const objv[])      /* Argument objects. */
6483{
6484    if (TCL_DTRACE_TCL_PROBE_ENABLED()) {
6485        char *a[10];
6486        int i = 0;
6487
6488        while (i++ < 10) {
6489            a[i-1] = i < objc ? TclGetString(objv[i]) : NULL;
6490        }
6491        TCL_DTRACE_TCL_PROBE(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
6492                a[8], a[9]);
6493    }
6494    return TCL_OK;
6495}
6496
6497/*
6498 *----------------------------------------------------------------------
6499 *
6500 * TclDTraceInfo --
6501 *
6502 *      Extract information from a TIP280 dict for use by DTrace probes.
6503 *
6504 * Results:
6505 *      None.
6506 *
6507 * Side effects:
6508 *      None.
6509 *
6510 *----------------------------------------------------------------------
6511 */
6512
6513void
6514TclDTraceInfo(
6515    Tcl_Obj *info,
6516    char **args,
6517    int *argsi)
6518{
6519    static Tcl_Obj *keys[7] = { NULL };
6520    Tcl_Obj **k = keys, *val;
6521    int i;
6522
6523    if (!*k) {
6524        TclNewLiteralStringObj(keys[0], "cmd");
6525        TclNewLiteralStringObj(keys[1], "type");
6526        TclNewLiteralStringObj(keys[2], "proc");
6527        TclNewLiteralStringObj(keys[3], "file");
6528        TclNewLiteralStringObj(keys[4], "lambda");
6529        TclNewLiteralStringObj(keys[5], "line");
6530        TclNewLiteralStringObj(keys[6], "level");
6531    }
6532    for (i = 0; i < 4; i++) {
6533        Tcl_DictObjGet(NULL, info, *k++, &val);
6534        args[i] = val ? TclGetString(val) : NULL;
6535    }
6536    if (!args[2]) {
6537        Tcl_DictObjGet(NULL, info, *k, &val);
6538        args[2] = val ? TclGetString(val) : NULL;
6539    }
6540    k++;
6541    for (i = 0; i < 2; i++) {
6542        Tcl_DictObjGet(NULL, info, *k++, &val);
6543        if (val) {
6544            TclGetIntFromObj(NULL, val, &(argsi[i]));
6545        } else {
6546            argsi[i] = 0;
6547        }
6548    }
6549}
6550#endif /* USE_DTRACE */
6551
6552/*
6553 * Local Variables:
6554 * mode: c
6555 * c-basic-offset: 4
6556 * fill-column: 78
6557 * End:
6558 */
Note: See TracBrowser for help on using the repository browser.