tclBasic.c

Go to the documentation of this file.
00001 /*
00002  * tclBasic.c --
00003  *
00004  *      Contains the basic facilities for TCL command interpretation,
00005  *      including interpreter creation and deletion, command creation and
00006  *      deletion, and command/script execution.
00007  *
00008  * Copyright (c) 1987-1994 The Regents of the University of California.
00009  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
00010  * Copyright (c) 1998-1999 by Scriptics Corporation.
00011  * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
00012  * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
00013  *
00014  * See the file "license.terms" for information on usage and redistribution of
00015  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
00016  *
00017  * RCS: @(#) $Id: tclBasic.c,v 1.291 2008/01/23 21:21:26 dgp Exp $
00018  */
00019 
00020 #include "tclInt.h"
00021 #include "tclCompile.h"
00022 #include <float.h>
00023 #include <limits.h>
00024 #include <math.h>
00025 #include "tommath.h"
00026 
00027 /*
00028  * Determine whether we're using IEEE floating point
00029  */
00030 
00031 #if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
00032 #   define IEEE_FLOATING_POINT
00033 /* Largest odd integer that can be represented exactly in a double */
00034 #   define MAX_EXACT 9007199254740991.0
00035 #endif
00036 
00037 /*
00038  * The following structure defines the client data for a math function
00039  * registered with Tcl_CreateMathFunc
00040  */
00041 
00042 typedef struct OldMathFuncData {
00043     Tcl_MathProc *proc;         /* Handler function */
00044     int numArgs;                /* Number of args expected */
00045     Tcl_ValueType *argTypes;    /* Types of the args */
00046     ClientData clientData;      /* Client data for the handler function */
00047 } OldMathFuncData;
00048 
00049 /*
00050  * Static functions in this file:
00051  */
00052 
00053 static char *   CallCommandTraces(Interp *iPtr, Command *cmdPtr,
00054                     const char *oldName, const char *newName, int flags);
00055 static int      CheckDoubleResult(Tcl_Interp *interp, double dResult);
00056 static void     DeleteInterpProc(Tcl_Interp *interp);
00057 static void     DeleteOpCmdClientData(ClientData clientData);
00058 static Tcl_Obj *GetCommandSource(Interp *iPtr, const char *command,
00059                     int numChars, int objc, Tcl_Obj *const objv[]);
00060 static void     ProcessUnexpectedResult(Tcl_Interp *interp, int returnCode);
00061 static int      OldMathFuncProc(ClientData clientData, Tcl_Interp *interp,
00062                     int argc, Tcl_Obj *const *objv);
00063 static void     OldMathFuncDeleteProc(ClientData clientData);
00064 static int      ExprAbsFunc(ClientData clientData, Tcl_Interp *interp,
00065                     int argc, Tcl_Obj *const *objv);
00066 static int      ExprBinaryFunc(ClientData clientData, Tcl_Interp *interp,
00067                     int argc, Tcl_Obj *const *objv);
00068 static int      ExprBoolFunc(ClientData clientData, Tcl_Interp *interp,
00069                     int argc, Tcl_Obj *const *objv);
00070 static int      ExprCeilFunc(ClientData clientData, Tcl_Interp *interp,
00071                     int argc, Tcl_Obj *const *objv);
00072 static int      ExprDoubleFunc(ClientData clientData, Tcl_Interp *interp,
00073                     int argc, Tcl_Obj *const *objv);
00074 static int      ExprEntierFunc(ClientData clientData, Tcl_Interp *interp,
00075                     int argc, Tcl_Obj *const *objv);
00076 static int      ExprFloorFunc(ClientData clientData, Tcl_Interp *interp,
00077                     int argc, Tcl_Obj *const *objv);
00078 static int      ExprIntFunc(ClientData clientData, Tcl_Interp *interp,
00079                     int argc, Tcl_Obj *const *objv);
00080 static int      ExprIsqrtFunc(ClientData clientData, Tcl_Interp *interp,
00081                     int argc, Tcl_Obj *const *objv);
00082 static int      ExprRandFunc(ClientData clientData, Tcl_Interp *interp,
00083                     int argc, Tcl_Obj *const *objv);
00084 static int      ExprRoundFunc(ClientData clientData, Tcl_Interp *interp,
00085                     int argc, Tcl_Obj *const *objv);
00086 static int      ExprSqrtFunc(ClientData clientData, Tcl_Interp *interp,
00087                     int argc, Tcl_Obj *const *objv);
00088 static int      ExprSrandFunc(ClientData clientData, Tcl_Interp *interp,
00089                     int argc, Tcl_Obj *const *objv);
00090 static int      ExprUnaryFunc(ClientData clientData, Tcl_Interp *interp,
00091                     int argc, Tcl_Obj *const *objv);
00092 static int      ExprWideFunc(ClientData clientData, Tcl_Interp *interp,
00093                     int argc, Tcl_Obj *const *objv);
00094 static void     MathFuncWrongNumArgs(Tcl_Interp *interp, int expected,
00095                     int actual, Tcl_Obj *const *objv);
00096 #ifdef USE_DTRACE
00097 static int      DTraceObjCmd(ClientData dummy, Tcl_Interp *interp, int objc,
00098                     Tcl_Obj *const objv[]);
00099 #endif
00100 
00101 extern TclStubs tclStubs;
00102 
00103 /*
00104  * The following structure define the commands in the Tcl core.
00105  */
00106 
00107 typedef struct {
00108     const char *name;           /* Name of object-based command. */
00109     Tcl_ObjCmdProc *objProc;    /* Object-based function for command. */
00110     CompileProc *compileProc;   /* Function called to compile command. */
00111     int isSafe;                 /* If non-zero, command will be present in
00112                                  * safe interpreter. Otherwise it will be
00113                                  * hidden. */
00114 } CmdInfo;
00115 
00116 /*
00117  * The built-in commands, and the functions that implement them:
00118  */
00119 
00120 static const CmdInfo builtInCmds[] = {
00121     /*
00122      * Commands in the generic core.
00123      */
00124 
00125     {"append",          Tcl_AppendObjCmd,       TclCompileAppendCmd,    1},
00126     {"apply",           Tcl_ApplyObjCmd,        NULL,                   1},
00127     {"array",           Tcl_ArrayObjCmd,        NULL,                   1},
00128     {"binary",          Tcl_BinaryObjCmd,       NULL,                   1},
00129     {"break",           Tcl_BreakObjCmd,        TclCompileBreakCmd,     1},
00130 #ifndef EXCLUDE_OBSOLETE_COMMANDS
00131     {"case",            Tcl_CaseObjCmd,         NULL,                   1},
00132 #endif
00133     {"catch",           Tcl_CatchObjCmd,        TclCompileCatchCmd,     1},
00134     {"concat",          Tcl_ConcatObjCmd,       NULL,                   1},
00135     {"continue",        Tcl_ContinueObjCmd,     TclCompileContinueCmd,  1},
00136     {"error",           Tcl_ErrorObjCmd,        NULL,                   1},
00137     {"eval",            Tcl_EvalObjCmd,         NULL,                   1},
00138     {"expr",            Tcl_ExprObjCmd,         TclCompileExprCmd,      1},
00139     {"for",             Tcl_ForObjCmd,          TclCompileForCmd,       1},
00140     {"foreach",         Tcl_ForeachObjCmd,      TclCompileForeachCmd,   1},
00141     {"format",          Tcl_FormatObjCmd,       NULL,                   1},
00142     {"global",          Tcl_GlobalObjCmd,       TclCompileGlobalCmd,    1},
00143     {"if",              Tcl_IfObjCmd,           TclCompileIfCmd,        1},
00144     {"incr",            Tcl_IncrObjCmd,         TclCompileIncrCmd,      1},
00145     {"join",            Tcl_JoinObjCmd,         NULL,                   1},
00146     {"lappend",         Tcl_LappendObjCmd,      TclCompileLappendCmd,   1},
00147     {"lassign",         Tcl_LassignObjCmd,      TclCompileLassignCmd,   1},
00148     {"lindex",          Tcl_LindexObjCmd,       TclCompileLindexCmd,    1},
00149     {"linsert",         Tcl_LinsertObjCmd,      NULL,                   1},
00150     {"list",            Tcl_ListObjCmd,         TclCompileListCmd,      1},
00151     {"llength",         Tcl_LlengthObjCmd,      TclCompileLlengthCmd,   1},
00152     {"lrange",          Tcl_LrangeObjCmd,       NULL,                   1},
00153     {"lrepeat",         Tcl_LrepeatObjCmd,      NULL,                   1},
00154     {"lreplace",        Tcl_LreplaceObjCmd,     NULL,                   1},
00155     {"lreverse",        Tcl_LreverseObjCmd,     NULL,                   1},
00156     {"lsearch",         Tcl_LsearchObjCmd,      NULL,                   1},
00157     {"lset",            Tcl_LsetObjCmd,         TclCompileLsetCmd,      1},
00158     {"lsort",           Tcl_LsortObjCmd,        NULL,                   1},
00159     {"namespace",       Tcl_NamespaceObjCmd,    TclCompileNamespaceCmd, 1},
00160     {"package",         Tcl_PackageObjCmd,      NULL,                   1},
00161     {"proc",            Tcl_ProcObjCmd,         NULL,                   1},
00162     {"regexp",          Tcl_RegexpObjCmd,       TclCompileRegexpCmd,    1},
00163     {"regsub",          Tcl_RegsubObjCmd,       NULL,                   1},
00164     {"rename",          Tcl_RenameObjCmd,       NULL,                   1},
00165     {"return",          Tcl_ReturnObjCmd,       TclCompileReturnCmd,    1},
00166     {"scan",            Tcl_ScanObjCmd,         NULL,                   1},
00167     {"set",             Tcl_SetObjCmd,          TclCompileSetCmd,       1},
00168     {"split",           Tcl_SplitObjCmd,        NULL,                   1},
00169     {"subst",           Tcl_SubstObjCmd,        NULL,                   1},
00170     {"switch",          Tcl_SwitchObjCmd,       TclCompileSwitchCmd,    1},
00171     {"trace",           Tcl_TraceObjCmd,        NULL,                   1},
00172     {"unset",           Tcl_UnsetObjCmd,        NULL,                   1},
00173     {"uplevel",         Tcl_UplevelObjCmd,      NULL,                   1},
00174     {"upvar",           Tcl_UpvarObjCmd,        TclCompileUpvarCmd,     1},
00175     {"variable",        Tcl_VariableObjCmd,     TclCompileVariableCmd,  1},
00176     {"while",           Tcl_WhileObjCmd,        TclCompileWhileCmd,     1},
00177 
00178     /*
00179      * Commands in the OS-interface. Note that many of these are unsafe.
00180      */
00181 
00182     {"after",           Tcl_AfterObjCmd,        NULL,                   1},
00183     {"cd",              Tcl_CdObjCmd,           NULL,                   0},
00184     {"close",           Tcl_CloseObjCmd,        NULL,                   1},
00185     {"eof",             Tcl_EofObjCmd,          NULL,                   1},
00186     {"encoding",        Tcl_EncodingObjCmd,     NULL,                   0},
00187     {"exec",            Tcl_ExecObjCmd,         NULL,                   0},
00188     {"exit",            Tcl_ExitObjCmd,         NULL,                   0},
00189     {"fblocked",        Tcl_FblockedObjCmd,     NULL,                   1},
00190     {"fconfigure",      Tcl_FconfigureObjCmd,   NULL,                   0},
00191     {"fcopy",           Tcl_FcopyObjCmd,        NULL,                   1},
00192     {"file",            Tcl_FileObjCmd,         NULL,                   0},
00193     {"fileevent",       Tcl_FileEventObjCmd,    NULL,                   1},
00194     {"flush",           Tcl_FlushObjCmd,        NULL,                   1},
00195     {"gets",            Tcl_GetsObjCmd,         NULL,                   1},
00196     {"glob",            Tcl_GlobObjCmd,         NULL,                   0},
00197     {"load",            Tcl_LoadObjCmd,         NULL,                   0},
00198     {"open",            Tcl_OpenObjCmd,         NULL,                   0},
00199     {"pid",             Tcl_PidObjCmd,          NULL,                   1},
00200     {"puts",            Tcl_PutsObjCmd,         NULL,                   1},
00201     {"pwd",             Tcl_PwdObjCmd,          NULL,                   0},
00202     {"read",            Tcl_ReadObjCmd,         NULL,                   1},
00203     {"seek",            Tcl_SeekObjCmd,         NULL,                   1},
00204     {"socket",          Tcl_SocketObjCmd,       NULL,                   0},
00205     {"source",          Tcl_SourceObjCmd,       NULL,                   0},
00206     {"tell",            Tcl_TellObjCmd,         NULL,                   1},
00207     {"time",            Tcl_TimeObjCmd,         NULL,                   1},
00208     {"unload",          Tcl_UnloadObjCmd,       NULL,                   0},
00209     {"update",          Tcl_UpdateObjCmd,       NULL,                   1},
00210     {"vwait",           Tcl_VwaitObjCmd,        NULL,                   1},
00211     {NULL,              NULL,                   NULL,                   0}
00212 };
00213 
00214 /*
00215  * Math functions. All are safe.
00216  */
00217 
00218 typedef struct {
00219     const char *name;           /* Name of the function. The full name is
00220                                  * "::tcl::mathfunc::<name>".  */
00221     Tcl_ObjCmdProc *objCmdProc; /* Function that evaluates the function */
00222     ClientData clientData;      /* Client data for the function */
00223 } BuiltinFuncDef;
00224 static const BuiltinFuncDef BuiltinFuncTable[] = {
00225     { "abs",    ExprAbsFunc,    NULL                    },
00226     { "acos",   ExprUnaryFunc,  (ClientData) acos       },
00227     { "asin",   ExprUnaryFunc,  (ClientData) asin       },
00228     { "atan",   ExprUnaryFunc,  (ClientData) atan       },
00229     { "atan2",  ExprBinaryFunc, (ClientData) atan2      },
00230     { "bool",   ExprBoolFunc,   NULL                    },
00231     { "ceil",   ExprCeilFunc,   NULL                    },
00232     { "cos",    ExprUnaryFunc,  (ClientData) cos        },
00233     { "cosh",   ExprUnaryFunc,  (ClientData) cosh       },
00234     { "double", ExprDoubleFunc, NULL                    },
00235     { "entier", ExprEntierFunc, NULL                    },
00236     { "exp",    ExprUnaryFunc,  (ClientData) exp        },
00237     { "floor",  ExprFloorFunc,  NULL                    },
00238     { "fmod",   ExprBinaryFunc, (ClientData) fmod       },
00239     { "hypot",  ExprBinaryFunc, (ClientData) hypot      },
00240     { "int",    ExprIntFunc,    NULL                    },
00241     { "isqrt",  ExprIsqrtFunc,  NULL                    },
00242     { "log",    ExprUnaryFunc,  (ClientData) log        },
00243     { "log10",  ExprUnaryFunc,  (ClientData) log10      },
00244     { "pow",    ExprBinaryFunc, (ClientData) pow        },
00245     { "rand",   ExprRandFunc,   NULL                    },
00246     { "round",  ExprRoundFunc,  NULL                    },
00247     { "sin",    ExprUnaryFunc,  (ClientData) sin        },
00248     { "sinh",   ExprUnaryFunc,  (ClientData) sinh       },
00249     { "sqrt",   ExprSqrtFunc,   NULL                    },
00250     { "srand",  ExprSrandFunc,  NULL                    },
00251     { "tan",    ExprUnaryFunc,  (ClientData) tan        },
00252     { "tanh",   ExprUnaryFunc,  (ClientData) tanh       },
00253     { "wide",   ExprWideFunc,   NULL                    },
00254     { NULL, NULL, NULL }
00255 };
00256 
00257 /*
00258  * TIP#174's math operators. All are safe.
00259  */
00260 
00261 typedef struct {
00262     const char *name;           /* Name of object-based command. */
00263     Tcl_ObjCmdProc *objProc;    /* Object-based function for command. */
00264     CompileProc *compileProc;   /* Function called to compile command. */
00265     union {
00266         int numArgs;
00267         int identity;
00268     } i;
00269     const char *expected;       /* For error message, what argument(s)
00270                                  * were expected. */
00271 } OpCmdInfo;
00272 static const OpCmdInfo mathOpCmds[] = {
00273     { "~",      TclSingleOpCmd,         TclCompileInvertOpCmd,
00274                 /* numArgs */ {1},      "integer"},
00275     { "!",      TclSingleOpCmd,         TclCompileNotOpCmd,
00276                 /* numArgs */ {1},      "boolean"},
00277     { "+",      TclVariadicOpCmd,       TclCompileAddOpCmd,
00278                 /* identity */ {0},     NULL},
00279     { "*",      TclVariadicOpCmd,       TclCompileMulOpCmd,
00280                 /* identity */ {1},     NULL},
00281     { "&",      TclVariadicOpCmd,       TclCompileAndOpCmd,
00282                 /* identity */ {-1},    NULL},
00283     { "|",      TclVariadicOpCmd,       TclCompileOrOpCmd,
00284                 /* identity */ {0},     NULL},
00285     { "^",      TclVariadicOpCmd,       TclCompileXorOpCmd,
00286                 /* identity */ {0},     NULL},
00287     { "**",     TclVariadicOpCmd,       TclCompilePowOpCmd,
00288                 /* identity */ {1},     NULL},
00289     { "<<",     TclSingleOpCmd,         TclCompileLshiftOpCmd,
00290                 /* numArgs */ {2},      "integer shift"},
00291     { ">>",     TclSingleOpCmd,         TclCompileRshiftOpCmd,
00292                 /* numArgs */ {2},      "integer shift"},
00293     { "%",      TclSingleOpCmd,         TclCompileModOpCmd,
00294                 /* numArgs */ {2},      "integer integer"},
00295     { "!=",     TclSingleOpCmd,         TclCompileNeqOpCmd,
00296                 /* numArgs */ {2},      "value value"},
00297     { "ne",     TclSingleOpCmd,         TclCompileStrneqOpCmd,
00298                 /* numArgs */ {2},      "value value"},
00299     { "in",     TclSingleOpCmd,         TclCompileInOpCmd,
00300                 /* numArgs */ {2},      "value list"},
00301     { "ni",     TclSingleOpCmd,         TclCompileNiOpCmd,
00302                 /* numArgs */ {2},      "value list"},
00303     { "-",      TclNoIdentOpCmd,        TclCompileMinusOpCmd,
00304                 /* unused */ {0},       "value ?value ...?"},
00305     { "/",      TclNoIdentOpCmd,        TclCompileDivOpCmd,
00306                 /* unused */ {0},       "value ?value ...?"},
00307     { "<",      TclSortingOpCmd,        TclCompileLessOpCmd,
00308                 /* unused */ {0},       NULL},
00309     { "<=",     TclSortingOpCmd,        TclCompileLeqOpCmd,
00310                 /* unused */ {0},       NULL},
00311     { ">",      TclSortingOpCmd,        TclCompileGreaterOpCmd,
00312                 /* unused */ {0},       NULL},
00313     { ">=",     TclSortingOpCmd,        TclCompileGeqOpCmd,
00314                 /* unused */ {0},       NULL},
00315     { "==",     TclSortingOpCmd,        TclCompileEqOpCmd,
00316                 /* unused */ {0},       NULL},
00317     { "eq",     TclSortingOpCmd,        TclCompileStreqOpCmd,
00318                 /* unused */ {0},       NULL},
00319     { NULL,     NULL,                   NULL,
00320                 {0},                    NULL}
00321 };
00322 
00323 /*
00324  * Macros for stack checks. The goal of these macros is to allow the size of
00325  * the stack to be checked (so preventing overflow) in a *cheap* way. Note
00326  * that the check needs to be (amortized) cheap since it is on the critical
00327  * path for recursion.
00328  */
00329 
00330 #if defined(TCL_NO_STACK_CHECK)
00331 /*
00332  * Stack check disabled: make them noops.
00333  */
00334 
00335 #   define CheckCStack(interp, localIntPtr)     1
00336 #   define GetCStackParams(iPtr)                /* do nothing */
00337 #elif defined(TCL_CROSS_COMPILE)
00338 
00339 /*
00340  * This variable is static and only set *once*, during library initialization.
00341  * It therefore needs no thread guards.
00342  */
00343 
00344 static int stackGrowsDown = 1;
00345 #   define GetCStackParams(iPtr) \
00346     stackGrowsDown = TclpGetCStackParams(&((iPtr)->stackBound))
00347 #   define CheckCStack(iPtr, localIntPtr) \
00348     (stackGrowsDown \
00349             ? ((localIntPtr) > (iPtr)->stackBound) \
00350             : ((localIntPtr) < (iPtr)->stackBound) \
00351     )
00352 #else /* !TCL_NO_STACK_CHECK && !TCL_CROSS_COMPILE */
00353 #   define GetCStackParams(iPtr) \
00354     TclpGetCStackParams(&((iPtr)->stackBound))
00355 #   ifdef TCL_STACK_GROWS_UP
00356 #       define CheckCStack(iPtr, localIntPtr) \
00357            (!(iPtr)->stackBound || (localIntPtr) < (iPtr)->stackBound)
00358 #    else /* TCL_STACK_GROWS_UP */
00359 #       define CheckCStack(iPtr, localIntPtr) \
00360            ((localIntPtr) > (iPtr)->stackBound)
00361 #    endif /* TCL_STACK_GROWS_UP */
00362 #endif /* TCL_NO_STACK_CHECK/TCL_CROSS_COMPILE */
00363 
00364 /*
00365  *----------------------------------------------------------------------
00366  *
00367  * Tcl_CreateInterp --
00368  *
00369  *      Create a new TCL command interpreter.
00370  *
00371  * Results:
00372  *      The return value is a token for the interpreter, which may be used in
00373  *      calls to functions like Tcl_CreateCmd, Tcl_Eval, or Tcl_DeleteInterp.
00374  *
00375  * Side effects:
00376  *      The command interpreter is initialized with the built-in commands and
00377  *      with the variables documented in tclvars(n).
00378  *
00379  *----------------------------------------------------------------------
00380  */
00381 
00382 Tcl_Interp *
00383 Tcl_CreateInterp(void)
00384 {
00385     Interp *iPtr;
00386     Tcl_Interp *interp;
00387     Command *cmdPtr;
00388     const BuiltinFuncDef *builtinFuncPtr;
00389     const OpCmdInfo *opcmdInfoPtr;
00390     const CmdInfo *cmdInfoPtr;
00391     Tcl_Namespace *mathfuncNSPtr, *mathopNSPtr;
00392     union {
00393         char c[sizeof(short)];
00394         short s;
00395     } order;
00396 #ifdef TCL_COMPILE_STATS
00397     ByteCodeStats *statsPtr;
00398 #endif /* TCL_COMPILE_STATS */
00399     char mathFuncName[32];
00400     CallFrame *framePtr;
00401     int result;
00402 
00403     TclInitSubsystems();
00404 
00405     /*
00406      * Panic if someone updated the CallFrame structure without also updating
00407      * the Tcl_CallFrame structure (or vice versa).
00408      */
00409 
00410     if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
00411         /*NOTREACHED*/
00412         Tcl_Panic("Tcl_CallFrame and CallFrame are not the same size");
00413     }
00414 
00415     /*
00416      * Initialize support for namespaces and create the global namespace
00417      * (whose name is ""; an alias is "::"). This also initializes the Tcl
00418      * object type table and other object management code.
00419      */
00420 
00421     iPtr = (Interp *) ckalloc(sizeof(Interp));
00422     interp = (Tcl_Interp *) iPtr;
00423 
00424     iPtr->result = iPtr->resultSpace;
00425     iPtr->freeProc = NULL;
00426     iPtr->errorLine = 0;
00427     iPtr->objResultPtr = Tcl_NewObj();
00428     Tcl_IncrRefCount(iPtr->objResultPtr);
00429     iPtr->handle = TclHandleCreate(iPtr);
00430     iPtr->globalNsPtr = NULL;
00431     iPtr->hiddenCmdTablePtr = NULL;
00432     iPtr->interpInfo = NULL;
00433 
00434     iPtr->numLevels = 0;
00435     iPtr->maxNestingDepth = MAX_NESTING_DEPTH;
00436     iPtr->framePtr = NULL;      /* Initialise as soon as :: is available */
00437     iPtr->varFramePtr = NULL;   /* Initialise as soon as :: is available */
00438 
00439     /*
00440      * TIP #280 - Initialize the arrays used to extend the ByteCode and
00441      * Proc structures.
00442      */
00443 
00444     iPtr->cmdFramePtr = NULL;
00445     iPtr->linePBodyPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
00446     iPtr->lineBCPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
00447     Tcl_InitHashTable(iPtr->linePBodyPtr, TCL_ONE_WORD_KEYS);
00448     Tcl_InitHashTable(iPtr->lineBCPtr, TCL_ONE_WORD_KEYS);
00449 
00450     iPtr->activeVarTracePtr = NULL;
00451 
00452     iPtr->returnOpts = NULL;
00453     iPtr->errorInfo = NULL;
00454     TclNewLiteralStringObj(iPtr->eiVar, "::errorInfo");
00455     Tcl_IncrRefCount(iPtr->eiVar);
00456     iPtr->errorCode = NULL;
00457     TclNewLiteralStringObj(iPtr->ecVar, "::errorCode");
00458     Tcl_IncrRefCount(iPtr->ecVar);
00459     iPtr->returnLevel = 1;
00460     iPtr->returnCode = TCL_OK;
00461 
00462     iPtr->rootFramePtr = NULL;  /* Initialise as soon as :: is available */
00463     iPtr->lookupNsPtr = NULL;
00464 
00465     iPtr->appendResult = NULL;
00466     iPtr->appendAvl = 0;
00467     iPtr->appendUsed = 0;
00468 
00469     Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
00470     iPtr->packageUnknown = NULL;
00471 
00472     /* TIP #268 */
00473     if (getenv("TCL_PKG_PREFER_LATEST") == NULL) {
00474         iPtr->packagePrefer = PKG_PREFER_STABLE;
00475     } else {
00476         iPtr->packagePrefer = PKG_PREFER_LATEST;
00477     }
00478 
00479     iPtr->cmdCount = 0;
00480     TclInitLiteralTable(&(iPtr->literalTable));
00481     iPtr->compileEpoch = 0;
00482     iPtr->compiledProcPtr = NULL;
00483     iPtr->resolverPtr = NULL;
00484     iPtr->evalFlags = 0;
00485     iPtr->scriptFile = NULL;
00486     iPtr->flags = 0;
00487     iPtr->tracePtr = NULL;
00488     iPtr->tracesForbiddingInline = 0;
00489     iPtr->activeCmdTracePtr = NULL;
00490     iPtr->activeInterpTracePtr = NULL;
00491     iPtr->assocData = NULL;
00492     iPtr->execEnvPtr = NULL;    /* Set after namespaces initialized. */
00493     iPtr->emptyObjPtr = Tcl_NewObj();
00494                                 /* Another empty object. */
00495     Tcl_IncrRefCount(iPtr->emptyObjPtr);
00496     iPtr->resultSpace[0] = 0;
00497     iPtr->threadId = Tcl_GetCurrentThread();
00498 
00499     /*
00500      * Initialise the tables for variable traces and searches *before*
00501      * creating the global ns - so that the trace on errorInfo can be
00502      * recorded.
00503      */
00504 
00505     Tcl_InitHashTable(&iPtr->varTraces, TCL_ONE_WORD_KEYS);
00506     Tcl_InitHashTable(&iPtr->varSearches, TCL_ONE_WORD_KEYS);
00507 
00508     iPtr->globalNsPtr = NULL;   /* Force creation of global ns below. */
00509     iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
00510             NULL, NULL);
00511     if (iPtr->globalNsPtr == NULL) {
00512         Tcl_Panic("Tcl_CreateInterp: can't create global namespace");
00513     }
00514 
00515     /*
00516      * Initialise the rootCallframe. It cannot be allocated on the stack, as
00517      * it has to be in place before TclCreateExecEnv tries to use a variable.
00518      */
00519 
00520     /* This is needed to satisfy GCC 3.3's strict aliasing rules */
00521     framePtr = (CallFrame *) ckalloc(sizeof(CallFrame));
00522     result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
00523             (Tcl_Namespace *) iPtr->globalNsPtr, /*isProcCallFrame*/ 0);
00524     if (result != TCL_OK) {
00525         Tcl_Panic("Tcl_CreateInterp: failed to push the root stack frame");
00526     }
00527     framePtr->objc = 0;
00528 
00529     iPtr->framePtr = framePtr;
00530     iPtr->varFramePtr = framePtr;
00531     iPtr->rootFramePtr = framePtr;
00532 
00533     /*
00534      * Initialize support for code compilation and execution. We call
00535      * TclCreateExecEnv after initializing namespaces since it tries to
00536      * reference a Tcl variable (it links to the Tcl "tcl_traceExec"
00537      * variable).
00538      */
00539 
00540     iPtr->execEnvPtr = TclCreateExecEnv(interp);
00541 
00542     /*
00543      * TIP #219, Tcl Channel Reflection API support.
00544      */
00545 
00546     iPtr->chanMsg = NULL;
00547 
00548     /*
00549      * Initialize the compilation and execution statistics kept for this
00550      * interpreter.
00551      */
00552 
00553 #ifdef TCL_COMPILE_STATS
00554     statsPtr = &(iPtr->stats);
00555     statsPtr->numExecutions = 0;
00556     statsPtr->numCompilations = 0;
00557     statsPtr->numByteCodesFreed = 0;
00558     (void) memset(statsPtr->instructionCount, 0,
00559             sizeof(statsPtr->instructionCount));
00560 
00561     statsPtr->totalSrcBytes = 0.0;
00562     statsPtr->totalByteCodeBytes = 0.0;
00563     statsPtr->currentSrcBytes = 0.0;
00564     statsPtr->currentByteCodeBytes = 0.0;
00565     (void) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
00566     (void) memset(statsPtr->byteCodeCount, 0, sizeof(statsPtr->byteCodeCount));
00567     (void) memset(statsPtr->lifetimeCount, 0, sizeof(statsPtr->lifetimeCount));
00568 
00569     statsPtr->currentInstBytes = 0.0;
00570     statsPtr->currentLitBytes = 0.0;
00571     statsPtr->currentExceptBytes = 0.0;
00572     statsPtr->currentAuxBytes = 0.0;
00573     statsPtr->currentCmdMapBytes = 0.0;
00574 
00575     statsPtr->numLiteralsCreated = 0;
00576     statsPtr->totalLitStringBytes = 0.0;
00577     statsPtr->currentLitStringBytes = 0.0;
00578     (void) memset(statsPtr->literalCount, 0, sizeof(statsPtr->literalCount));
00579 #endif /* TCL_COMPILE_STATS */
00580 
00581     /*
00582      * Initialise the stub table pointer.
00583      */
00584 
00585     iPtr->stubTable = &tclStubs;
00586 
00587     /*
00588      * Initialize the ensemble error message rewriting support.
00589      */
00590 
00591     iPtr->ensembleRewrite.sourceObjs = NULL;
00592     iPtr->ensembleRewrite.numRemovedObjs = 0;
00593     iPtr->ensembleRewrite.numInsertedObjs = 0;
00594 
00595     /*
00596      * TIP#143: Initialise the resource limit support.
00597      */
00598 
00599     TclInitLimitSupport(interp);
00600 
00601     /*
00602      * Initialise the thread-specific data ekeko.
00603      */
00604 
00605 #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
00606     iPtr->allocCache = TclpGetAllocCache();
00607 #else
00608     iPtr->allocCache = NULL;
00609 #endif
00610     iPtr->pendingObjDataPtr = NULL;
00611     iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
00612 
00613     /*
00614      * Insure that the stack checking mechanism for this interp is
00615      * initialized.
00616      */
00617 
00618     GetCStackParams(iPtr);
00619 
00620     /*
00621      * Create the core commands. Do it here, rather than calling
00622      * Tcl_CreateCommand, because it's faster (there's no need to check for a
00623      * pre-existing command by the same name). If a command has a Tcl_CmdProc
00624      * but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
00625      * TclInvokeStringCommand. This is an object-based wrapper function that
00626      * extracts strings, calls the string function, and creates an object for
00627      * the result. Similarly, if a command has a Tcl_ObjCmdProc but no
00628      * Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
00629      */
00630 
00631     for (cmdInfoPtr = builtInCmds;  cmdInfoPtr->name != NULL; cmdInfoPtr++) {
00632         int isNew;
00633         Tcl_HashEntry *hPtr;
00634 
00635         if ((cmdInfoPtr->objProc == NULL)
00636                 && (cmdInfoPtr->compileProc == NULL)) {
00637             Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc");
00638         }
00639 
00640         hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
00641                 cmdInfoPtr->name, &isNew);
00642         if (isNew) {
00643             cmdPtr = (Command *) ckalloc(sizeof(Command));
00644             cmdPtr->hPtr = hPtr;
00645             cmdPtr->nsPtr = iPtr->globalNsPtr;
00646             cmdPtr->refCount = 1;
00647             cmdPtr->cmdEpoch = 0;
00648             cmdPtr->compileProc = cmdInfoPtr->compileProc;
00649             cmdPtr->proc = TclInvokeObjectCommand;
00650             cmdPtr->clientData = cmdPtr;
00651             cmdPtr->objProc = cmdInfoPtr->objProc;
00652             cmdPtr->objClientData = NULL;
00653             cmdPtr->deleteProc = NULL;
00654             cmdPtr->deleteData = NULL;
00655             cmdPtr->flags = 0;
00656             cmdPtr->importRefPtr = NULL;
00657             cmdPtr->tracePtr = NULL;
00658             Tcl_SetHashValue(hPtr, cmdPtr);
00659         }
00660     }
00661 
00662     /*
00663      * Create the "chan", "dict", "info" and "string" ensembles. Note that all
00664      * these commands (and their subcommands that are not present in the
00665      * global namespace) are wholly safe.
00666      */
00667 
00668     TclInitChanCmd(interp);
00669     TclInitDictCmd(interp);
00670     TclInitInfoCmd(interp);
00671     TclInitStringCmd(interp);
00672 
00673     /*
00674      * Register "clock" subcommands. These *do* go through
00675      * Tcl_CreateObjCommand, since they aren't in the global namespace and
00676      * involve ensembles.
00677      */
00678 
00679     TclClockInit(interp);
00680 
00681     /*
00682      * Register the built-in functions. This is empty now that they are
00683      * implemented as commands in the ::tcl::mathfunc namespace.
00684      */
00685 
00686     /*
00687      * Register the default [interp bgerror] handler.
00688      */
00689 
00690     Tcl_CreateObjCommand(interp, "::tcl::Bgerror",
00691             TclDefaultBgErrorHandlerObjCmd, NULL, NULL);
00692 
00693     /*
00694      * Create an unsupported command for debugging bytecode.
00695      */
00696 
00697     Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble",
00698             Tcl_DisassembleObjCmd, NULL, NULL);
00699 
00700 #ifdef USE_DTRACE
00701     /*
00702      * Register the tcl::dtrace command.
00703      */
00704 
00705     Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL);
00706 #endif /* USE_DTRACE */
00707 
00708     /*
00709      * Register the builtin math functions.
00710      */
00711 
00712     mathfuncNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc", NULL,NULL);
00713     if (mathfuncNSPtr == NULL) {
00714         Tcl_Panic("Can't create math function namespace");
00715     }
00716     strcpy(mathFuncName, "::tcl::mathfunc::");
00717 #define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */
00718     for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL;
00719             builtinFuncPtr++) {
00720         strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
00721         Tcl_CreateObjCommand(interp, mathFuncName,
00722                 builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData, NULL);
00723         Tcl_Export(interp, mathfuncNSPtr, builtinFuncPtr->name, 0);
00724     }
00725 
00726     /*
00727      * Register the mathematical "operator" commands. [TIP #174]
00728      */
00729 
00730     mathopNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL);
00731 #define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */
00732     if (mathopNSPtr == NULL) {
00733         Tcl_Panic("can't create math operator namespace");
00734     }
00735     (void) Tcl_Export(interp, mathopNSPtr, "*", 1);
00736     strcpy(mathFuncName, "::tcl::mathop::");
00737     for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){
00738         TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)
00739                 ckalloc(sizeof(TclOpCmdClientData));
00740 
00741         occdPtr->op = opcmdInfoPtr->name;
00742         occdPtr->i.numArgs = opcmdInfoPtr->i.numArgs;
00743         occdPtr->expected = opcmdInfoPtr->expected;
00744         strcpy(mathFuncName + MATH_OP_PREFIX_LEN, opcmdInfoPtr->name);
00745         cmdPtr = (Command *) Tcl_CreateObjCommand(interp, mathFuncName,
00746                 opcmdInfoPtr->objProc, occdPtr, DeleteOpCmdClientData);
00747         if (cmdPtr == NULL) {
00748             Tcl_Panic("failed to create math operator %s",
00749                     opcmdInfoPtr->name);
00750         } else if (opcmdInfoPtr->compileProc != NULL) {
00751             cmdPtr->compileProc = opcmdInfoPtr->compileProc;
00752         }
00753     }
00754 
00755     /*
00756      * Do Multiple/Safe Interps Tcl init stuff
00757      */
00758 
00759     TclInterpInit(interp);
00760     TclSetupEnv(interp);
00761 
00762     /*
00763      * TIP #59: Make embedded configuration information available.
00764      */
00765 
00766     TclInitEmbeddedConfigurationInformation(interp);
00767 
00768     /*
00769      * Compute the byte order of this machine.
00770      */
00771 
00772     order.s = 1;
00773     Tcl_SetVar2(interp, "tcl_platform", "byteOrder",
00774             ((order.c[0] == 1) ? "littleEndian" : "bigEndian"),
00775             TCL_GLOBAL_ONLY);
00776 
00777     Tcl_SetVar2Ex(interp, "tcl_platform", "wordSize",
00778             Tcl_NewLongObj((long) sizeof(long)), TCL_GLOBAL_ONLY);
00779 
00780     /* TIP #291 */
00781     Tcl_SetVar2Ex(interp, "tcl_platform", "pointerSize",
00782             Tcl_NewLongObj((long) sizeof(void *)), TCL_GLOBAL_ONLY);
00783 
00784     /*
00785      * Set up other variables such as tcl_version and tcl_library
00786      */
00787 
00788     Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
00789     Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
00790     Tcl_TraceVar2(interp, "tcl_precision", NULL,
00791             TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
00792             TclPrecTraceProc, NULL);
00793     TclpSetVariables(interp);
00794 
00795 #ifdef TCL_THREADS
00796     /*
00797      * The existence of the "threaded" element of the tcl_platform array
00798      * indicates that this particular Tcl shell has been compiled with threads
00799      * turned on. Using "info exists tcl_platform(threaded)" a Tcl script can
00800      * introspect on the interpreter level of thread safety.
00801      */
00802 
00803     Tcl_SetVar2(interp, "tcl_platform", "threaded", "1", TCL_GLOBAL_ONLY);
00804 #endif
00805 
00806     /*
00807      * Register Tcl's version number.
00808      * TIP #268: Full patchlevel instead of just major.minor
00809      */
00810 
00811     Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs);
00812 
00813 #ifdef Tcl_InitStubs
00814 #undef Tcl_InitStubs
00815 #endif
00816     Tcl_InitStubs(interp, TCL_VERSION, 1);
00817 
00818     if (TclTommath_Init(interp) != TCL_OK) {
00819         Tcl_Panic(Tcl_GetString(Tcl_GetObjResult(interp)));
00820     }
00821 
00822     return interp;
00823 }
00824 
00825 static void
00826 DeleteOpCmdClientData(
00827     ClientData clientData)
00828 {
00829     TclOpCmdClientData *occdPtr = clientData;
00830 
00831     ckfree((char *) occdPtr);
00832 }
00833 
00834 /*
00835  *----------------------------------------------------------------------
00836  *
00837  * TclHideUnsafeCommands --
00838  *
00839  *      Hides base commands that are not marked as safe from this interpreter.
00840  *
00841  * Results:
00842  *      TCL_OK if it succeeds, TCL_ERROR else.
00843  *
00844  * Side effects:
00845  *      Hides functionality in an interpreter.
00846  *
00847  *----------------------------------------------------------------------
00848  */
00849 
00850 int
00851 TclHideUnsafeCommands(
00852     Tcl_Interp *interp)         /* Hide commands in this interpreter. */
00853 {
00854     register const CmdInfo *cmdInfoPtr;
00855 
00856     if (interp == NULL) {
00857         return TCL_ERROR;
00858     }
00859     for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
00860         if (!cmdInfoPtr->isSafe) {
00861             Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
00862         }
00863     }
00864     return TCL_OK;
00865 }
00866 
00867 /*
00868  *--------------------------------------------------------------
00869  *
00870  * Tcl_CallWhenDeleted --
00871  *
00872  *      Arrange for a function to be called before a given interpreter is
00873  *      deleted. The function is called as soon as Tcl_DeleteInterp is called;
00874  *      if Tcl_CallWhenDeleted is called on an interpreter that has already
00875  *      been deleted, the function will be called when the last Tcl_Release is
00876  *      done on the interpreter.
00877  *
00878  * Results:
00879  *      None.
00880  *
00881  * Side effects:
00882  *      When Tcl_DeleteInterp is invoked to delete interp, proc will be
00883  *      invoked. See the manual entry for details.
00884  *
00885  *--------------------------------------------------------------
00886  */
00887 
00888 void
00889 Tcl_CallWhenDeleted(
00890     Tcl_Interp *interp,         /* Interpreter to watch. */
00891     Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about
00892                                  * to be deleted. */
00893     ClientData clientData)      /* One-word value to pass to proc. */
00894 {
00895     Interp *iPtr = (Interp *) interp;
00896     static Tcl_ThreadDataKey assocDataCounterKey;
00897     int *assocDataCounterPtr =
00898             Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int));
00899     int isNew;
00900     char buffer[32 + TCL_INTEGER_SPACE];
00901     AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));
00902     Tcl_HashEntry *hPtr;
00903 
00904     sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr);
00905     (*assocDataCounterPtr)++;
00906 
00907     if (iPtr->assocData == NULL) {
00908         iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
00909         Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
00910     }
00911     hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &isNew);
00912     dPtr->proc = proc;
00913     dPtr->clientData = clientData;
00914     Tcl_SetHashValue(hPtr, dPtr);
00915 }
00916 
00917 /*
00918  *--------------------------------------------------------------
00919  *
00920  * Tcl_DontCallWhenDeleted --
00921  *
00922  *      Cancel the arrangement for a function to be called when a given
00923  *      interpreter is deleted.
00924  *
00925  * Results:
00926  *      None.
00927  *
00928  * Side effects:
00929  *      If proc and clientData were previously registered as a callback via
00930  *      Tcl_CallWhenDeleted, they are unregistered. If they weren't previously
00931  *      registered then nothing happens.
00932  *
00933  *--------------------------------------------------------------
00934  */
00935 
00936 void
00937 Tcl_DontCallWhenDeleted(
00938     Tcl_Interp *interp,         /* Interpreter to watch. */
00939     Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about
00940                                  * to be deleted. */
00941     ClientData clientData)      /* One-word value to pass to proc. */
00942 {
00943     Interp *iPtr = (Interp *) interp;
00944     Tcl_HashTable *hTablePtr;
00945     Tcl_HashSearch hSearch;
00946     Tcl_HashEntry *hPtr;
00947     AssocData *dPtr;
00948 
00949     hTablePtr = iPtr->assocData;
00950     if (hTablePtr == NULL) {
00951         return;
00952     }
00953     for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
00954             hPtr = Tcl_NextHashEntry(&hSearch)) {
00955         dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
00956         if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
00957             ckfree((char *) dPtr);
00958             Tcl_DeleteHashEntry(hPtr);
00959             return;
00960         }
00961     }
00962 }
00963 
00964 /*
00965  *----------------------------------------------------------------------
00966  *
00967  * Tcl_SetAssocData --
00968  *
00969  *      Creates a named association between user-specified data, a delete
00970  *      function and this interpreter. If the association already exists the
00971  *      data is overwritten with the new data. The delete function will be
00972  *      invoked when the interpreter is deleted.
00973  *
00974  * Results:
00975  *      None.
00976  *
00977  * Side effects:
00978  *      Sets the associated data, creates the association if needed.
00979  *
00980  *----------------------------------------------------------------------
00981  */
00982 
00983 void
00984 Tcl_SetAssocData(
00985     Tcl_Interp *interp,         /* Interpreter to associate with. */
00986     const char *name,           /* Name for association. */
00987     Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to
00988                                  * be deleted. */
00989     ClientData clientData)      /* One-word value to pass to proc. */
00990 {
00991     Interp *iPtr = (Interp *) interp;
00992     AssocData *dPtr;
00993     Tcl_HashEntry *hPtr;
00994     int isNew;
00995 
00996     if (iPtr->assocData == NULL) {
00997         iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
00998         Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
00999     }
01000     hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &isNew);
01001     if (isNew == 0) {
01002         dPtr = Tcl_GetHashValue(hPtr);
01003     } else {
01004         dPtr = (AssocData *) ckalloc(sizeof(AssocData));
01005     }
01006     dPtr->proc = proc;
01007     dPtr->clientData = clientData;
01008 
01009     Tcl_SetHashValue(hPtr, dPtr);
01010 }
01011 
01012 /*
01013  *----------------------------------------------------------------------
01014  *
01015  * Tcl_DeleteAssocData --
01016  *
01017  *      Deletes a named association of user-specified data with the specified
01018  *      interpreter.
01019  *
01020  * Results:
01021  *      None.
01022  *
01023  * Side effects:
01024  *      Deletes the association.
01025  *
01026  *----------------------------------------------------------------------
01027  */
01028 
01029 void
01030 Tcl_DeleteAssocData(
01031     Tcl_Interp *interp,         /* Interpreter to associate with. */
01032     const char *name)           /* Name of association. */
01033 {
01034     Interp *iPtr = (Interp *) interp;
01035     AssocData *dPtr;
01036     Tcl_HashEntry *hPtr;
01037 
01038     if (iPtr->assocData == NULL) {
01039         return;
01040     }
01041     hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
01042     if (hPtr == NULL) {
01043         return;
01044     }
01045     dPtr = Tcl_GetHashValue(hPtr);
01046     if (dPtr->proc != NULL) {
01047         dPtr->proc(dPtr->clientData, interp);
01048     }
01049     ckfree((char *) dPtr);
01050     Tcl_DeleteHashEntry(hPtr);
01051 }
01052 
01053 /*
01054  *----------------------------------------------------------------------
01055  *
01056  * Tcl_GetAssocData --
01057  *
01058  *      Returns the client data associated with this name in the specified
01059  *      interpreter.
01060  *
01061  * Results:
01062  *      The client data in the AssocData record denoted by the named
01063  *      association, or NULL.
01064  *
01065  * Side effects:
01066  *      None.
01067  *
01068  *----------------------------------------------------------------------
01069  */
01070 
01071 ClientData
01072 Tcl_GetAssocData(
01073     Tcl_Interp *interp,         /* Interpreter associated with. */
01074     const char *name,           /* Name of association. */
01075     Tcl_InterpDeleteProc **procPtr)
01076                                 /* Pointer to place to store address of
01077                                  * current deletion callback. */
01078 {
01079     Interp *iPtr = (Interp *) interp;
01080     AssocData *dPtr;
01081     Tcl_HashEntry *hPtr;
01082 
01083     if (iPtr->assocData == NULL) {
01084         return NULL;
01085     }
01086     hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
01087     if (hPtr == NULL) {
01088         return NULL;
01089     }
01090     dPtr = Tcl_GetHashValue(hPtr);
01091     if (procPtr != NULL) {
01092         *procPtr = dPtr->proc;
01093     }
01094     return dPtr->clientData;
01095 }
01096 
01097 /*
01098  *----------------------------------------------------------------------
01099  *
01100  * Tcl_InterpDeleted --
01101  *
01102  *      Returns nonzero if the interpreter has been deleted with a call to
01103  *      Tcl_DeleteInterp.
01104  *
01105  * Results:
01106  *      Nonzero if the interpreter is deleted, zero otherwise.
01107  *
01108  * Side effects:
01109  *      None.
01110  *
01111  *----------------------------------------------------------------------
01112  */
01113 
01114 int
01115 Tcl_InterpDeleted(
01116     Tcl_Interp *interp)
01117 {
01118     return (((Interp *) interp)->flags & DELETED) ? 1 : 0;
01119 }
01120 
01121 /*
01122  *----------------------------------------------------------------------
01123  *
01124  * Tcl_DeleteInterp --
01125  *
01126  *      Ensures that the interpreter will be deleted eventually. If there are
01127  *      no Tcl_Preserve calls in effect for this interpreter, it is deleted
01128  *      immediately, otherwise the interpreter is deleted when the last
01129  *      Tcl_Preserve is matched by a call to Tcl_Release. In either case, the
01130  *      function runs the currently registered deletion callbacks.
01131  *
01132  * Results:
01133  *      None.
01134  *
01135  * Side effects:
01136  *      The interpreter is marked as deleted. The caller may still use it
01137  *      safely if there are calls to Tcl_Preserve in effect for the
01138  *      interpreter, but further calls to Tcl_Eval etc in this interpreter
01139  *      will fail.
01140  *
01141  *----------------------------------------------------------------------
01142  */
01143 
01144 void
01145 Tcl_DeleteInterp(
01146     Tcl_Interp *interp)         /* Token for command interpreter (returned by
01147                                  * a previous call to Tcl_CreateInterp). */
01148 {
01149     Interp *iPtr = (Interp *) interp;
01150 
01151     /*
01152      * If the interpreter has already been marked deleted, just punt.
01153      */
01154 
01155     if (iPtr->flags & DELETED) {
01156         return;
01157     }
01158 
01159     /*
01160      * Mark the interpreter as deleted. No further evals will be allowed.
01161      * Increase the compileEpoch as a signal to compiled bytecodes.
01162      */
01163 
01164     iPtr->flags |= DELETED;
01165     iPtr->compileEpoch++;
01166 
01167     /*
01168      * Ensure that the interpreter is eventually deleted.
01169      */
01170 
01171     Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc);
01172 }
01173 
01174 /*
01175  *----------------------------------------------------------------------
01176  *
01177  * DeleteInterpProc --
01178  *
01179  *      Helper function to delete an interpreter. This function is called when
01180  *      the last call to Tcl_Preserve on this interpreter is matched by a call
01181  *      to Tcl_Release. The function cleans up all resources used in the
01182  *      interpreter and calls all currently registered interpreter deletion
01183  *      callbacks.
01184  *
01185  * Results:
01186  *      None.
01187  *
01188  * Side effects:
01189  *      Whatever the interpreter deletion callbacks do. Frees resources used
01190  *      by the interpreter.
01191  *
01192  *----------------------------------------------------------------------
01193  */
01194 
01195 static void
01196 DeleteInterpProc(
01197     Tcl_Interp *interp)         /* Interpreter to delete. */
01198 {
01199     Interp *iPtr = (Interp *) interp;
01200     Tcl_HashEntry *hPtr;
01201     Tcl_HashSearch search;
01202     Tcl_HashTable *hTablePtr;
01203     ResolverScheme *resPtr, *nextResPtr;
01204 
01205     /*
01206      * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
01207      */
01208 
01209     if (iPtr->numLevels > 0) {
01210         Tcl_Panic("DeleteInterpProc called with active evals");
01211     }
01212 
01213     /*
01214      * The interpreter should already be marked deleted; otherwise how did we
01215      * get here?
01216      */
01217 
01218     if (!(iPtr->flags & DELETED)) {
01219         Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted");
01220     }
01221 
01222     /*
01223      * TIP #219, Tcl Channel Reflection API. Discard a leftover state.
01224      */
01225 
01226     if (iPtr->chanMsg != NULL) {
01227         Tcl_DecrRefCount(iPtr->chanMsg);
01228         iPtr->chanMsg = NULL;
01229     }
01230 
01231     /*
01232      * Shut down all limit handler callback scripts that call back into this
01233      * interpreter. Then eliminate all limit handlers for this interpreter.
01234      */
01235 
01236     TclRemoveScriptLimitCallbacks(interp);
01237     TclLimitRemoveAllHandlers(interp);
01238 
01239     /*
01240      * Dismantle the namespace here, before we clear the assocData. If any
01241      * background errors occur here, they will be deleted below.
01242      *
01243      * Dismantle the namespace after freeing the iPtr->handle so that each
01244      * bytecode releases its literals without caring to update the literal
01245      * table, as it will be freed later in this function without further use.
01246      */
01247 
01248     TclCleanupLiteralTable(interp, &(iPtr->literalTable));
01249     TclHandleFree(iPtr->handle);
01250     TclTeardownNamespace(iPtr->globalNsPtr);
01251 
01252     /*
01253      * Delete all the hidden commands.
01254      */
01255 
01256     hTablePtr = iPtr->hiddenCmdTablePtr;
01257     if (hTablePtr != NULL) {
01258         /*
01259          * Non-pernicious deletion. The deletion callbacks will not be allowed
01260          * to create any new hidden or non-hidden commands.
01261          * Tcl_DeleteCommandFromToken() will remove the entry from the
01262          * hiddenCmdTablePtr.
01263          */
01264 
01265         hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
01266         for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
01267             Tcl_DeleteCommandFromToken(interp,
01268                     (Tcl_Command) Tcl_GetHashValue(hPtr));
01269         }
01270         Tcl_DeleteHashTable(hTablePtr);
01271         ckfree((char *) hTablePtr);
01272     }
01273 
01274     /*
01275      * Invoke deletion callbacks; note that a callback can create new
01276      * callbacks, so we iterate.
01277      */
01278 
01279     while (iPtr->assocData != NULL) {
01280         AssocData *dPtr;
01281 
01282         hTablePtr = iPtr->assocData;
01283         iPtr->assocData = NULL;
01284         for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
01285                 hPtr != NULL;
01286                 hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
01287             dPtr = Tcl_GetHashValue(hPtr);
01288             Tcl_DeleteHashEntry(hPtr);
01289             if (dPtr->proc != NULL) {
01290                 dPtr->proc(dPtr->clientData, interp);
01291             }
01292             ckfree((char *) dPtr);
01293         }
01294         Tcl_DeleteHashTable(hTablePtr);
01295         ckfree((char *) hTablePtr);
01296     }
01297 
01298     /*
01299      * Pop the root frame pointer and finish deleting the global
01300      * namespace. The order is important [Bug 1658572].
01301      */
01302 
01303     if (iPtr->framePtr != iPtr->rootFramePtr) {
01304         Tcl_Panic("DeleteInterpProc: popping rootCallFrame with other frames on top");
01305     }
01306     Tcl_PopCallFrame(interp);
01307     ckfree((char *) iPtr->rootFramePtr);
01308     iPtr->rootFramePtr = NULL;
01309     Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
01310 
01311     /*
01312      * Free up the result *after* deleting variables, since variable deletion
01313      * could have transferred ownership of the result string to Tcl.
01314      */
01315 
01316     Tcl_FreeResult(interp);
01317     interp->result = NULL;
01318     Tcl_DecrRefCount(iPtr->objResultPtr);
01319     iPtr->objResultPtr = NULL;
01320     Tcl_DecrRefCount(iPtr->ecVar);
01321     if (iPtr->errorCode) {
01322         Tcl_DecrRefCount(iPtr->errorCode);
01323         iPtr->errorCode = NULL;
01324     }
01325     Tcl_DecrRefCount(iPtr->eiVar);
01326     if (iPtr->errorInfo) {
01327         Tcl_DecrRefCount(iPtr->errorInfo);
01328         iPtr->errorInfo = NULL;
01329     }
01330     if (iPtr->returnOpts) {
01331         Tcl_DecrRefCount(iPtr->returnOpts);
01332     }
01333     if (iPtr->appendResult != NULL) {
01334         ckfree(iPtr->appendResult);
01335         iPtr->appendResult = NULL;
01336     }
01337     TclFreePackageInfo(iPtr);
01338     while (iPtr->tracePtr != NULL) {
01339         Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr);
01340     }
01341     if (iPtr->execEnvPtr != NULL) {
01342         TclDeleteExecEnv(iPtr->execEnvPtr);
01343     }
01344     Tcl_DecrRefCount(iPtr->emptyObjPtr);
01345     iPtr->emptyObjPtr = NULL;
01346 
01347     resPtr = iPtr->resolverPtr;
01348     while (resPtr) {
01349         nextResPtr = resPtr->nextPtr;
01350         ckfree(resPtr->name);
01351         ckfree((char *) resPtr);
01352         resPtr = nextResPtr;
01353     }
01354 
01355     /*
01356      * Free up literal objects created for scripts compiled by the
01357      * interpreter.
01358      */
01359 
01360     TclDeleteLiteralTable(interp, &(iPtr->literalTable));
01361 
01362     /*
01363      * TIP #280 - Release the arrays for ByteCode/Proc extension, and
01364      * contents.
01365      */
01366 
01367     {
01368         Tcl_HashEntry *hPtr;
01369         Tcl_HashSearch hSearch;
01370         int i;
01371 
01372         for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &hSearch);
01373                 hPtr != NULL;
01374                 hPtr = Tcl_NextHashEntry(&hSearch)) {
01375             CmdFrame *cfPtr = Tcl_GetHashValue(hPtr);
01376 
01377             if (cfPtr->type == TCL_LOCATION_SOURCE) {
01378                 Tcl_DecrRefCount(cfPtr->data.eval.path);
01379             }
01380             ckfree((char *) cfPtr->line);
01381             ckfree((char *) cfPtr);
01382             Tcl_DeleteHashEntry(hPtr);
01383         }
01384         Tcl_DeleteHashTable(iPtr->linePBodyPtr);
01385         ckfree((char *) iPtr->linePBodyPtr);
01386         iPtr->linePBodyPtr = NULL;
01387 
01388         /*
01389          * See also tclCompile.c, TclCleanupByteCode
01390          */
01391 
01392         for (hPtr = Tcl_FirstHashEntry(iPtr->lineBCPtr, &hSearch);
01393                 hPtr != NULL;
01394                 hPtr = Tcl_NextHashEntry(&hSearch)) {
01395             ExtCmdLoc *eclPtr = (ExtCmdLoc *) Tcl_GetHashValue(hPtr);
01396 
01397             if (eclPtr->type == TCL_LOCATION_SOURCE) {
01398                 Tcl_DecrRefCount(eclPtr->path);
01399             }
01400             for (i=0; i< eclPtr->nuloc; i++) {
01401                 ckfree((char *) eclPtr->loc[i].line);
01402             }
01403 
01404             if (eclPtr->loc != NULL) {
01405                 ckfree((char *) eclPtr->loc);
01406             }
01407 
01408             ckfree((char *) eclPtr);
01409             Tcl_DeleteHashEntry(hPtr);
01410         }
01411         Tcl_DeleteHashTable(iPtr->lineBCPtr);
01412         ckfree((char *) iPtr->lineBCPtr);
01413         iPtr->lineBCPtr = NULL;
01414     }
01415 
01416     Tcl_DeleteHashTable(&iPtr->varTraces);
01417     Tcl_DeleteHashTable(&iPtr->varSearches);
01418 
01419     ckfree((char *) iPtr);
01420 }
01421 
01422 /*
01423  *---------------------------------------------------------------------------
01424  *
01425  * Tcl_HideCommand --
01426  *
01427  *      Makes a command hidden so that it cannot be invoked from within an
01428  *      interpreter, only from within an ancestor.
01429  *
01430  * Results:
01431  *      A standard Tcl result; also leaves a message in the interp's result if
01432  *      an error occurs.
01433  *
01434  * Side effects:
01435  *      Removes a command from the command table and create an entry into the
01436  *      hidden command table under the specified token name.
01437  *
01438  *---------------------------------------------------------------------------
01439  */
01440 
01441 int
01442 Tcl_HideCommand(
01443     Tcl_Interp *interp,         /* Interpreter in which to hide command. */
01444     const char *cmdName,        /* Name of command to hide. */
01445     const char *hiddenCmdToken) /* Token name of the to-be-hidden command. */
01446 {
01447     Interp *iPtr = (Interp *) interp;
01448     Tcl_Command cmd;
01449     Command *cmdPtr;
01450     Tcl_HashTable *hiddenCmdTablePtr;
01451     Tcl_HashEntry *hPtr;
01452     int isNew;
01453 
01454     if (iPtr->flags & DELETED) {
01455         /*
01456          * The interpreter is being deleted. Do not create any new structures,
01457          * because it is not safe to modify the interpreter.
01458          */
01459 
01460         return TCL_ERROR;
01461     }
01462 
01463     /*
01464      * Disallow hiding of commands that are currently in a namespace or
01465      * renaming (as part of hiding) into a namespace (because the current
01466      * implementation with a single global table and the needed uniqueness of
01467      * names cause problems with namespaces).
01468      *
01469      * We don't need to check for "::" in cmdName because the real check is on
01470      * the nsPtr below.
01471      *
01472      * hiddenCmdToken is just a string which is not interpreted in any way. It
01473      * may contain :: but the string is not interpreted as a namespace
01474      * qualifier command name. Thus, hiding foo::bar to foo::bar and then
01475      * trying to expose or invoke ::foo::bar will NOT work; but if the
01476      * application always uses the same strings it will get consistent
01477      * behaviour.
01478      *
01479      * But as we currently limit ourselves to the global namespace only for
01480      * the source, in order to avoid potential confusion, lets prevent "::" in
01481      * the token too. - dl
01482      */
01483 
01484     if (strstr(hiddenCmdToken, "::") != NULL) {
01485         Tcl_AppendResult(interp,
01486                 "cannot use namespace qualifiers in hidden command"
01487                 " token (rename)", NULL);
01488         return TCL_ERROR;
01489     }
01490 
01491     /*
01492      * Find the command to hide. An error is returned if cmdName can't be
01493      * found. Look up the command only from the global namespace. Full path of
01494      * the command must be given if using namespaces.
01495      */
01496 
01497     cmd = Tcl_FindCommand(interp, cmdName, NULL,
01498             /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
01499     if (cmd == (Tcl_Command) NULL) {
01500         return TCL_ERROR;
01501     }
01502     cmdPtr = (Command *) cmd;
01503 
01504     /*
01505      * Check that the command is really in global namespace
01506      */
01507 
01508     if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
01509         Tcl_AppendResult(interp, "can only hide global namespace commands"
01510                 " (use rename then hide)", NULL);
01511         return TCL_ERROR;
01512     }
01513 
01514     /*
01515      * Initialize the hidden command table if necessary.
01516      */
01517 
01518     hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
01519     if (hiddenCmdTablePtr == NULL) {
01520         hiddenCmdTablePtr = (Tcl_HashTable *)
01521                 ckalloc((unsigned) sizeof(Tcl_HashTable));
01522         Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
01523         iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr;
01524     }
01525 
01526     /*
01527      * It is an error to move an exposed command to a hidden command with
01528      * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
01529      * exists.
01530      */
01531 
01532     hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew);
01533     if (!isNew) {
01534         Tcl_AppendResult(interp, "hidden command named \"", hiddenCmdToken,
01535                 "\" already exists", NULL);
01536         return TCL_ERROR;
01537     }
01538 
01539     /*
01540      * NB: This code is currently 'like' a rename to a specialy set apart name
01541      * table. Changes here and in TclRenameCommand must be kept in synch until
01542      * the common parts are actually factorized out.
01543      */
01544 
01545     /*
01546      * Remove the hash entry for the command from the interpreter command
01547      * table. This is like deleting the command, so bump its command epoch;
01548      * this invalidates any cached references that point to the command.
01549      */
01550 
01551     if (cmdPtr->hPtr != NULL) {
01552         Tcl_DeleteHashEntry(cmdPtr->hPtr);
01553         cmdPtr->hPtr = NULL;
01554         cmdPtr->cmdEpoch++;
01555     }
01556 
01557     /*
01558      * The list of command exported from the namespace might have changed.
01559      * However, we do not need to recompute this just yet; next time we need
01560      * the info will be soon enough.
01561      */
01562 
01563     TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
01564 
01565     /*
01566      * Now link the hash table entry with the command structure. We ensured
01567      * above that the nsPtr was right.
01568      */
01569 
01570     cmdPtr->hPtr = hPtr;
01571     Tcl_SetHashValue(hPtr, cmdPtr);
01572 
01573     /*
01574      * If the command being hidden has a compile function, increment the
01575      * interpreter's compileEpoch to invalidate its compiled code. This makes
01576      * sure that we don't later try to execute old code compiled with
01577      * command-specific (i.e., inline) bytecodes for the now-hidden command.
01578      * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose
01579      * compilation epoch doesn't match is recompiled.
01580      */
01581 
01582     if (cmdPtr->compileProc != NULL) {
01583         iPtr->compileEpoch++;
01584     }
01585     return TCL_OK;
01586 }
01587 
01588 /*
01589  *----------------------------------------------------------------------
01590  *
01591  * Tcl_ExposeCommand --
01592  *
01593  *      Makes a previously hidden command callable from inside the interpreter
01594  *      instead of only by its ancestors.
01595  *
01596  * Results:
01597  *      A standard Tcl result. If an error occurs, a message is left in the
01598  *      interp's result.
01599  *
01600  * Side effects:
01601  *      Moves commands from one hash table to another.
01602  *
01603  *----------------------------------------------------------------------
01604  */
01605 
01606 int
01607 Tcl_ExposeCommand(
01608     Tcl_Interp *interp,         /* Interpreter in which to make command
01609                                  * callable. */
01610     const char *hiddenCmdToken, /* Name of hidden command. */
01611     const char *cmdName)        /* Name of to-be-exposed command. */
01612 {
01613     Interp *iPtr = (Interp *) interp;
01614     Command *cmdPtr;
01615     Namespace *nsPtr;
01616     Tcl_HashEntry *hPtr;
01617     Tcl_HashTable *hiddenCmdTablePtr;
01618     int isNew;
01619 
01620     if (iPtr->flags & DELETED) {
01621         /*
01622          * The interpreter is being deleted. Do not create any new structures,
01623          * because it is not safe to modify the interpreter.
01624          */
01625 
01626         return TCL_ERROR;
01627     }
01628 
01629     /*
01630      * Check that we have a regular name for the command (that the user is not
01631      * trying to do an expose and a rename (to another namespace) at the same
01632      * time).
01633      */
01634 
01635     if (strstr(cmdName, "::") != NULL) {
01636         Tcl_AppendResult(interp, "cannot expose to a namespace "
01637                 "(use expose to toplevel, then rename)", NULL);
01638         return TCL_ERROR;
01639     }
01640 
01641     /*
01642      * Get the command from the hidden command table:
01643      */
01644 
01645     hPtr = NULL;
01646     hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
01647     if (hiddenCmdTablePtr != NULL) {
01648         hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
01649     }
01650     if (hPtr == NULL) {
01651         Tcl_AppendResult(interp, "unknown hidden command \"", hiddenCmdToken,
01652                 "\"", NULL);
01653         return TCL_ERROR;
01654     }
01655     cmdPtr = Tcl_GetHashValue(hPtr);
01656 
01657     /*
01658      * Check that we have a true global namespace command (enforced by
01659      * Tcl_HideCommand() but let's double check. (If it was not, we would not
01660      * really know how to handle it).
01661      */
01662 
01663     if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
01664         /*
01665          * This case is theoritically impossible, we might rather Tcl_Panic()
01666          * than 'nicely' erroring out ?
01667          */
01668 
01669         Tcl_AppendResult(interp,
01670                 "trying to expose a non global command name space command",
01671                 NULL);
01672         return TCL_ERROR;
01673     }
01674 
01675     /*
01676      * This is the global table.
01677      */
01678 
01679     nsPtr = cmdPtr->nsPtr;
01680 
01681     /*
01682      * It is an error to overwrite an existing exposed command as a result of
01683      * exposing a previously hidden command.
01684      */
01685 
01686     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew);
01687     if (!isNew) {
01688         Tcl_AppendResult(interp, "exposed command \"", cmdName,
01689                 "\" already exists", NULL);
01690         return TCL_ERROR;
01691     }
01692 
01693     /*
01694      * The list of command exported from the namespace might have changed.
01695      * However, we do not need to recompute this just yet; next time we need
01696      * the info will be soon enough.
01697      */
01698 
01699     TclInvalidateNsCmdLookup(nsPtr);
01700 
01701     /*
01702      * Remove the hash entry for the command from the interpreter hidden
01703      * command table.
01704      */
01705 
01706     if (cmdPtr->hPtr != NULL) {
01707         Tcl_DeleteHashEntry(cmdPtr->hPtr);
01708         cmdPtr->hPtr = NULL;
01709     }
01710 
01711     /*
01712      * Now link the hash table entry with the command structure. This is like
01713      * creating a new command, so deal with any shadowing of commands in the
01714      * global namespace.
01715      */
01716 
01717     cmdPtr->hPtr = hPtr;
01718 
01719     Tcl_SetHashValue(hPtr, cmdPtr);
01720 
01721     /*
01722      * Not needed as we are only in the global namespace (but would be needed
01723      * again if we supported namespace command hiding)
01724      *
01725      * TclResetShadowedCmdRefs(interp, cmdPtr);
01726      */
01727 
01728     /*
01729      * If the command being exposed has a compile function, increment
01730      * interpreter's compileEpoch to invalidate its compiled code. This makes
01731      * sure that we don't later try to execute old code compiled assuming the
01732      * command is hidden. This field is checked in Tcl_EvalObj and
01733      * ObjInterpProc, and code whose compilation epoch doesn't match is
01734      * recompiled.
01735      */
01736 
01737     if (cmdPtr->compileProc != NULL) {
01738         iPtr->compileEpoch++;
01739     }
01740     return TCL_OK;
01741 }
01742 
01743 /*
01744  *----------------------------------------------------------------------
01745  *
01746  * Tcl_CreateCommand --
01747  *
01748  *      Define a new command in a command table.
01749  *
01750  * Results:
01751  *      The return value is a token for the command, which can be used in
01752  *      future calls to Tcl_GetCommandName.
01753  *
01754  * Side effects:
01755  *      If a command named cmdName already exists for interp, it is deleted.
01756  *      In the future, when cmdName is seen as the name of a command by
01757  *      Tcl_Eval, proc will be called. To support the bytecode interpreter,
01758  *      the command is created with a wrapper Tcl_ObjCmdProc
01759  *      (TclInvokeStringCommand) that eventially calls proc. When the command
01760  *      is deleted from the table, deleteProc will be called. See the manual
01761  *      entry for details on the calling sequence.
01762  *
01763  *----------------------------------------------------------------------
01764  */
01765 
01766 Tcl_Command
01767 Tcl_CreateCommand(
01768     Tcl_Interp *interp,         /* Token for command interpreter returned by a
01769                                  * previous call to Tcl_CreateInterp. */
01770     const char *cmdName,        /* Name of command. If it contains namespace
01771                                  * qualifiers, the new command is put in the
01772                                  * specified namespace; otherwise it is put in
01773                                  * the global namespace. */
01774     Tcl_CmdProc *proc,          /* Function to associate with cmdName. */
01775     ClientData clientData,      /* Arbitrary value passed to string proc. */
01776     Tcl_CmdDeleteProc *deleteProc)
01777                                 /* If not NULL, gives a function to call when
01778                                  * this command is deleted. */
01779 {
01780     Interp *iPtr = (Interp *) interp;
01781     ImportRef *oldRefPtr = NULL;
01782     Namespace *nsPtr, *dummy1, *dummy2;
01783     Command *cmdPtr, *refCmdPtr;
01784     Tcl_HashEntry *hPtr;
01785     const char *tail;
01786     int isNew;
01787     ImportedCmdData *dataPtr;
01788 
01789     if (iPtr->flags & DELETED) {
01790         /*
01791          * The interpreter is being deleted. Don't create any new commands;
01792          * it's not safe to muck with the interpreter anymore.
01793          */
01794 
01795         return (Tcl_Command) NULL;
01796     }
01797 
01798     /*
01799      * Determine where the command should reside. If its name contains
01800      * namespace qualifiers, we put it in the specified namespace; otherwise,
01801      * we always put it in the global namespace.
01802      */
01803 
01804     if (strstr(cmdName, "::") != NULL) {
01805         TclGetNamespaceForQualName(interp, cmdName, NULL,
01806                 TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
01807         if ((nsPtr == NULL) || (tail == NULL)) {
01808             return (Tcl_Command) NULL;
01809         }
01810     } else {
01811         nsPtr = iPtr->globalNsPtr;
01812         tail = cmdName;
01813     }
01814 
01815     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
01816     if (!isNew) {
01817         /*
01818          * Command already exists. Delete the old one. Be careful to preserve
01819          * any existing import links so we can restore them down below. That
01820          * way, you can redefine a command and its import status will remain
01821          * intact.
01822          */
01823 
01824         cmdPtr = Tcl_GetHashValue(hPtr);
01825         oldRefPtr = cmdPtr->importRefPtr;
01826         cmdPtr->importRefPtr = NULL;
01827 
01828         Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
01829         hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
01830         if (!isNew) {
01831             /*
01832              * If the deletion callback recreated the command, just throw away
01833              * the new command (if we try to delete it again, we could get
01834              * stuck in an infinite loop).
01835              */
01836 
01837              ckfree((char *) Tcl_GetHashValue(hPtr));
01838         }
01839     } else {
01840         /*
01841          * The list of command exported from the namespace might have changed.
01842          * However, we do not need to recompute this just yet; next time we
01843          * need the info will be soon enough.
01844          */
01845 
01846         TclInvalidateNsCmdLookup(nsPtr);
01847         TclInvalidateNsPath(nsPtr);
01848     }
01849     cmdPtr = (Command *) ckalloc(sizeof(Command));
01850     Tcl_SetHashValue(hPtr, cmdPtr);
01851     cmdPtr->hPtr = hPtr;
01852     cmdPtr->nsPtr = nsPtr;
01853     cmdPtr->refCount = 1;
01854     cmdPtr->cmdEpoch = 0;
01855     cmdPtr->compileProc = NULL;
01856     cmdPtr->objProc = TclInvokeStringCommand;
01857     cmdPtr->objClientData = cmdPtr;
01858     cmdPtr->proc = proc;
01859     cmdPtr->clientData = clientData;
01860     cmdPtr->deleteProc = deleteProc;
01861     cmdPtr->deleteData = clientData;
01862     cmdPtr->flags = 0;
01863     cmdPtr->importRefPtr = NULL;
01864     cmdPtr->tracePtr = NULL;
01865 
01866     /*
01867      * Plug in any existing import references found above. Be sure to update
01868      * all of these references to point to the new command.
01869      */
01870 
01871     if (oldRefPtr != NULL) {
01872         cmdPtr->importRefPtr = oldRefPtr;
01873         while (oldRefPtr != NULL) {
01874             refCmdPtr = oldRefPtr->importedCmdPtr;
01875             dataPtr = refCmdPtr->objClientData;
01876             dataPtr->realCmdPtr = cmdPtr;
01877             oldRefPtr = oldRefPtr->nextPtr;
01878         }
01879     }
01880 
01881     /*
01882      * We just created a command, so in its namespace and all of its parent
01883      * namespaces, it may shadow global commands with the same name. If any
01884      * shadowed commands are found, invalidate all cached command references
01885      * in the affected namespaces.
01886      */
01887 
01888     TclResetShadowedCmdRefs(interp, cmdPtr);
01889     return (Tcl_Command) cmdPtr;
01890 }
01891 
01892 /*
01893  *----------------------------------------------------------------------
01894  *
01895  * Tcl_CreateObjCommand --
01896  *
01897  *      Define a new object-based command in a command table.
01898  *
01899  * Results:
01900  *      The return value is a token for the command, which can be used in
01901  *      future calls to Tcl_GetCommandName.
01902  *
01903  * Side effects:
01904  *      If no command named "cmdName" already exists for interp, one is
01905  *      created. Otherwise, if a command does exist, then if the object-based
01906  *      Tcl_ObjCmdProc is TclInvokeStringCommand, we assume Tcl_CreateCommand
01907  *      was called previously for the same command and just set its
01908  *      Tcl_ObjCmdProc to the argument "proc"; otherwise, we delete the old
01909  *      command.
01910  *
01911  *      In the future, during bytecode evaluation when "cmdName" is seen as
01912  *      the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
01913  *      Tcl_ObjCmdProc proc will be called. When the command is deleted from
01914  *      the table, deleteProc will be called. See the manual entry for details
01915  *      on the calling sequence.
01916  *
01917  *----------------------------------------------------------------------
01918  */
01919 
01920 Tcl_Command
01921 Tcl_CreateObjCommand(
01922     Tcl_Interp *interp,         /* Token for command interpreter (returned by
01923                                  * previous call to Tcl_CreateInterp). */
01924     const char *cmdName,        /* Name of command. If it contains namespace
01925                                  * qualifiers, the new command is put in the
01926                                  * specified namespace; otherwise it is put in
01927                                  * the global namespace. */
01928     Tcl_ObjCmdProc *proc,       /* Object-based function to associate with
01929                                  * name. */
01930     ClientData clientData,      /* Arbitrary value to pass to object
01931                                  * function. */
01932     Tcl_CmdDeleteProc *deleteProc)
01933                                 /* If not NULL, gives a function to call when
01934                                  * this command is deleted. */
01935 {
01936     Interp *iPtr = (Interp *) interp;
01937     ImportRef *oldRefPtr = NULL;
01938     Namespace *nsPtr, *dummy1, *dummy2;
01939     Command *cmdPtr, *refCmdPtr;
01940     Tcl_HashEntry *hPtr;
01941     const char *tail;
01942     int isNew;
01943     ImportedCmdData *dataPtr;
01944 
01945     if (iPtr->flags & DELETED) {
01946         /*
01947          * The interpreter is being deleted. Don't create any new commands;
01948          * it's not safe to muck with the interpreter anymore.
01949          */
01950 
01951         return (Tcl_Command) NULL;
01952     }
01953 
01954     /*
01955      * Determine where the command should reside. If its name contains
01956      * namespace qualifiers, we put it in the specified namespace; otherwise,
01957      * we always put it in the global namespace.
01958      */
01959 
01960     if (strstr(cmdName, "::") != NULL) {
01961         TclGetNamespaceForQualName(interp, cmdName, NULL,
01962                 TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
01963         if ((nsPtr == NULL) || (tail == NULL)) {
01964             return (Tcl_Command) NULL;
01965         }
01966     } else {
01967         nsPtr = iPtr->globalNsPtr;
01968         tail = cmdName;
01969     }
01970 
01971     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
01972     TclInvalidateNsPath(nsPtr);
01973     if (!isNew) {
01974         cmdPtr = Tcl_GetHashValue(hPtr);
01975 
01976         /*
01977          * Command already exists. If its object-based Tcl_ObjCmdProc is
01978          * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
01979          * argument "proc". Otherwise, we delete the old command.
01980          */
01981 
01982         if (cmdPtr->objProc == TclInvokeStringCommand) {
01983             cmdPtr->objProc = proc;
01984             cmdPtr->objClientData = clientData;
01985             cmdPtr->deleteProc = deleteProc;
01986             cmdPtr->deleteData = clientData;
01987             return (Tcl_Command) cmdPtr;
01988         }
01989 
01990         /*
01991          * Otherwise, we delete the old command. Be careful to preserve any
01992          * existing import links so we can restore them down below. That way,
01993          * you can redefine a command and its import status will remain
01994          * intact.
01995          */
01996 
01997         oldRefPtr = cmdPtr->importRefPtr;
01998         cmdPtr->importRefPtr = NULL;
01999 
02000         Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
02001         hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
02002         if (!isNew) {
02003             /*
02004              * If the deletion callback recreated the command, just throw away
02005              * the new command (if we try to delete it again, we could get
02006              * stuck in an infinite loop).
02007              */
02008 
02009              ckfree(Tcl_GetHashValue(hPtr));
02010         }
02011     } else {
02012         /*
02013          * The list of command exported from the namespace might have changed.
02014          * However, we do not need to recompute this just yet; next time we
02015          * need the info will be soon enough.
02016          */
02017 
02018         TclInvalidateNsCmdLookup(nsPtr);
02019     }
02020     cmdPtr = (Command *) ckalloc(sizeof(Command));
02021     Tcl_SetHashValue(hPtr, cmdPtr);
02022     cmdPtr->hPtr = hPtr;
02023     cmdPtr->nsPtr = nsPtr;
02024     cmdPtr->refCount = 1;
02025     cmdPtr->cmdEpoch = 0;
02026     cmdPtr->compileProc = NULL;
02027     cmdPtr->objProc = proc;
02028     cmdPtr->objClientData = clientData;
02029     cmdPtr->proc = TclInvokeObjectCommand;
02030     cmdPtr->clientData = cmdPtr;
02031     cmdPtr->deleteProc = deleteProc;
02032     cmdPtr->deleteData = clientData;
02033     cmdPtr->flags = 0;
02034     cmdPtr->importRefPtr = NULL;
02035     cmdPtr->tracePtr = NULL;
02036 
02037     /*
02038      * Plug in any existing import references found above. Be sure to update
02039      * all of these references to point to the new command.
02040      */
02041 
02042     if (oldRefPtr != NULL) {
02043         cmdPtr->importRefPtr = oldRefPtr;
02044         while (oldRefPtr != NULL) {
02045             refCmdPtr = oldRefPtr->importedCmdPtr;
02046             dataPtr = refCmdPtr->objClientData;
02047             dataPtr->realCmdPtr = cmdPtr;
02048             oldRefPtr = oldRefPtr->nextPtr;
02049         }
02050     }
02051 
02052     /*
02053      * We just created a command, so in its namespace and all of its parent
02054      * namespaces, it may shadow global commands with the same name. If any
02055      * shadowed commands are found, invalidate all cached command references
02056      * in the affected namespaces.
02057      */
02058 
02059     TclResetShadowedCmdRefs(interp, cmdPtr);
02060     return (Tcl_Command) cmdPtr;
02061 }
02062 
02063 /*
02064  *----------------------------------------------------------------------
02065  *
02066  * TclInvokeStringCommand --
02067  *
02068  *      "Wrapper" Tcl_ObjCmdProc used to call an existing string-based
02069  *      Tcl_CmdProc if no object-based function exists for a command. A
02070  *      pointer to this function is stored as the Tcl_ObjCmdProc in a Command
02071  *      structure. It simply turns around and calls the string Tcl_CmdProc in
02072  *      the Command structure.
02073  *
02074  * Results:
02075  *      A standard Tcl object result value.
02076  *
02077  * Side effects:
02078  *      Besides those side effects of the called Tcl_CmdProc,
02079  *      TclInvokeStringCommand allocates and frees storage.
02080  *
02081  *----------------------------------------------------------------------
02082  */
02083 
02084 int
02085 TclInvokeStringCommand(
02086     ClientData clientData,      /* Points to command's Command structure. */
02087     Tcl_Interp *interp,         /* Current interpreter. */
02088     register int objc,          /* Number of arguments. */
02089     Tcl_Obj *const objv[])      /* Argument objects. */
02090 {
02091     Command *cmdPtr = clientData;
02092     int i, result;
02093     const char **argv = (const char **)
02094             TclStackAlloc(interp, (unsigned)(objc + 1) * sizeof(char *));
02095 
02096     for (i = 0;  i < objc;  i++) {
02097         argv[i] = Tcl_GetString(objv[i]);
02098     }
02099     argv[objc] = 0;
02100 
02101     /*
02102      * Invoke the command's string-based Tcl_CmdProc.
02103      */
02104 
02105     result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv);
02106 
02107     TclStackFree(interp, (void *) argv);
02108     return result;
02109 }
02110 
02111 /*
02112  *----------------------------------------------------------------------
02113  *
02114  * TclInvokeObjectCommand --
02115  *
02116  *      "Wrapper" Tcl_CmdProc used to call an existing object-based
02117  *      Tcl_ObjCmdProc if no string-based function exists for a command. A
02118  *      pointer to this function is stored as the Tcl_CmdProc in a Command
02119  *      structure. It simply turns around and calls the object Tcl_ObjCmdProc
02120  *      in the Command structure.
02121  *
02122  * Results:
02123  *      A standard Tcl string result value.
02124  *
02125  * Side effects:
02126  *      Besides those side effects of the called Tcl_CmdProc,
02127  *      TclInvokeStringCommand allocates and frees storage.
02128  *
02129  *----------------------------------------------------------------------
02130  */
02131 
02132 int
02133 TclInvokeObjectCommand(
02134     ClientData clientData,      /* Points to command's Command structure. */
02135     Tcl_Interp *interp,         /* Current interpreter. */
02136     int argc,                   /* Number of arguments. */
02137     register const char **argv) /* Argument strings. */
02138 {
02139     Command *cmdPtr = (Command *) clientData;
02140     Tcl_Obj *objPtr;
02141     int i, length, result;
02142     Tcl_Obj **objv = (Tcl_Obj **)
02143             TclStackAlloc(interp, (unsigned)(argc * sizeof(Tcl_Obj *)));
02144 
02145     for (i = 0;  i < argc;  i++) {
02146         length = strlen(argv[i]);
02147         TclNewStringObj(objPtr, argv[i], length);
02148         Tcl_IncrRefCount(objPtr);
02149         objv[i] = objPtr;
02150     }
02151 
02152     /*
02153      * Invoke the command's object-based Tcl_ObjCmdProc.
02154      */
02155 
02156     result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);
02157 
02158     /*
02159      * Move the interpreter's object result to the string result, then reset
02160      * the object result.
02161      */
02162 
02163     (void) Tcl_GetStringResult(interp);
02164 
02165     /*
02166      * Decrement the ref counts for the argument objects created above, then
02167      * free the objv array if malloc'ed storage was used.
02168      */
02169 
02170     for (i = 0;  i < argc;  i++) {
02171         objPtr = objv[i];
02172         Tcl_DecrRefCount(objPtr);
02173     }
02174     TclStackFree(interp, objv);
02175     return result;
02176 }
02177 
02178 /*
02179  *----------------------------------------------------------------------
02180  *
02181  * TclRenameCommand --
02182  *
02183  *      Called to give an existing Tcl command a different name. Both the old
02184  *      command name and the new command name can have "::" namespace
02185  *      qualifiers. If the new command has a different namespace context, the
02186  *      command will be moved to that namespace and will execute in the
02187  *      context of that new namespace.
02188  *
02189  *      If the new command name is NULL or the null string, the command is
02190  *      deleted.
02191  *
02192  * Results:
02193  *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
02194  *
02195  * Side effects:
02196  *      If anything goes wrong, an error message is returned in the
02197  *      interpreter's result object.
02198  *
02199  *----------------------------------------------------------------------
02200  */
02201 
02202 int
02203 TclRenameCommand(
02204     Tcl_Interp *interp,         /* Current interpreter. */
02205     const char *oldName,        /* Existing command name. */
02206     const char *newName)        /* New command name. */
02207 {
02208     Interp *iPtr = (Interp *) interp;
02209     const char *newTail;
02210     Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2;
02211     Tcl_Command cmd;
02212     Command *cmdPtr;
02213     Tcl_HashEntry *hPtr, *oldHPtr;
02214     int isNew, result;
02215     Tcl_Obj *oldFullName;
02216     Tcl_DString newFullName;
02217 
02218     /*
02219      * Find the existing command. An error is returned if cmdName can't be
02220      * found.
02221      */
02222 
02223     cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0);
02224     cmdPtr = (Command *) cmd;
02225     if (cmdPtr == NULL) {
02226         Tcl_AppendResult(interp, "can't ",
02227                 ((newName == NULL)||(*newName == '\0'))? "delete":"rename",
02228                 " \"", oldName, "\": command doesn't exist", NULL);
02229         return TCL_ERROR;
02230     }
02231     cmdNsPtr = cmdPtr->nsPtr;
02232     oldFullName = Tcl_NewObj();
02233     Tcl_IncrRefCount(oldFullName);
02234     Tcl_GetCommandFullName(interp, cmd, oldFullName);
02235 
02236     /*
02237      * If the new command name is NULL or empty, delete the command. Do this
02238      * with Tcl_DeleteCommandFromToken, since we already have the command.
02239      */
02240 
02241     if ((newName == NULL) || (*newName == '\0')) {
02242         Tcl_DeleteCommandFromToken(interp, cmd);
02243         result = TCL_OK;
02244         goto done;
02245     }
02246 
02247     /*
02248      * Make sure that the destination command does not already exist. The
02249      * rename operation is like creating a command, so we should automatically
02250      * create the containing namespaces just like Tcl_CreateCommand would.
02251      */
02252 
02253     TclGetNamespaceForQualName(interp, newName, NULL,
02254             TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
02255 
02256     if ((newNsPtr == NULL) || (newTail == NULL)) {
02257         Tcl_AppendResult(interp, "can't rename to \"", newName,
02258                 "\": bad command name", NULL);
02259         result = TCL_ERROR;
02260         goto done;
02261     }
02262     if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) {
02263         Tcl_AppendResult(interp, "can't rename to \"", newName,
02264                  "\": command already exists", NULL);
02265         result = TCL_ERROR;
02266         goto done;
02267     }
02268 
02269     /*
02270      * Warning: any changes done in the code here are likely to be needed in
02271      * Tcl_HideCommand() code too (until the common parts are extracted out).
02272      * - dl
02273      */
02274 
02275     /*
02276      * Put the command in the new namespace so we can check for an alias loop.
02277      * Since we are adding a new command to a namespace, we must handle any
02278      * shadowing of the global commands that this might create.
02279      */
02280 
02281     oldHPtr = cmdPtr->hPtr;
02282     hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &isNew);
02283     Tcl_SetHashValue(hPtr, cmdPtr);
02284     cmdPtr->hPtr = hPtr;
02285     cmdPtr->nsPtr = newNsPtr;
02286     TclResetShadowedCmdRefs(interp, cmdPtr);
02287 
02288     /*
02289      * Now check for an alias loop. If we detect one, put everything back the
02290      * way it was and report the error.
02291      */
02292 
02293     result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr);
02294     if (result != TCL_OK) {
02295         Tcl_DeleteHashEntry(cmdPtr->hPtr);
02296         cmdPtr->hPtr = oldHPtr;
02297         cmdPtr->nsPtr = cmdNsPtr;
02298         goto done;
02299     }
02300 
02301     /*
02302      * The list of command exported from the namespace might have changed.
02303      * However, we do not need to recompute this just yet; next time we need
02304      * the info will be soon enough. These might refer to the same variable,
02305      * but that's no big deal.
02306      */
02307 
02308     TclInvalidateNsCmdLookup(cmdNsPtr);
02309     TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
02310 
02311     /*
02312      * Script for rename traces can delete the command "oldName". Therefore
02313      * increment the reference count for cmdPtr so that it's Command structure
02314      * is freed only towards the end of this function by calling
02315      * TclCleanupCommand.
02316      *
02317      * The trace function needs to get a fully qualified name for old and new
02318      * commands [Tcl bug #651271], or else there's no way for the trace
02319      * function to get the namespace from which the old command is being
02320      * renamed!
02321      */
02322 
02323     Tcl_DStringInit(&newFullName);
02324     Tcl_DStringAppend(&newFullName, newNsPtr->fullName, -1);
02325     if (newNsPtr != iPtr->globalNsPtr) {
02326         Tcl_DStringAppend(&newFullName, "::", 2);
02327     }
02328     Tcl_DStringAppend(&newFullName, newTail, -1);
02329     cmdPtr->refCount++;
02330     CallCommandTraces(iPtr, cmdPtr, Tcl_GetString(oldFullName),
02331             Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME);
02332     Tcl_DStringFree(&newFullName);
02333 
02334     /*
02335      * The new command name is okay, so remove the command from its current
02336      * namespace. This is like deleting the command, so bump the cmdEpoch to
02337      * invalidate any cached references to the command.
02338      */
02339 
02340     Tcl_DeleteHashEntry(oldHPtr);
02341     cmdPtr->cmdEpoch++;
02342 
02343     /*
02344      * If the command being renamed has a compile function, increment the
02345      * interpreter's compileEpoch to invalidate its compiled code. This makes
02346      * sure that we don't later try to execute old code compiled for the
02347      * now-renamed command.
02348      */
02349 
02350     if (cmdPtr->compileProc != NULL) {
02351         iPtr->compileEpoch++;
02352     }
02353 
02354     /*
02355      * Now free the Command structure, if the "oldName" command has been
02356      * deleted by invocation of rename traces.
02357      */
02358 
02359     TclCleanupCommandMacro(cmdPtr);
02360     result = TCL_OK;
02361 
02362   done:
02363     TclDecrRefCount(oldFullName);
02364     return result;
02365 }
02366 
02367 /*
02368  *----------------------------------------------------------------------
02369  *
02370  * Tcl_SetCommandInfo --
02371  *
02372  *      Modifies various information about a Tcl command. Note that this
02373  *      function will not change a command's namespace; use TclRenameCommand
02374  *      to do that. Also, the isNativeObjectProc member of *infoPtr is
02375  *      ignored.
02376  *
02377  * Results:
02378  *      If cmdName exists in interp, then the information at *infoPtr is
02379  *      stored with the command in place of the current information and 1 is
02380  *      returned. If the command doesn't exist then 0 is returned.
02381  *
02382  * Side effects:
02383  *      None.
02384  *
02385  *----------------------------------------------------------------------
02386  */
02387 
02388 int
02389 Tcl_SetCommandInfo(
02390     Tcl_Interp *interp,         /* Interpreter in which to look for
02391                                  * command. */
02392     const char *cmdName,        /* Name of desired command. */
02393     const Tcl_CmdInfo *infoPtr) /* Where to find information to store in the
02394                                  * command. */
02395 {
02396     Tcl_Command cmd;
02397 
02398     cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
02399     return Tcl_SetCommandInfoFromToken(cmd, infoPtr);
02400 }
02401 
02402 /*
02403  *----------------------------------------------------------------------
02404  *
02405  * Tcl_SetCommandInfoFromToken --
02406  *
02407  *      Modifies various information about a Tcl command. Note that this
02408  *      function will not change a command's namespace; use TclRenameCommand
02409  *      to do that. Also, the isNativeObjectProc member of *infoPtr is
02410  *      ignored.
02411  *
02412  * Results:
02413  *      If cmdName exists in interp, then the information at *infoPtr is
02414  *      stored with the command in place of the current information and 1 is
02415  *      returned. If the command doesn't exist then 0 is returned.
02416  *
02417  * Side effects:
02418  *      None.
02419  *
02420  *----------------------------------------------------------------------
02421  */
02422 
02423 int
02424 Tcl_SetCommandInfoFromToken(
02425     Tcl_Command cmd,
02426     const Tcl_CmdInfo *infoPtr)
02427 {
02428     Command *cmdPtr;            /* Internal representation of the command */
02429 
02430     if (cmd == (Tcl_Command) NULL) {
02431         return 0;
02432     }
02433 
02434     /*
02435      * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
02436      */
02437 
02438     cmdPtr = (Command *) cmd;
02439     cmdPtr->proc = infoPtr->proc;
02440     cmdPtr->clientData = infoPtr->clientData;
02441     if (infoPtr->objProc == NULL) {
02442         cmdPtr->objProc = TclInvokeStringCommand;
02443         cmdPtr->objClientData = cmdPtr;
02444     } else {
02445         cmdPtr->objProc = infoPtr->objProc;
02446         cmdPtr->objClientData = infoPtr->objClientData;
02447     }
02448     cmdPtr->deleteProc = infoPtr->deleteProc;
02449     cmdPtr->deleteData = infoPtr->deleteData;
02450     return 1;
02451 }
02452 
02453 /*
02454  *----------------------------------------------------------------------
02455  *
02456  * Tcl_GetCommandInfo --
02457  *
02458  *      Returns various information about a Tcl command.
02459  *
02460  * Results:
02461  *      If cmdName exists in interp, then *infoPtr is modified to hold
02462  *      information about cmdName and 1 is returned. If the command doesn't
02463  *      exist then 0 is returned and *infoPtr isn't modified.
02464  *
02465  * Side effects:
02466  *      None.
02467  *
02468  *----------------------------------------------------------------------
02469  */
02470 
02471 int
02472 Tcl_GetCommandInfo(
02473     Tcl_Interp *interp,         /* Interpreter in which to look for
02474                                  * command. */
02475     const char *cmdName,        /* Name of desired command. */
02476     Tcl_CmdInfo *infoPtr)       /* Where to store information about
02477                                  * command. */
02478 {
02479     Tcl_Command cmd;
02480 
02481     cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
02482     return Tcl_GetCommandInfoFromToken(cmd, infoPtr);
02483 }
02484 
02485 /*
02486  *----------------------------------------------------------------------
02487  *
02488  * Tcl_GetCommandInfoFromToken --
02489  *
02490  *      Returns various information about a Tcl command.
02491  *
02492  * Results:
02493  *      Copies information from the command identified by 'cmd' into a
02494  *      caller-supplied structure and returns 1. If the 'cmd' is NULL, leaves
02495  *      the structure untouched and returns 0.
02496  *
02497  * Side effects:
02498  *      None.
02499  *
02500  *----------------------------------------------------------------------
02501  */
02502 
02503 int
02504 Tcl_GetCommandInfoFromToken(
02505     Tcl_Command cmd,
02506     Tcl_CmdInfo *infoPtr)
02507 {
02508     Command *cmdPtr;            /* Internal representation of the command */
02509 
02510     if (cmd == (Tcl_Command) NULL) {
02511         return 0;
02512     }
02513 
02514     /*
02515      * Set isNativeObjectProc 1 if objProc was registered by a call to
02516      * Tcl_CreateObjCommand. Otherwise set it to 0.
02517      */
02518 
02519     cmdPtr = (Command *) cmd;
02520     infoPtr->isNativeObjectProc =
02521             (cmdPtr->objProc != TclInvokeStringCommand);
02522     infoPtr->objProc = cmdPtr->objProc;
02523     infoPtr->objClientData = cmdPtr->objClientData;
02524     infoPtr->proc = cmdPtr->proc;
02525     infoPtr->clientData = cmdPtr->clientData;
02526     infoPtr->deleteProc = cmdPtr->deleteProc;
02527     infoPtr->deleteData = cmdPtr->deleteData;
02528     infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
02529 
02530     return 1;
02531 }
02532 
02533 /*
02534  *----------------------------------------------------------------------
02535  *
02536  * Tcl_GetCommandName --
02537  *
02538  *      Given a token returned by Tcl_CreateCommand, this function returns the
02539  *      current name of the command (which may have changed due to renaming).
02540  *
02541  * Results:
02542  *      The return value is the name of the given command.
02543  *
02544  * Side effects:
02545  *      None.
02546  *
02547  *----------------------------------------------------------------------
02548  */
02549 
02550 const char *
02551 Tcl_GetCommandName(
02552     Tcl_Interp *interp,         /* Interpreter containing the command. */
02553     Tcl_Command command)        /* Token for command returned by a previous
02554                                  * call to Tcl_CreateCommand. The command must
02555                                  * not have been deleted. */
02556 {
02557     Command *cmdPtr = (Command *) command;
02558 
02559     if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
02560         /*
02561          * This should only happen if command was "created" after the
02562          * interpreter began to be deleted, so there isn't really any command.
02563          * Just return an empty string.
02564          */
02565 
02566         return "";
02567     }
02568 
02569     return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
02570 }
02571 
02572 /*
02573  *----------------------------------------------------------------------
02574  *
02575  * Tcl_GetCommandFullName --
02576  *
02577  *      Given a token returned by, e.g., Tcl_CreateCommand or Tcl_FindCommand,
02578  *      this function appends to an object the command's full name, qualified
02579  *      by a sequence of parent namespace names. The command's fully-qualified
02580  *      name may have changed due to renaming.
02581  *
02582  * Results:
02583  *      None.
02584  *
02585  * Side effects:
02586  *      The command's fully-qualified name is appended to the string
02587  *      representation of objPtr.
02588  *
02589  *----------------------------------------------------------------------
02590  */
02591 
02592 void
02593 Tcl_GetCommandFullName(
02594     Tcl_Interp *interp,         /* Interpreter containing the command. */
02595     Tcl_Command command,        /* Token for command returned by a previous
02596                                  * call to Tcl_CreateCommand. The command must
02597                                  * not have been deleted. */
02598     Tcl_Obj *objPtr)            /* Points to the object onto which the
02599                                  * command's full name is appended. */
02600 
02601 {
02602     Interp *iPtr = (Interp *) interp;
02603     register Command *cmdPtr = (Command *) command;
02604     char *name;
02605 
02606     /*
02607      * Add the full name of the containing namespace, followed by the "::"
02608      * separator, and the command name.
02609      */
02610 
02611     if (cmdPtr != NULL) {
02612         if (cmdPtr->nsPtr != NULL) {
02613             Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1);
02614             if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
02615                 Tcl_AppendToObj(objPtr, "::", 2);
02616             }
02617         }
02618         if (cmdPtr->hPtr != NULL) {
02619             name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
02620             Tcl_AppendToObj(objPtr, name, -1);
02621         }
02622     }
02623 }
02624 
02625 /*
02626  *----------------------------------------------------------------------
02627  *
02628  * Tcl_DeleteCommand --
02629  *
02630  *      Remove the given command from the given interpreter.
02631  *
02632  * Results:
02633  *      0 is returned if the command was deleted successfully. -1 is returned
02634  *      if there didn't exist a command by that name.
02635  *
02636  * Side effects:
02637  *      cmdName will no longer be recognized as a valid command for interp.
02638  *
02639  *----------------------------------------------------------------------
02640  */
02641 
02642 int
02643 Tcl_DeleteCommand(
02644     Tcl_Interp *interp,         /* Token for command interpreter (returned by
02645                                  * a previous Tcl_CreateInterp call). */
02646     const char *cmdName)        /* Name of command to remove. */
02647 {
02648     Tcl_Command cmd;
02649 
02650     /*
02651      * Find the desired command and delete it.
02652      */
02653 
02654     cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
02655     if (cmd == (Tcl_Command) NULL) {
02656         return -1;
02657     }
02658     return Tcl_DeleteCommandFromToken(interp, cmd);
02659 }
02660 
02661 /*
02662  *----------------------------------------------------------------------
02663  *
02664  * Tcl_DeleteCommandFromToken --
02665  *
02666  *      Removes the given command from the given interpreter. This function
02667  *      resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead of
02668  *      a command name for efficiency.
02669  *
02670  * Results:
02671  *      0 is returned if the command was deleted successfully. -1 is returned
02672  *      if there didn't exist a command by that name.
02673  *
02674  * Side effects:
02675  *      The command specified by "cmd" will no longer be recognized as a valid
02676  *      command for "interp".
02677  *
02678  *----------------------------------------------------------------------
02679  */
02680 
02681 int
02682 Tcl_DeleteCommandFromToken(
02683     Tcl_Interp *interp,         /* Token for command interpreter returned by a
02684                                  * previous call to Tcl_CreateInterp. */
02685     Tcl_Command cmd)            /* Token for command to delete. */
02686 {
02687     Interp *iPtr = (Interp *) interp;
02688     Command *cmdPtr = (Command *) cmd;
02689     ImportRef *refPtr, *nextRefPtr;
02690     Tcl_Command importCmd;
02691 
02692     /*
02693      * Bump the command epoch counter. This will invalidate all cached
02694      * references that point to this command.
02695      */
02696 
02697     cmdPtr->cmdEpoch++;
02698 
02699     /*
02700      * The code here is tricky. We can't delete the hash table entry before
02701      * invoking the deletion callback because there are cases where the
02702      * deletion callback needs to invoke the command (e.g. object systems such
02703      * as OTcl). However, this means that the callback could try to delete or
02704      * rename the command. The deleted flag allows us to detect these cases
02705      * and skip nested deletes.
02706      */
02707 
02708     if (cmdPtr->flags & CMD_IS_DELETED) {
02709         /*
02710          * Another deletion is already in progress. Remove the hash table
02711          * entry now, but don't invoke a callback or free the command
02712          * structure. Take care to only remove the hash entry if it has not
02713          * already been removed; otherwise if we manage to hit this function
02714          * three times, everything goes up in smoke. [Bug 1220058]
02715          */
02716 
02717         if (cmdPtr->hPtr != NULL) {
02718             Tcl_DeleteHashEntry(cmdPtr->hPtr);
02719             cmdPtr->hPtr = NULL;
02720         }
02721         return 0;
02722     }
02723 
02724     /*
02725      * We must delete this command, even though both traces and delete procs
02726      * may try to avoid this (renaming the command etc). Also traces and
02727      * delete procs may try to delete the command themsevles. This flag
02728      * declares that a delete is in progress and that recursive deletes should
02729      * be ignored.
02730      */
02731 
02732     cmdPtr->flags |= CMD_IS_DELETED;
02733 
02734     /*
02735      * Call trace functions for the command being deleted. Then delete its
02736      * traces.
02737      */
02738 
02739     if (cmdPtr->tracePtr != NULL) {
02740         CommandTrace *tracePtr;
02741         CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);
02742 
02743         /*
02744          * Now delete these traces.
02745          */
02746 
02747         tracePtr = cmdPtr->tracePtr;
02748         while (tracePtr != NULL) {
02749             CommandTrace *nextPtr = tracePtr->nextPtr;
02750             if ((--tracePtr->refCount) <= 0) {
02751                 ckfree((char *) tracePtr);
02752             }
02753             tracePtr = nextPtr;
02754         }
02755         cmdPtr->tracePtr = NULL;
02756     }
02757 
02758     /*
02759      * The list of command exported from the namespace might have changed.
02760      * However, we do not need to recompute this just yet; next time we need
02761      * the info will be soon enough.
02762      */
02763 
02764     TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
02765 
02766     /*
02767      * If the command being deleted has a compile function, increment the
02768      * interpreter's compileEpoch to invalidate its compiled code. This makes
02769      * sure that we don't later try to execute old code compiled with
02770      * command-specific (i.e., inline) bytecodes for the now-deleted command.
02771      * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose
02772      * compilation epoch doesn't match is recompiled.
02773      */
02774 
02775     if (cmdPtr->compileProc != NULL) {
02776         iPtr->compileEpoch++;
02777     }
02778 
02779     if (cmdPtr->deleteProc != NULL) {
02780         /*
02781          * Delete the command's client data. If this was an imported command
02782          * created when a command was imported into a namespace, this client
02783          * data will be a pointer to a ImportedCmdData structure describing
02784          * the "real" command that this imported command refers to.
02785          */
02786 
02787         /*
02788          * If you are getting a crash during the call to deleteProc and
02789          * cmdPtr->deleteProc is a pointer to the function free(), the most
02790          * likely cause is that your extension allocated memory for the
02791          * clientData argument to Tcl_CreateObjCommand() with the ckalloc()
02792          * macro and you are now trying to deallocate this memory with free()
02793          * instead of ckfree(). You should pass a pointer to your own method
02794          * that calls ckfree().
02795          */
02796 
02797         (*cmdPtr->deleteProc)(cmdPtr->deleteData);
02798     }
02799 
02800     /*
02801      * If this command was imported into other namespaces, then imported
02802      * commands were created that refer back to this command. Delete these
02803      * imported commands now.
02804      */
02805 
02806     for (refPtr = cmdPtr->importRefPtr;  refPtr != NULL;
02807             refPtr = nextRefPtr) {
02808         nextRefPtr = refPtr->nextPtr;
02809         importCmd = (Tcl_Command) refPtr->importedCmdPtr;
02810         Tcl_DeleteCommandFromToken(interp, importCmd);
02811     }
02812 
02813     /*
02814      * Don't use hPtr to delete the hash entry here, because it's possible
02815      * that the deletion callback renamed the command. Instead, use
02816      * cmdPtr->hptr, and make sure that no-one else has already deleted the
02817      * hash entry.
02818      */
02819 
02820     if (cmdPtr->hPtr != NULL) {
02821         Tcl_DeleteHashEntry(cmdPtr->hPtr);
02822         cmdPtr->hPtr = NULL;
02823     }
02824 
02825     /*
02826      * Mark the Command structure as no longer valid. This allows
02827      * TclExecuteByteCode to recognize when a Command has logically been
02828      * deleted and a pointer to this Command structure cached in a CmdName
02829      * object is invalid. TclExecuteByteCode will look up the command again in
02830      * the interpreter's command hashtable.
02831      */
02832 
02833     cmdPtr->objProc = NULL;
02834 
02835     /*
02836      * Now free the Command structure, unless there is another reference to it
02837      * from a CmdName Tcl object in some ByteCode code sequence. In that case,
02838      * delay the cleanup until all references are either discarded (when a
02839      * ByteCode is freed) or replaced by a new reference (when a cached
02840      * CmdName Command reference is found to be invalid and TclExecuteByteCode
02841      * looks up the command in the command hashtable).
02842      */
02843 
02844     TclCleanupCommandMacro(cmdPtr);
02845     return 0;
02846 }
02847 
02848 static char *
02849 CallCommandTraces(
02850     Interp *iPtr,               /* Interpreter containing command. */
02851     Command *cmdPtr,            /* Command whose traces are to be invoked. */
02852     const char *oldName,        /* Command's old name, or NULL if we must get
02853                                  * the name from cmdPtr */
02854     const char *newName,        /* Command's new name, or NULL if the command
02855                                  * is not being renamed */
02856     int flags)                  /* Flags indicating the type of traces to
02857                                  * trigger, either TCL_TRACE_DELETE or
02858                                  * TCL_TRACE_RENAME. */
02859 {
02860     register CommandTrace *tracePtr;
02861     ActiveCommandTrace active;
02862     char *result;
02863     Tcl_Obj *oldNamePtr = NULL;
02864     Tcl_InterpState state = NULL;
02865 
02866     if (cmdPtr->flags & CMD_TRACE_ACTIVE) {
02867         /*
02868          * While a rename trace is active, we will not process any more rename
02869          * traces; while a delete trace is active we will never reach here -
02870          * because Tcl_DeleteCommandFromToken checks for the condition
02871          * (cmdPtr->flags & CMD_IS_DELETED) and returns immediately when a
02872          * command deletion is in progress. For all other traces, delete
02873          * traces will not be invoked but a call to TraceCommandProc will
02874          * ensure that tracePtr->clientData is freed whenever the command
02875          * "oldName" is deleted.
02876          */
02877 
02878         if (cmdPtr->flags & TCL_TRACE_RENAME) {
02879             flags &= ~TCL_TRACE_RENAME;
02880         }
02881         if (flags == 0) {
02882             return NULL;
02883         }
02884     }
02885     cmdPtr->flags |= CMD_TRACE_ACTIVE;
02886     cmdPtr->refCount++;
02887 
02888     result = NULL;
02889     active.nextPtr = iPtr->activeCmdTracePtr;
02890     active.reverseScan = 0;
02891     iPtr->activeCmdTracePtr = &active;
02892 
02893     if (flags & TCL_TRACE_DELETE) {
02894         flags |= TCL_TRACE_DESTROYED;
02895     }
02896     active.cmdPtr = cmdPtr;
02897 
02898     Tcl_Preserve(iPtr);
02899 
02900     for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL;
02901             tracePtr = active.nextTracePtr) {
02902         active.nextTracePtr = tracePtr->nextPtr;
02903         if (!(tracePtr->flags & flags)) {
02904             continue;
02905         }
02906         cmdPtr->flags |= tracePtr->flags;
02907         if (oldName == NULL) {
02908             TclNewObj(oldNamePtr);
02909             Tcl_IncrRefCount(oldNamePtr);
02910             Tcl_GetCommandFullName((Tcl_Interp *) iPtr,
02911                     (Tcl_Command) cmdPtr, oldNamePtr);
02912             oldName = TclGetString(oldNamePtr);
02913         }
02914         tracePtr->refCount++;
02915         if (state == NULL) {
02916             state = Tcl_SaveInterpState((Tcl_Interp *) iPtr, TCL_OK);
02917         }
02918         (*tracePtr->traceProc)(tracePtr->clientData,
02919                 (Tcl_Interp *) iPtr, oldName, newName, flags);
02920         cmdPtr->flags &= ~tracePtr->flags;
02921         if ((--tracePtr->refCount) <= 0) {
02922             ckfree((char *) tracePtr);
02923         }
02924     }
02925 
02926     if (state) {
02927         Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state);
02928     }
02929 
02930     /*
02931      * If a new object was created to hold the full oldName, free it now.
02932      */
02933 
02934     if (oldNamePtr != NULL) {
02935         TclDecrRefCount(oldNamePtr);
02936     }
02937 
02938     /*
02939      * Restore the variable's flags, remove the record of our active traces,
02940      * and then return.
02941      */
02942 
02943     cmdPtr->flags &= ~CMD_TRACE_ACTIVE;
02944     cmdPtr->refCount--;
02945     iPtr->activeCmdTracePtr = active.nextPtr;
02946     Tcl_Release(iPtr);
02947     return result;
02948 }
02949 
02950 /*
02951  *----------------------------------------------------------------------
02952  *
02953  * GetCommandSource --
02954  *
02955  *      This function returns a Tcl_Obj with the full source string for the
02956  *      command. This insures that traces get a correct NUL-terminated command
02957  *      string.
02958  *
02959  *----------------------------------------------------------------------
02960  */
02961 
02962 static Tcl_Obj *
02963 GetCommandSource(
02964     Interp *iPtr,
02965     const char *command,
02966     int numChars,
02967     int objc,
02968     Tcl_Obj *const objv[])
02969 {
02970     if (!command) {
02971         return Tcl_NewListObj(objc, objv);
02972     }
02973     if (command == (char *) -1) {
02974         command = TclGetSrcInfoForCmd(iPtr, &numChars);
02975     }
02976     return Tcl_NewStringObj(command, numChars);
02977 }
02978 
02979 /*
02980  *----------------------------------------------------------------------
02981  *
02982  * TclCleanupCommand --
02983  *
02984  *      This function frees up a Command structure unless it is still
02985  *      referenced from an interpreter's command hashtable or from a CmdName
02986  *      Tcl object representing the name of a command in a ByteCode
02987  *      instruction sequence.
02988  *
02989  * Results:
02990  *      None.
02991  *
02992  * Side effects:
02993  *      Memory gets freed unless a reference to the Command structure still
02994  *      exists. In that case the cleanup is delayed until the command is
02995  *      deleted or when the last ByteCode referring to it is freed.
02996  *
02997  *----------------------------------------------------------------------
02998  */
02999 
03000 void
03001 TclCleanupCommand(
03002     register Command *cmdPtr)   /* Points to the Command structure to
03003                                  * be freed. */
03004 {
03005     cmdPtr->refCount--;
03006     if (cmdPtr->refCount <= 0) {
03007         ckfree((char *) cmdPtr);
03008     }
03009 }
03010 
03011 /*
03012  *----------------------------------------------------------------------
03013  *
03014  * Tcl_CreateMathFunc --
03015  *
03016  *      Creates a new math function for expressions in a given interpreter.
03017  *
03018  * Results:
03019  *      None.
03020  *
03021  * Side effects:
03022  *      The Tcl function defined by "name" is created or redefined. If the
03023  *      function already exists then its definition is replaced; this includes
03024  *      the builtin functions. Redefining a builtin function forces all
03025  *      existing code to be invalidated since that code may be compiled using
03026  *      an instruction specific to the replaced function. In addition,
03027  *      redefioning a non-builtin function will force existing code to be
03028  *      invalidated if the number of arguments has changed.
03029  *
03030  *----------------------------------------------------------------------
03031  */
03032 
03033 void
03034 Tcl_CreateMathFunc(
03035     Tcl_Interp *interp,         /* Interpreter in which function is to be
03036                                  * available. */
03037     const char *name,           /* Name of function (e.g. "sin"). */
03038     int numArgs,                /* Nnumber of arguments required by
03039                                  * function. */
03040     Tcl_ValueType *argTypes,    /* Array of types acceptable for each
03041                                  * argument. */
03042     Tcl_MathProc *proc,         /* C function that implements the math
03043                                  * function. */
03044     ClientData clientData)      /* Additional value to pass to the
03045                                  * function. */
03046 {
03047     Tcl_DString bigName;
03048     OldMathFuncData *data = (OldMathFuncData *)
03049             ckalloc(sizeof(OldMathFuncData));
03050 
03051     data->proc = proc;
03052     data->numArgs = numArgs;
03053     data->argTypes = (Tcl_ValueType *)
03054             ckalloc(numArgs * sizeof(Tcl_ValueType));
03055     memcpy(data->argTypes, argTypes, numArgs * sizeof(Tcl_ValueType));
03056     data->clientData = clientData;
03057 
03058     Tcl_DStringInit(&bigName);
03059     Tcl_DStringAppend(&bigName, "::tcl::mathfunc::", -1);
03060     Tcl_DStringAppend(&bigName, name, -1);
03061 
03062     Tcl_CreateObjCommand(interp, Tcl_DStringValue(&bigName),
03063             OldMathFuncProc, data, OldMathFuncDeleteProc);
03064     Tcl_DStringFree(&bigName);
03065 }
03066 
03067 /*
03068  *----------------------------------------------------------------------
03069  *
03070  * OldMathFuncProc --
03071  *
03072  *      Dispatch to a math function created with Tcl_CreateMathFunc
03073  *
03074  * Results:
03075  *      Returns a standard Tcl result.
03076  *
03077  * Side effects:
03078  *      Whatever the math function does.
03079  *
03080  *----------------------------------------------------------------------
03081  */
03082 
03083 static int
03084 OldMathFuncProc(
03085     ClientData clientData,      /* Ponter to OldMathFuncData describing the
03086                                  * function being called */
03087     Tcl_Interp *interp,         /* Tcl interpreter */
03088     int objc,                   /* Actual parameter count */
03089     Tcl_Obj *const *objv)       /* Parameter vector */
03090 {
03091     Tcl_Obj *valuePtr;
03092     OldMathFuncData *dataPtr = clientData;
03093     Tcl_Value funcResult, *args;
03094     int result;
03095     int j, k;
03096     double d;
03097 
03098     /*
03099      * Check argument count.
03100      */
03101 
03102     if (objc != dataPtr->numArgs + 1) {
03103         MathFuncWrongNumArgs(interp, dataPtr->numArgs+1, objc, objv);
03104         return TCL_ERROR;
03105     }
03106 
03107     /*
03108      * Convert arguments from Tcl_Obj's to Tcl_Value's.
03109      */
03110 
03111     args = (Tcl_Value *)
03112             TclStackAlloc(interp, dataPtr->numArgs * sizeof(Tcl_Value));
03113     for (j = 1, k = 0; j < objc; ++j, ++k) {
03114 
03115         /* TODO: Convert to TclGetNumberFromObj() ? */
03116         valuePtr = objv[j];
03117         result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d);
03118 #ifdef ACCEPT_NAN
03119         if ((result != TCL_OK) && (valuePtr->typePtr == &tclDoubleType)) {
03120             d = valuePtr->internalRep.doubleValue;
03121             result = TCL_OK;
03122         }
03123 #endif
03124         if (result != TCL_OK) {
03125             /*
03126              * We have a non-numeric argument.
03127              */
03128 
03129             Tcl_SetObjResult(interp, Tcl_NewStringObj(
03130                     "argument to math function didn't have numeric value",-1));
03131             TclCheckBadOctal(interp, Tcl_GetString(valuePtr));
03132             TclStackFree(interp, args);
03133             return TCL_ERROR;
03134         }
03135 
03136         /*
03137          * Copy the object's numeric value to the argument record, converting
03138          * it if necessary.
03139          *
03140          * NOTE: no bignum support; use the new mathfunc interface for that.
03141          */
03142 
03143         args[k].type = dataPtr->argTypes[k];
03144         switch (args[k].type) {
03145         case TCL_EITHER:
03146             if (Tcl_GetLongFromObj(NULL, valuePtr, &(args[k].intValue))
03147                     == TCL_OK) {
03148                 args[k].type = TCL_INT;
03149                 break;
03150             }
03151             if (Tcl_GetWideIntFromObj(interp, valuePtr, &(args[k].wideValue))
03152                     == TCL_OK) {
03153                 args[k].type = TCL_WIDE_INT;
03154                 break;
03155             }
03156             args[k].type = TCL_DOUBLE;
03157             /* FALLTHROUGH */
03158 
03159         case TCL_DOUBLE:
03160             args[k].doubleValue = d;
03161             break;
03162         case TCL_INT:
03163             if (ExprIntFunc(NULL, interp, 2, &(objv[j-1])) != TCL_OK) {
03164                 TclStackFree(interp, args);
03165                 return TCL_ERROR;
03166             }
03167             valuePtr = Tcl_GetObjResult(interp);
03168             Tcl_GetLongFromObj(NULL, valuePtr, &(args[k].intValue));
03169             Tcl_ResetResult(interp);
03170             break;
03171         case TCL_WIDE_INT:
03172             if (ExprWideFunc(NULL, interp, 2, &(objv[j-1])) != TCL_OK) {
03173                 TclStackFree(interp, args);
03174                 return TCL_ERROR;
03175             }
03176             valuePtr = Tcl_GetObjResult(interp);
03177             Tcl_GetWideIntFromObj(NULL, valuePtr, &(args[k].wideValue));
03178             Tcl_ResetResult(interp);
03179             break;
03180         }
03181     }
03182 
03183     /*
03184      * Call the function.
03185      */
03186 
03187     errno = 0;
03188     result = (*dataPtr->proc)(dataPtr->clientData, interp, args, &funcResult);
03189     TclStackFree(interp, args);
03190     if (result != TCL_OK) {
03191         return result;
03192     }
03193 
03194     /*
03195      * Return the result of the call.
03196      */
03197 
03198     if (funcResult.type == TCL_INT) {
03199         TclNewLongObj(valuePtr, funcResult.intValue);
03200     } else if (funcResult.type == TCL_WIDE_INT) {
03201         valuePtr = Tcl_NewWideIntObj(funcResult.wideValue);
03202     } else {
03203         return CheckDoubleResult(interp, funcResult.doubleValue);
03204     }
03205     Tcl_SetObjResult(interp, valuePtr);
03206     return TCL_OK;
03207 }
03208 
03209 /*
03210  *----------------------------------------------------------------------
03211  *
03212  * OldMathFuncDeleteProc --
03213  *
03214  *      Cleans up after deleting a math function registered with
03215  *      Tcl_CreateMathFunc
03216  *
03217  * Results:
03218  *      None.
03219  *
03220  * Side effects:
03221  *      Frees allocated memory.
03222  *
03223  *----------------------------------------------------------------------
03224  */
03225 
03226 static void
03227 OldMathFuncDeleteProc(
03228      ClientData clientData)
03229 {
03230     OldMathFuncData *dataPtr = clientData;
03231 
03232     ckfree((void *) dataPtr->argTypes);
03233     ckfree((void *) dataPtr);
03234 }
03235 
03236 /*
03237  *----------------------------------------------------------------------
03238  *
03239  * Tcl_GetMathFuncInfo --
03240  *
03241  *      Discovers how a particular math function was created in a given
03242  *      interpreter.
03243  *
03244  * Results:
03245  *      TCL_OK if it succeeds, TCL_ERROR else (leaving an error message in the
03246  *      interpreter result if that happens.)
03247  *
03248  * Side effects:
03249  *      If this function succeeds, the variables pointed to by the numArgsPtr
03250  *      and argTypePtr arguments will be updated to detail the arguments
03251  *      allowed by the function. The variable pointed to by the procPtr
03252  *      argument will be set to NULL if the function is a builtin function,
03253  *      and will be set to the address of the C function used to implement the
03254  *      math function otherwise (in which case the variable pointed to by the
03255  *      clientDataPtr argument will also be updated.)
03256  *
03257  *----------------------------------------------------------------------
03258  */
03259 
03260 int
03261 Tcl_GetMathFuncInfo(
03262     Tcl_Interp *interp,
03263     const char *name,
03264     int *numArgsPtr,
03265     Tcl_ValueType **argTypesPtr,
03266     Tcl_MathProc **procPtr,
03267     ClientData *clientDataPtr)
03268 {
03269     Tcl_Obj *cmdNameObj;
03270     Command *cmdPtr;
03271 
03272     /*
03273      * Get the command that implements the math function.
03274      */
03275 
03276     TclNewLiteralStringObj(cmdNameObj, "tcl::mathfunc::");
03277     Tcl_AppendToObj(cmdNameObj, name, -1);
03278     Tcl_IncrRefCount(cmdNameObj);
03279     cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdNameObj);
03280     Tcl_DecrRefCount(cmdNameObj);
03281 
03282     /*
03283      * Report unknown functions.
03284      */
03285 
03286     if (cmdPtr == NULL) {
03287         Tcl_Obj *message;
03288 
03289         TclNewLiteralStringObj(message, "unknown math function \"");
03290         Tcl_AppendToObj(message, name, -1);
03291         Tcl_AppendToObj(message, "\"", 1);
03292         Tcl_SetObjResult(interp, message);
03293         *numArgsPtr = -1;
03294         *argTypesPtr = NULL;
03295         *procPtr = NULL;
03296         *clientDataPtr = NULL;
03297         return TCL_ERROR;
03298     }
03299 
03300     /*
03301      * Retrieve function info for user defined functions; return dummy
03302      * information for builtins.
03303      */
03304 
03305     if (cmdPtr->objProc == &OldMathFuncProc) {
03306         OldMathFuncData *dataPtr = cmdPtr->clientData;
03307 
03308         *procPtr = dataPtr->proc;
03309         *numArgsPtr = dataPtr->numArgs;
03310         *argTypesPtr = dataPtr->argTypes;
03311         *clientDataPtr = dataPtr->clientData;
03312     } else {
03313         *procPtr = NULL;
03314         *numArgsPtr = -1;
03315         *argTypesPtr = NULL;
03316         *procPtr = NULL;
03317         *clientDataPtr = NULL;
03318     }
03319     return TCL_OK;
03320 }
03321 
03322 /*
03323  *----------------------------------------------------------------------
03324  *
03325  * Tcl_ListMathFuncs --
03326  *
03327  *      Produces a list of all the math functions defined in a given
03328  *      interpreter.
03329  *
03330  * Results:
03331  *      A pointer to a Tcl_Obj structure with a reference count of zero, or
03332  *      NULL in the case of an error (in which case a suitable error message
03333  *      will be left in the interpreter result.)
03334  *
03335  * Side effects:
03336  *      None.
03337  *
03338  *----------------------------------------------------------------------
03339  */
03340 
03341 Tcl_Obj *
03342 Tcl_ListMathFuncs(
03343     Tcl_Interp *interp,
03344     const char *pattern)
03345 {
03346     Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
03347     Namespace *nsPtr;
03348     Namespace *dummy1NsPtr;
03349     Namespace *dummy2NsPtr;
03350     const char *dummyNamePtr;
03351     Tcl_Obj *result = Tcl_NewObj();
03352 
03353     TclGetNamespaceForQualName(interp, "::tcl::mathfunc",
03354             globalNsPtr, TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY,
03355             &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &dummyNamePtr);
03356     if (nsPtr == NULL) {
03357         return result;
03358     }
03359 
03360     if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
03361         if (Tcl_FindHashEntry(&nsPtr->cmdTable, pattern) != NULL) {
03362             Tcl_ListObjAppendElement(NULL, result,
03363                     Tcl_NewStringObj(pattern, -1));
03364         }
03365     } else {
03366         Tcl_HashSearch cmdHashSearch;
03367         Tcl_HashEntry *cmdHashEntry =
03368                 Tcl_FirstHashEntry(&nsPtr->cmdTable,&cmdHashSearch);
03369 
03370         for (; cmdHashEntry != NULL;
03371                 cmdHashEntry = Tcl_NextHashEntry(&cmdHashSearch)) {
03372             const char *cmdNamePtr =
03373                     Tcl_GetHashKey(&nsPtr->cmdTable, cmdHashEntry);
03374 
03375             if (pattern == NULL || Tcl_StringMatch(cmdNamePtr, pattern)) {
03376                 Tcl_ListObjAppendElement(NULL, result,
03377                         Tcl_NewStringObj(cmdNamePtr, -1));
03378             }
03379         }
03380     }
03381     return result;
03382 }
03383 
03384 /*
03385  *----------------------------------------------------------------------
03386  *
03387  * TclInterpReady --
03388  *
03389  *      Check if an interpreter is ready to eval commands or scripts, i.e., if
03390  *      it was not deleted and if the nesting level is not too high.
03391  *
03392  * Results:
03393  *      The return value is TCL_OK if it the interpreter is ready, TCL_ERROR
03394  *      otherwise.
03395  *
03396  * Side effects:
03397  *      The interpreters object and string results are cleared.
03398  *
03399  *----------------------------------------------------------------------
03400  */
03401 
03402 int
03403 TclInterpReady(
03404     Tcl_Interp *interp)
03405 {
03406     int localInt; /* used for checking the stack */
03407     register Interp *iPtr = (Interp *) interp;
03408 
03409     /*
03410      * Reset both the interpreter's string and object results and clear out
03411      * any previous error information.
03412      */
03413 
03414     Tcl_ResetResult(interp);
03415 
03416     /*
03417      * If the interpreter has been deleted, return an error.
03418      */
03419 
03420     if (iPtr->flags & DELETED) {
03421         Tcl_ResetResult(interp);
03422         Tcl_AppendResult(interp,
03423                 "attempt to call eval in deleted interpreter", NULL);
03424         Tcl_SetErrorCode(interp, "TCL", "IDELETE",
03425                 "attempt to call eval in deleted interpreter", NULL);
03426         return TCL_ERROR;
03427     }
03428 
03429     /*
03430      * Check depth of nested calls to Tcl_Eval: if this gets too large, it's
03431      * probably because of an infinite loop somewhere.
03432      */
03433 
03434     if (((iPtr->numLevels) <= iPtr->maxNestingDepth)
03435             && CheckCStack(iPtr, &localInt)) {
03436         return TCL_OK;
03437     }
03438 
03439     if (!CheckCStack(iPtr, &localInt)) {
03440         Tcl_AppendResult(interp,
03441                 "out of stack space (infinite loop?)", NULL);
03442     } else {
03443         Tcl_AppendResult(interp,
03444                 "too many nested evaluations (infinite loop?)", NULL);
03445     }
03446     return TCL_ERROR;
03447 }
03448 
03449 /*
03450  *----------------------------------------------------------------------
03451  *
03452  * TclEvalObjvInternal
03453  *
03454  *      This function evaluates a Tcl command that has already been parsed
03455  *      into words, with one Tcl_Obj holding each word. The caller is
03456  *      responsible for managing the iPtr->numLevels.
03457  *
03458  *      TclEvalObjvInternal is the backend for Tcl_EvalObjv, the bytecode
03459  *      engine also calls it directly.
03460  *
03461  * Results:
03462  *      The return value is a standard Tcl completion code such as TCL_OK or
03463  *      TCL_ERROR. A result or error message is left in interp's result. If an
03464  *      error occurs, this function does NOT add any information to the
03465  *      errorInfo variable.
03466  *
03467  * Side effects:
03468  *      Depends on the command.
03469  *
03470  *----------------------------------------------------------------------
03471  */
03472 
03473 int
03474 TclEvalObjvInternal(
03475     Tcl_Interp *interp,         /* Interpreter in which to evaluate the
03476                                  * command. Also used for error reporting. */
03477     int objc,                   /* Number of words in command. */
03478     Tcl_Obj *const objv[],      /* An array of pointers to objects that are
03479                                  * the words that make up the command. */
03480     const char *command,        /* Points to the beginning of the string
03481                                  * representation of the command; this is used
03482                                  * for traces. NULL if the string
03483                                  * representation of the command is unknown is
03484                                  * to be generated from (objc,objv), -1 if it
03485                                  * is to be generated from bytecode
03486                                  * source. This is only needed the traces. */
03487     int length,                 /* Number of bytes in command; if -1, all
03488                                  * characters up to the first null byte are
03489                                  * used. */
03490     int flags)                  /* Collection of OR-ed bits that control the
03491                                  * evaluation of the script. Only
03492                                  * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
03493                                  * currently supported. */
03494 {
03495     Command *cmdPtr;
03496     Interp *iPtr = (Interp *) interp;
03497     Tcl_Obj **newObjv;
03498     int i;
03499     CallFrame *savedVarFramePtr = NULL;
03500     CallFrame *varFramePtr = iPtr->varFramePtr;
03501     int code = TCL_OK;
03502     int traceCode = TCL_OK;
03503     int checkTraces = 1, traced;
03504     Namespace *savedNsPtr = NULL;
03505     Namespace *lookupNsPtr = iPtr->lookupNsPtr;
03506     Tcl_Obj *commandPtr = NULL;
03507 
03508     if (TclInterpReady(interp) == TCL_ERROR) {
03509         return TCL_ERROR;
03510     }
03511 
03512     if (objc == 0) {
03513         return TCL_OK;
03514     }
03515 
03516     /*
03517      * If any execution traces rename or delete the current command, we may
03518      * need (at most) two passes here.
03519      */
03520 
03521   reparseBecauseOfTraces:
03522 
03523     /*
03524      * Configure evaluation context to match the requested flags.
03525      */
03526 
03527     if (flags) {
03528         if (flags & TCL_EVAL_INVOKE) {
03529             savedNsPtr = varFramePtr->nsPtr;
03530             if (lookupNsPtr) {
03531                 varFramePtr->nsPtr = lookupNsPtr;
03532                 iPtr->lookupNsPtr = NULL;
03533             } else {
03534                 varFramePtr->nsPtr = iPtr->globalNsPtr;
03535             }
03536         } else if ((flags & TCL_EVAL_GLOBAL)
03537                 && (varFramePtr != iPtr->rootFramePtr) && !savedVarFramePtr) {
03538             varFramePtr = iPtr->rootFramePtr;
03539             savedVarFramePtr = iPtr->varFramePtr;
03540             iPtr->varFramePtr = varFramePtr;
03541         }
03542     }
03543 
03544     /*
03545      * Find the function to execute this command. If there isn't one, then see
03546      * if there is an unknown command handler registered for this namespace.
03547      * If so, create a new word array with the handler as the first words and
03548      * the original command words as arguments. Then call ourselves
03549      * recursively to execute it.
03550      */
03551 
03552     cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
03553     if (!cmdPtr) {
03554         goto notFound;
03555     }
03556 
03557     if (savedNsPtr) {
03558         varFramePtr->nsPtr = savedNsPtr;
03559     } else if (iPtr->ensembleRewrite.sourceObjs) {
03560         /*
03561          * TCL_EVAL_INVOKE was not set: clear rewrite rules
03562          */
03563 
03564         iPtr->ensembleRewrite.sourceObjs = NULL;
03565     }
03566 
03567     /*
03568      * Call trace functions if needed.
03569      */
03570 
03571     traced = (iPtr->tracePtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES));
03572     if (traced && checkTraces) {
03573         int cmdEpoch = cmdPtr->cmdEpoch;
03574         int newEpoch;
03575 
03576         /*
03577          * Insure that we have a correct nul-terminated command string for the
03578          * trace code.
03579          */
03580 
03581         commandPtr = GetCommandSource(iPtr, command, length, objc, objv);
03582         command = TclGetStringFromObj(commandPtr, &length);
03583 
03584         /*
03585          * Execute any command or execution traces. Note that we bump up the
03586          * command's reference count for the duration of the calling of the
03587          * traces so that the structure doesn't go away underneath our feet.
03588          */
03589 
03590         cmdPtr->refCount++;
03591         if (iPtr->tracePtr && (traceCode == TCL_OK)) {
03592             traceCode = TclCheckInterpTraces(interp, command, length,
03593                     cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
03594         }
03595         if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
03596             traceCode = TclCheckExecutionTraces(interp, command, length,
03597                     cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
03598         }
03599         newEpoch = cmdPtr->cmdEpoch;
03600         TclCleanupCommandMacro(cmdPtr);
03601 
03602         /*
03603          * If the traces modified/deleted the command or any existing traces,
03604          * they will update the command's epoch. When that happens, set
03605          * checkTraces is set to 0 to prevent the re-calling of traces (and
03606          * any possible infinite loop) and we go back to re-find the command
03607          * implementation.
03608          */
03609 
03610         if (cmdEpoch != newEpoch) {
03611             checkTraces = 0;
03612             goto reparseBecauseOfTraces;
03613         }
03614     }
03615 
03616     if (TCL_DTRACE_CMD_ARGS_ENABLED()) {
03617         char *a[10];
03618         int i = 0;
03619 
03620         while (i < 10) {
03621             a[i] = i < objc ? TclGetString(objv[i]) : NULL; i++;
03622         }
03623         TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
03624                 a[8], a[9]);
03625     }
03626     if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) {
03627         Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
03628         char *a[4]; int i[2];
03629 
03630         TclDTraceInfo(info, a, i);
03631         TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1]);
03632         TclDecrRefCount(info);
03633     }
03634 
03635     /*
03636      * Finally, invoke the command's Tcl_ObjCmdProc.
03637      */
03638 
03639     cmdPtr->refCount++;
03640     iPtr->cmdCount++;
03641     if (code == TCL_OK && traceCode == TCL_OK
03642             && !TclLimitExceeded(iPtr->limit)) {
03643         if (TCL_DTRACE_CMD_ENTRY_ENABLED()) {
03644             TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1,
03645                     (Tcl_Obj **)(objv + 1));
03646         }
03647         code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
03648         if (TCL_DTRACE_CMD_RETURN_ENABLED()) {
03649             TCL_DTRACE_CMD_RETURN(TclGetString(objv[0]), code);
03650         }
03651     }
03652 
03653     if (TclAsyncReady(iPtr)) {
03654         code = Tcl_AsyncInvoke(interp, code);
03655     }
03656     if (code == TCL_OK && TclLimitReady(iPtr->limit)) {
03657         code = Tcl_LimitCheck(interp);
03658     }
03659 
03660     /*
03661      * Call 'leave' command traces
03662      */
03663 
03664     if (traced) {
03665         if (!(cmdPtr->flags & CMD_IS_DELETED)) {
03666             if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && traceCode == TCL_OK){
03667                 traceCode = TclCheckExecutionTraces(interp, command, length,
03668                         cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
03669             }
03670             if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
03671                 traceCode = TclCheckInterpTraces(interp, command, length,
03672                         cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
03673             }
03674         }
03675 
03676         /*
03677          * If one of the trace invocation resulted in error, then change the
03678          * result code accordingly. Note, that the interp->result should
03679          * already be set correctly by the call to TraceExecutionProc.
03680          */
03681 
03682         if (traceCode != TCL_OK) {
03683             code = traceCode;
03684         }
03685         if (commandPtr) {
03686             Tcl_DecrRefCount(commandPtr);
03687         }
03688     }
03689 
03690     /*
03691      * Decrement the reference count of cmdPtr and deallocate it if it has
03692      * dropped to zero.
03693      */
03694 
03695     TclCleanupCommandMacro(cmdPtr);
03696 
03697     /*
03698      * If the interpreter has a non-empty string result, the result object is
03699      * either empty or stale because some function set interp->result
03700      * directly. If so, move the string result to the result object, then
03701      * reset the string result.
03702      */
03703 
03704     if (*(iPtr->result) != 0) {
03705         (void) Tcl_GetObjResult(interp);
03706     }
03707 
03708     if (TCL_DTRACE_CMD_RESULT_ENABLED()) {
03709         Tcl_Obj *r;
03710 
03711         r = Tcl_GetObjResult(interp);
03712         TCL_DTRACE_CMD_RESULT(TclGetString(objv[0]), code, TclGetString(r),r);
03713     }
03714 
03715   done:
03716     if (savedVarFramePtr) {
03717         iPtr->varFramePtr = savedVarFramePtr;
03718     }
03719     return code;
03720 
03721   notFound:
03722     {
03723         Namespace *currNsPtr = NULL;    /* Used to check for and invoke any
03724                                          * registered unknown command handler
03725                                          * for the current namespace (TIP
03726                                          * 181). */
03727         int newObjc, handlerObjc;
03728         Tcl_Obj **handlerObjv;
03729 
03730         currNsPtr = varFramePtr->nsPtr;
03731         if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) {
03732             currNsPtr = iPtr->globalNsPtr;
03733             if (currNsPtr == NULL) {
03734                 Tcl_Panic("TclEvalObjvInternal: NULL global namespace pointer");
03735             }
03736         }
03737 
03738         /*
03739          * Check to see if the resolution namespace has lost its unknown
03740          * handler. If so, reset it to "::unknown".
03741          */
03742 
03743         if (currNsPtr->unknownHandlerPtr == NULL) {
03744             TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown");
03745             Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr);
03746         }
03747 
03748         /*
03749          * Get the list of words for the unknown handler and allocate enough
03750          * space to hold both the handler prefix and all words of the command
03751          * invokation itself.
03752          */
03753 
03754         Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr,
03755                 &handlerObjc, &handlerObjv);
03756         newObjc = objc + handlerObjc;
03757         newObjv = (Tcl_Obj **) TclStackAlloc(interp,
03758                 (int) sizeof(Tcl_Obj *) * newObjc);
03759 
03760         /*
03761          * Copy command prefix from unknown handler and add on the real
03762          * command's full argument list. Note that we only use memcpy() once
03763          * because we have to increment the reference count of all the handler
03764          * arguments anyway.
03765          */
03766 
03767         for (i = 0; i < handlerObjc; ++i) {
03768             newObjv[i] = handlerObjv[i];
03769             Tcl_IncrRefCount(newObjv[i]);
03770         }
03771         memcpy(newObjv+handlerObjc, objv, sizeof(Tcl_Obj *) * (unsigned)objc);
03772 
03773         /*
03774          * Look up and invoke the handler (by recursive call to this
03775          * function). If there is no handler at all, instead of doing the
03776          * recursive call we just generate a generic error message; it would
03777          * be an infinite-recursion nightmare otherwise.
03778          */
03779 
03780         cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
03781         if (cmdPtr == NULL) {
03782             Tcl_AppendResult(interp, "invalid command name \"",
03783                     TclGetString(objv[0]), "\"", NULL);
03784             code = TCL_ERROR;
03785         } else {
03786             iPtr->numLevels++;
03787             code = TclEvalObjvInternal(interp, newObjc, newObjv, command,
03788                     length, 0);
03789             iPtr->numLevels--;
03790         }
03791 
03792         /*
03793          * Release any resources we locked and allocated during the handler
03794          * call.
03795          */
03796 
03797         for (i = 0; i < handlerObjc; ++i) {
03798             Tcl_DecrRefCount(newObjv[i]);
03799         }
03800         TclStackFree(interp, newObjv);
03801         if (savedNsPtr) {
03802             varFramePtr->nsPtr = savedNsPtr;
03803         }
03804         goto done;
03805     }
03806 }
03807 
03808 /*
03809  *----------------------------------------------------------------------
03810  *
03811  * Tcl_EvalObjv --
03812  *
03813  *      This function evaluates a Tcl command that has already been parsed
03814  *      into words, with one Tcl_Obj holding each word.
03815  *
03816  * Results:
03817  *      The return value is a standard Tcl completion code such as TCL_OK or
03818  *      TCL_ERROR. A result or error message is left in interp's result.
03819  *
03820  * Side effects:
03821  *      Depends on the command.
03822  *
03823  *----------------------------------------------------------------------
03824  */
03825 
03826 int
03827 Tcl_EvalObjv(
03828     Tcl_Interp *interp,         /* Interpreter in which to evaluate the
03829                                  * command. Also used for error reporting. */
03830     int objc,                   /* Number of words in command. */
03831     Tcl_Obj *const objv[],      /* An array of pointers to objects that are
03832                                  * the words that make up the command. */
03833     int flags)                  /* Collection of OR-ed bits that control the
03834                                  * evaluation of the script. Only
03835                                  * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
03836                                  * currently supported. */
03837 {
03838     Interp *iPtr = (Interp *) interp;
03839     int code = TCL_OK;
03840 
03841     iPtr->numLevels++;
03842     code = TclEvalObjvInternal(interp, objc, objv, NULL, 0, flags);
03843     iPtr->numLevels--;
03844 
03845     if (code == TCL_OK) {
03846         return code;
03847     } else {
03848         int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
03849 
03850         /*
03851          * If we are again at the top level, process any unusual return code
03852          * returned by the evaluated code.
03853          */
03854 
03855         if (iPtr->numLevels == 0) {
03856             if (code == TCL_RETURN) {
03857                 code = TclUpdateReturnInfo(iPtr);
03858             }
03859             if ((code != TCL_ERROR) && !allowExceptions) {
03860                 ProcessUnexpectedResult(interp, code);
03861                 code = TCL_ERROR;
03862             }
03863         }
03864 
03865         if ((code == TCL_ERROR) && !(flags & TCL_EVAL_INVOKE)) {
03866             /*
03867              * If there was an error, a command string will be needed for the
03868              * error log: generate it now. Do not worry too much about doing
03869              * it expensively.
03870              */
03871 
03872             Tcl_Obj *listPtr;
03873             char *cmdString;
03874             int cmdLen;
03875 
03876             listPtr = Tcl_NewListObj(objc, objv);
03877             cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen);
03878             Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
03879             Tcl_DecrRefCount(listPtr);
03880         }
03881 
03882         return code;
03883     }
03884 }
03885 
03886 /*
03887  *----------------------------------------------------------------------
03888  *
03889  * Tcl_EvalTokensStandard --
03890  *
03891  *      Given an array of tokens parsed from a Tcl command (e.g., the tokens
03892  *      that make up a word or the index for an array variable) this function
03893  *      evaluates the tokens and concatenates their values to form a single
03894  *      result value.
03895  *
03896  * Results:
03897  *      The return value is a standard Tcl completion code such as TCL_OK or
03898  *      TCL_ERROR. A result or error message is left in interp's result.
03899  *
03900  * Side effects:
03901  *      Depends on the array of tokens being evaled.
03902  *
03903  *----------------------------------------------------------------------
03904  */
03905 
03906 int
03907 Tcl_EvalTokensStandard(
03908     Tcl_Interp *interp,         /* Interpreter in which to lookup variables,
03909                                  * execute nested commands, and report
03910                                  * errors. */
03911     Tcl_Token *tokenPtr,        /* Pointer to first in an array of tokens to
03912                                  * evaluate and concatenate. */
03913     int count)                  /* Number of tokens to consider at tokenPtr.
03914                                  * Must be at least 1. */
03915 {
03916     return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1);
03917 }
03918 
03919 /*
03920  *----------------------------------------------------------------------
03921  *
03922  * Tcl_EvalTokens --
03923  *
03924  *      Given an array of tokens parsed from a Tcl command (e.g., the tokens
03925  *      that make up a word or the index for an array variable) this function
03926  *      evaluates the tokens and concatenates their values to form a single
03927  *      result value.
03928  *
03929  * Results:
03930  *      The return value is a pointer to a newly allocated Tcl_Obj containing
03931  *      the value of the array of tokens. The reference count of the returned
03932  *      object has been incremented. If an error occurs in evaluating the
03933  *      tokens then a NULL value is returned and an error message is left in
03934  *      interp's result.
03935  *
03936  * Side effects:
03937  *      A new object is allocated to hold the result.
03938  *
03939  *----------------------------------------------------------------------
03940  *
03941  * This uses a non-standard return convention; its use is now deprecated. It
03942  * is a wrapper for the new function Tcl_EvalTokensStandard, and is not used
03943  * in the core any longer. It is only kept for backward compatibility.
03944  */
03945 
03946 Tcl_Obj *
03947 Tcl_EvalTokens(
03948     Tcl_Interp *interp,         /* Interpreter in which to lookup variables,
03949                                  * execute nested commands, and report
03950                                  * errors. */
03951     Tcl_Token *tokenPtr,        /* Pointer to first in an array of tokens to
03952                                  * evaluate and concatenate. */
03953     int count)                  /* Number of tokens to consider at tokenPtr.
03954                                  * Must be at least 1. */
03955 {
03956     Tcl_Obj *resPtr;
03957 
03958     if (Tcl_EvalTokensStandard(interp, tokenPtr, count) != TCL_OK) {
03959         return NULL;
03960     }
03961     resPtr = Tcl_GetObjResult(interp);
03962     Tcl_IncrRefCount(resPtr);
03963     Tcl_ResetResult(interp);
03964     return resPtr;
03965 }
03966 
03967 /*
03968  *----------------------------------------------------------------------
03969  *
03970  * Tcl_EvalEx, TclEvalEx --
03971  *
03972  *      This function evaluates a Tcl script without using the compiler or
03973  *      byte-code interpreter. It just parses the script, creates values for
03974  *      each word of each command, then calls EvalObjv to execute each
03975  *      command.
03976  *
03977  * Results:
03978  *      The return value is a standard Tcl completion code such as TCL_OK or
03979  *      TCL_ERROR. A result or error message is left in interp's result.
03980  *
03981  * Side effects:
03982  *      Depends on the script.
03983  *
03984  * TIP #280 : Keep public API, internally extended API.
03985  *----------------------------------------------------------------------
03986  */
03987 
03988 int
03989 Tcl_EvalEx(
03990     Tcl_Interp *interp,         /* Interpreter in which to evaluate the
03991                                  * script. Also used for error reporting. */
03992     const char *script,         /* First character of script to evaluate. */
03993     int numBytes,               /* Number of bytes in script. If < 0, the
03994                                  * script consists of all bytes up to the
03995                                  * first null character. */
03996     int flags)                  /* Collection of OR-ed bits that control the
03997                                  * evaluation of the script. Only
03998                                  * TCL_EVAL_GLOBAL is currently supported. */
03999 {
04000   return TclEvalEx(interp, script, numBytes, flags, 1);
04001 }
04002 
04003 int
04004 TclEvalEx(
04005     Tcl_Interp *interp,         /* Interpreter in which to evaluate the
04006                                  * script. Also used for error reporting. */
04007     const char *script,         /* First character of script to evaluate. */
04008     int numBytes,               /* Number of bytes in script. If < 0, the
04009                                  * script consists of all bytes up to the
04010                                  * first NUL character. */
04011     int flags,                  /* Collection of OR-ed bits that control the
04012                                  * evaluation of the script. Only
04013                                  * TCL_EVAL_GLOBAL is currently supported. */
04014     int line)                   /* The line the script starts on. */
04015 {
04016     Interp *iPtr = (Interp *) interp;
04017     const char *p, *next;
04018     const unsigned int minObjs = 20;
04019     Tcl_Obj **objv, **objvSpace;
04020     int *expand, *lines, *lineSpace;
04021     Tcl_Token *tokenPtr;
04022     int commandLength, bytesLeft, expandRequested, code = TCL_OK;
04023     CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
04024                                  * TCL_EVAL_GLOBAL was set. */
04025     int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
04026     int gotParse = 0;
04027     unsigned int i, objectsUsed = 0;
04028                                 /* These variables keep track of how much
04029                                  * state has been allocated while evaluating
04030                                  * the script, so that it can be freed
04031                                  * properly if an error occurs. */
04032     Tcl_Parse *parsePtr = (Tcl_Parse *)
04033             TclStackAlloc(interp, sizeof(Tcl_Parse));
04034     CmdFrame *eeFramePtr = (CmdFrame *)
04035             TclStackAlloc(interp, sizeof(CmdFrame));
04036     Tcl_Obj **stackObjArray = (Tcl_Obj **)
04037             TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
04038     int *expandStack = (int *) TclStackAlloc(interp, minObjs * sizeof(int));
04039     int *linesStack = (int *) TclStackAlloc(interp, minObjs * sizeof(int));
04040                                 /* TIP #280 Structures for tracking of command
04041                                  * locations. */
04042 
04043     if (numBytes < 0) {
04044         numBytes = strlen(script);
04045     }
04046     Tcl_ResetResult(interp);
04047 
04048     savedVarFramePtr = iPtr->varFramePtr;
04049     if (flags & TCL_EVAL_GLOBAL) {
04050         iPtr->varFramePtr = iPtr->rootFramePtr;
04051     }
04052 
04053     /*
04054      * Each iteration through the following loop parses the next command from
04055      * the script and then executes it.
04056      */
04057 
04058     objv = objvSpace = stackObjArray;
04059     lines = lineSpace = linesStack;
04060     expand = expandStack;
04061     p = script;
04062     bytesLeft = numBytes;
04063 
04064     /*
04065      * TIP #280 Initialize tracking. Do not push on the frame stack yet.
04066      *
04067      * We may cont. counting based on a specific context (CTX), or open a new
04068      * context, either for a sourced script, or 'eval'. For sourced files we
04069      * always have a path object, even if nothing was specified in the interp
04070      * itself. That makes code using it simpler as NULL checks can be left
04071      * out. Sourced file without path in the 'scriptFile' is possible during
04072      * Tcl initialization.
04073      */
04074 
04075     if (iPtr->evalFlags & TCL_EVAL_CTX) {
04076         /*
04077          * Path information comes out of the context.
04078          */
04079 
04080         eeFramePtr->type = TCL_LOCATION_SOURCE;
04081         eeFramePtr->data.eval.path = iPtr->invokeCmdFramePtr->data.eval.path;
04082         Tcl_IncrRefCount(eeFramePtr->data.eval.path);
04083     } else if (iPtr->evalFlags & TCL_EVAL_FILE) {
04084         /*
04085          * Set up for a sourced file.
04086          */
04087 
04088         eeFramePtr->type = TCL_LOCATION_SOURCE;
04089 
04090         if (iPtr->scriptFile) {
04091             /*
04092              * Normalization here, to have the correct pwd. Should have
04093              * negligible impact on performance, as the norm should have been
04094              * done already by the 'source' invoking us, and it caches the
04095              * result.
04096              */
04097 
04098             Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile);
04099 
04100             if (norm == NULL) {
04101                 /*
04102                  * Error message in the interp result.
04103                  */
04104                 code = TCL_ERROR;
04105                 goto error;
04106             }
04107             eeFramePtr->data.eval.path = norm;
04108             Tcl_IncrRefCount(eeFramePtr->data.eval.path);
04109         } else {
04110             TclNewLiteralStringObj(eeFramePtr->data.eval.path, "");
04111         }
04112     } else {
04113         /*
04114          * Set up for plain eval.
04115          */
04116 
04117         eeFramePtr->type = TCL_LOCATION_EVAL;
04118         eeFramePtr->data.eval.path = NULL;
04119     }
04120 
04121     eeFramePtr->level = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level + 1 : 1;
04122     eeFramePtr->framePtr = iPtr->framePtr;
04123     eeFramePtr->nextPtr = iPtr->cmdFramePtr;
04124     eeFramePtr->nline = 0;
04125     eeFramePtr->line = NULL;
04126 
04127     iPtr->evalFlags = 0;
04128     do {
04129         if (Tcl_ParseCommand(interp, p, bytesLeft, 0, parsePtr) != TCL_OK) {
04130             code = TCL_ERROR;
04131             goto error;
04132         }
04133 
04134         /*
04135          * TIP #280 Track lines. The parser may have skipped text till it
04136          * found the command we are now at. We have to count the lines in this
04137          * block.
04138          */
04139 
04140         TclAdvanceLines(&line, p, parsePtr->commandStart);
04141 
04142         gotParse = 1;
04143         if (parsePtr->numWords > 0) {
04144             /*
04145              * TIP #280. Track lines within the words of the current command.
04146              */
04147 
04148             int wordLine  = line;
04149             const char *wordStart = parsePtr->commandStart;
04150 
04151             /*
04152              * Generate an array of objects for the words of the command.
04153              */
04154 
04155             unsigned int objectsNeeded = 0;
04156             unsigned int numWords = parsePtr->numWords;
04157 
04158             if (numWords > minObjs) {
04159                 expand = (int *) ckalloc(numWords * sizeof(int));
04160                 objvSpace = (Tcl_Obj **)
04161                         ckalloc(numWords * sizeof(Tcl_Obj *));
04162                 lineSpace = (int *) ckalloc(numWords * sizeof(int));
04163             }
04164             expandRequested = 0;
04165             objv = objvSpace;
04166             lines = lineSpace;
04167 
04168             for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
04169                     objectsUsed < numWords;
04170                     objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {
04171                 /*
04172                  * TIP #280. Track lines to current word. Save the information
04173                  * on a per-word basis, signaling dynamic words as needed.
04174                  * Make the information available to the recursively called
04175                  * evaluator as well, including the type of context (source
04176                  * vs. eval).
04177                  */
04178 
04179                 TclAdvanceLines(&wordLine, wordStart, tokenPtr->start);
04180                 wordStart = tokenPtr->start;
04181 
04182                 lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL)
04183                         ? wordLine : -1;
04184 
04185                 if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
04186                     iPtr->evalFlags |= TCL_EVAL_FILE;
04187                 }
04188 
04189                 code = TclSubstTokens(interp, tokenPtr+1,
04190                         tokenPtr->numComponents, NULL, wordLine);
04191 
04192                 iPtr->evalFlags = 0;
04193 
04194                 if (code != TCL_OK) {
04195                     goto error;
04196                 }
04197                 objv[objectsUsed] = Tcl_GetObjResult(interp);
04198                 Tcl_IncrRefCount(objv[objectsUsed]);
04199                 if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
04200                     int numElements;
04201 
04202                     code = TclListObjLength(interp, objv[objectsUsed],
04203                             &numElements);
04204                     if (code == TCL_ERROR) {
04205                         /*
04206                          * Attempt to expand a non-list.
04207                          */
04208 
04209                         Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
04210                                 "\n    (expanding word %d)", objectsUsed));
04211                         Tcl_DecrRefCount(objv[objectsUsed]);
04212                         goto error;
04213                     }
04214                     expandRequested = 1;
04215                     expand[objectsUsed] = 1;
04216 
04217                     objectsNeeded += (numElements ? numElements : 1);
04218                 } else {
04219                     expand[objectsUsed] = 0;
04220                     objectsNeeded++;
04221                 }
04222             } /* for loop */
04223             if (expandRequested) {
04224                 /*
04225                  * Some word expansion was requested. Check for objv resize.
04226                  */
04227 
04228                 Tcl_Obj **copy = objvSpace;
04229                 int *lcopy = lineSpace;
04230                 int wordIdx = numWords;
04231                 int objIdx = objectsNeeded - 1;
04232 
04233                 if ((numWords > minObjs) || (objectsNeeded >  minObjs)) {
04234                     objv = objvSpace = (Tcl_Obj **)
04235                             ckalloc(objectsNeeded * sizeof(Tcl_Obj *));
04236                     lines = lineSpace = (int *)
04237                             ckalloc(objectsNeeded * sizeof(int));
04238                 }
04239 
04240                 objectsUsed = 0;
04241                 while (wordIdx--) {
04242                     if (expand[wordIdx]) {
04243                         int numElements;
04244                         Tcl_Obj **elements, *temp = copy[wordIdx];
04245 
04246                         Tcl_ListObjGetElements(NULL, temp, &numElements,
04247                                 &elements);
04248                         objectsUsed += numElements;
04249                         while (numElements--) {
04250                             lines[objIdx] = -1;
04251                             objv[objIdx--] = elements[numElements];
04252                             Tcl_IncrRefCount(elements[numElements]);
04253                         }
04254                         Tcl_DecrRefCount(temp);
04255                     } else {
04256                         lines[objIdx] = lcopy[wordIdx];
04257                         objv[objIdx--] = copy[wordIdx];
04258                         objectsUsed++;
04259                     }
04260                 }
04261                 objv += objIdx+1;
04262 
04263                 if (copy != stackObjArray) {
04264                     ckfree((char *) copy);
04265                 }
04266                 if (lcopy != linesStack) {
04267                     ckfree((char *) lcopy);
04268                 }
04269             }
04270 
04271             /*
04272              * Execute the command and free the objects for its words.
04273              *
04274              * TIP #280: Remember the command itself for 'info frame'. We
04275              * shorten the visible command by one char to exclude the
04276              * termination character, if necessary. Here is where we put our
04277              * frame on the stack of frames too. _After_ the nested commands
04278              * have been executed.
04279              */
04280 
04281             eeFramePtr->cmd.str.cmd = parsePtr->commandStart;
04282             eeFramePtr->cmd.str.len = parsePtr->commandSize;
04283 
04284             if (parsePtr->term ==
04285                     parsePtr->commandStart + parsePtr->commandSize - 1) {
04286                 eeFramePtr->cmd.str.len--;
04287             }
04288 
04289             eeFramePtr->nline = objectsUsed;
04290             eeFramePtr->line = lines;
04291 
04292             iPtr->cmdFramePtr = eeFramePtr;
04293             iPtr->numLevels++;
04294             code = TclEvalObjvInternal(interp, objectsUsed, objv,
04295                     parsePtr->commandStart, parsePtr->commandSize, 0);
04296             iPtr->numLevels--;
04297             iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
04298 
04299             eeFramePtr->line = NULL;
04300             eeFramePtr->nline = 0;
04301 
04302             if (code != TCL_OK) {
04303                 goto error;
04304             }
04305             for (i = 0; i < objectsUsed; i++) {
04306                 Tcl_DecrRefCount(objv[i]);
04307             }
04308             objectsUsed = 0;
04309             if (objvSpace != stackObjArray) {
04310                 ckfree((char *) objvSpace);
04311                 objvSpace = stackObjArray;
04312                 ckfree((char *) lineSpace);
04313                 lineSpace = linesStack;
04314             }
04315 
04316             /*
04317              * Free expand separately since objvSpace could have been
04318              * reallocated above.
04319              */
04320 
04321             if (expand != expandStack) {
04322                 ckfree((char *) expand);
04323                 expand = expandStack;
04324             }
04325         }
04326 
04327         /*
04328          * Advance to the next command in the script.
04329          *
04330          * TIP #280 Track Lines. Now we track how many lines were in the
04331          * executed command.
04332          */
04333 
04334         next = parsePtr->commandStart + parsePtr->commandSize;
04335         bytesLeft -= next - p;
04336         p = next;
04337         TclAdvanceLines(&line, parsePtr->commandStart, p);
04338         Tcl_FreeParse(parsePtr);
04339         gotParse = 0;
04340     } while (bytesLeft > 0);
04341     iPtr->varFramePtr = savedVarFramePtr;
04342     code = TCL_OK;
04343     goto cleanup_return;
04344 
04345   error:
04346     /*
04347      * Generate and log various pieces of error information.
04348      */
04349 
04350     if (iPtr->numLevels == 0) {
04351         if (code == TCL_RETURN) {
04352             code = TclUpdateReturnInfo(iPtr);
04353         }
04354         if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) {
04355             ProcessUnexpectedResult(interp, code);
04356             code = TCL_ERROR;
04357         }
04358     }
04359     if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
04360         commandLength = parsePtr->commandSize;
04361         if (parsePtr->term == parsePtr->commandStart + commandLength - 1) {
04362             /*
04363              * The terminator character (such as ; or ]) of the command where
04364              * the error occurred is the last character in the parsed command.
04365              * Reduce the length by one so that the error message doesn't
04366              * include the terminator character.
04367              */
04368 
04369             commandLength -= 1;
04370         }
04371         Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
04372                 commandLength);
04373     }
04374     iPtr->flags &= ~ERR_ALREADY_LOGGED;
04375 
04376     /*
04377      * Then free resources that had been allocated to the command.
04378      */
04379 
04380     for (i = 0; i < objectsUsed; i++) {
04381         Tcl_DecrRefCount(objv[i]);
04382     }
04383     if (gotParse) {
04384         Tcl_FreeParse(parsePtr);
04385     }
04386     if (objvSpace != stackObjArray) {
04387         ckfree((char *) objvSpace);
04388         ckfree((char *) lineSpace);
04389     }
04390     if (expand != expandStack) {
04391         ckfree((char *) expand);
04392     }
04393     iPtr->varFramePtr = savedVarFramePtr;
04394 
04395  cleanup_return:
04396     /*
04397      * TIP #280. Release the local CmdFrame, and its contents.
04398      */
04399 
04400     if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
04401         Tcl_DecrRefCount(eeFramePtr->data.eval.path);
04402     }
04403     TclStackFree(interp, linesStack);
04404     TclStackFree(interp, expandStack);
04405     TclStackFree(interp, stackObjArray);
04406     TclStackFree(interp, eeFramePtr);
04407     TclStackFree(interp, parsePtr);
04408 
04409     return code;
04410 }
04411 
04412 /*
04413  *----------------------------------------------------------------------
04414  *
04415  * TclAdvanceLines --
04416  *
04417  *      This function is a helper which counts the number of lines in a block
04418  *      of text and advances an external counter.
04419  *
04420  * Results:
04421  *      None.
04422  *
04423  * Side effects:
04424  *      The specified counter is advanced per the number of lines found.
04425  *
04426  * TIP #280
04427  *----------------------------------------------------------------------
04428  */
04429 
04430 void
04431 TclAdvanceLines(
04432     int *line,
04433     const char *start,
04434     const char *end)
04435 {
04436     register const char *p;
04437 
04438     for (p = start; p < end; p++) {
04439         if (*p == '\n') {
04440             (*line)++;
04441         }
04442     }
04443 }
04444 
04445 /*
04446  *----------------------------------------------------------------------
04447  *
04448  * Tcl_Eval --
04449  *
04450  *      Execute a Tcl command in a string. This function executes the script
04451  *      directly, rather than compiling it to bytecodes. Before the arrival of
04452  *      the bytecode compiler in Tcl 8.0 Tcl_Eval was the main function used
04453  *      for executing Tcl commands, but nowadays it isn't used much.
04454  *
04455  * Results:
04456  *      The return value is one of the return codes defined in tcl.h (such as
04457  *      TCL_OK), and interp's result contains a value to supplement the return
04458  *      code. The value of the result will persist only until the next call to
04459  *      Tcl_Eval or Tcl_EvalObj: you must copy it or lose it!
04460  *
04461  * Side effects:
04462  *      Can be almost arbitrary, depending on the commands in the script.
04463  *
04464  *----------------------------------------------------------------------
04465  */
04466 
04467 int
04468 Tcl_Eval(
04469     Tcl_Interp *interp,         /* Token for command interpreter (returned by
04470                                  * previous call to Tcl_CreateInterp). */
04471     const char *script)         /* Pointer to TCL command to execute. */
04472 {
04473     int code = Tcl_EvalEx(interp, script, -1, 0);
04474 
04475     /*
04476      * For backwards compatibility with old C code that predates the object
04477      * system in Tcl 8.0, we have to mirror the object result back into the
04478      * string result (some callers may expect it there).
04479      */
04480 
04481     (void) Tcl_GetStringResult(interp);
04482     return code;
04483 }
04484 
04485 /*
04486  *----------------------------------------------------------------------
04487  *
04488  * Tcl_EvalObj, Tcl_GlobalEvalObj --
04489  *
04490  *      These functions are deprecated but we keep them around for backwards
04491  *      compatibility reasons.
04492  *
04493  * Results:
04494  *      See the functions they call.
04495  *
04496  * Side effects:
04497  *      See the functions they call.
04498  *
04499  *----------------------------------------------------------------------
04500  */
04501 
04502 #undef Tcl_EvalObj
04503 int
04504 Tcl_EvalObj(
04505     Tcl_Interp *interp,
04506     Tcl_Obj *objPtr)
04507 {
04508     return Tcl_EvalObjEx(interp, objPtr, 0);
04509 }
04510 
04511 #undef Tcl_GlobalEvalObj
04512 int
04513 Tcl_GlobalEvalObj(
04514     Tcl_Interp *interp,
04515     Tcl_Obj *objPtr)
04516 {
04517     return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
04518 }
04519 
04520 /*
04521  *----------------------------------------------------------------------
04522  *
04523  * Tcl_EvalObjEx, TclEvalObjEx --
04524  *
04525  *      Execute Tcl commands stored in a Tcl object. These commands are
04526  *      compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT is
04527  *      specified.
04528  *
04529  * Results:
04530  *      The return value is one of the return codes defined in tcl.h (such as
04531  *      TCL_OK), and the interpreter's result contains a value to supplement
04532  *      the return code.
04533  *
04534  * Side effects:
04535  *      The object is converted, if necessary, to a ByteCode object that holds
04536  *      the bytecode instructions for the commands. Executing the commands
04537  *      will almost certainly have side effects that depend on those commands.
04538  *
04539  * TIP #280 : Keep public API, internally extended API.
04540  *----------------------------------------------------------------------
04541  */
04542 
04543 int
04544 Tcl_EvalObjEx(
04545     Tcl_Interp *interp,         /* Token for command interpreter (returned by
04546                                  * a previous call to Tcl_CreateInterp). */
04547     register Tcl_Obj *objPtr,   /* Pointer to object containing commands to
04548                                  * execute. */
04549     int flags)                  /* Collection of OR-ed bits that control the
04550                                  * evaluation of the script. Supported values
04551                                  * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
04552 {
04553     return TclEvalObjEx(interp, objPtr, flags, NULL, 0);
04554 }
04555 
04556 int
04557 TclEvalObjEx(
04558     Tcl_Interp *interp,         /* Token for command interpreter (returned by
04559                                  * a previous call to Tcl_CreateInterp). */
04560     register Tcl_Obj *objPtr,   /* Pointer to object containing commands to
04561                                  * execute. */
04562     int flags,                  /* Collection of OR-ed bits that control the
04563                                  * evaluation of the script. Supported values
04564                                  * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
04565     const CmdFrame *invoker,    /* Frame of the command doing the eval. */
04566     int word)                   /* Index of the word which is in objPtr. */
04567 {
04568     register Interp *iPtr = (Interp *) interp;
04569     char *script;
04570     int numSrcBytes;
04571     int result;
04572     CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
04573                                  * TCL_EVAL_GLOBAL was set. */
04574     int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
04575 
04576     Tcl_IncrRefCount(objPtr);
04577 
04578     if (flags & TCL_EVAL_DIRECT) {
04579         /*
04580          * We're not supposed to use the compiler or byte-code interpreter.
04581          * Let Tcl_EvalEx evaluate the command directly (and probably more
04582          * slowly).
04583          *
04584          * Pure List Optimization (no string representation). In this case, we
04585          * can safely use Tcl_EvalObjv instead and get an appreciable
04586          * improvement in execution speed. This is because it allows us to
04587          * avoid a setFromAny step that would just pack everything into a
04588          * string and back out again.
04589          *
04590          * This restriction has been relaxed a bit by storing in lists whether
04591          * they are "canonical" or not (a canonical list being one that is
04592          * either pure or that has its string rep derived by
04593          * UpdateStringOfList from the internal rep).
04594          */
04595 
04596         if (objPtr->typePtr == &tclListType) {  /* is a list... */
04597             List *listRepPtr = objPtr->internalRep.twoPtrValue.ptr1;
04598 
04599             if (objPtr->bytes == NULL ||        /* ...without a string rep */
04600                     listRepPtr->canonicalFlag) {/* ...or that is canonical */
04601                 /*
04602                  * TIP #280 Structures for tracking lines. As we know that
04603                  * this is dynamic execution we ignore the invoker, even if
04604                  * known.
04605                  */
04606 
04607                 int line, i;
04608                 char *w;
04609                 Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
04610                 CmdFrame *eoFramePtr = (CmdFrame *)
04611                         TclStackAlloc(interp, sizeof(CmdFrame));
04612 
04613                 eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
04614                 eoFramePtr->level = (iPtr->cmdFramePtr == NULL?
04615                         1 : iPtr->cmdFramePtr->level + 1);
04616                 eoFramePtr->framePtr = iPtr->framePtr;
04617                 eoFramePtr->nextPtr = iPtr->cmdFramePtr;
04618 
04619                 Tcl_ListObjGetElements(NULL, copyPtr,
04620                         &(eoFramePtr->nline), &elements);
04621                 eoFramePtr->line = (int *)
04622                         ckalloc(eoFramePtr->nline * sizeof(int));
04623 
04624                 eoFramePtr->cmd.listPtr  = objPtr;
04625                 Tcl_IncrRefCount(eoFramePtr->cmd.listPtr);
04626                 eoFramePtr->data.eval.path = NULL;
04627 
04628                 /*
04629                  * TIP #280 Computes all the line numbers for the words in the
04630                  * command.
04631                  */
04632 
04633                 line = 1;
04634                 for (i=0; i < eoFramePtr->nline; i++) {
04635                     eoFramePtr->line[i] = line;
04636                     w = TclGetString(elements[i]);
04637                     TclAdvanceLines(&line, w, w + strlen(w));
04638                 }
04639 
04640                 iPtr->cmdFramePtr = eoFramePtr;
04641                 result = Tcl_EvalObjv(interp, eoFramePtr->nline, elements,
04642                         flags);
04643 
04644                 Tcl_DecrRefCount(copyPtr);
04645                 iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
04646                 Tcl_DecrRefCount(eoFramePtr->cmd.listPtr);
04647                 ckfree((char *) eoFramePtr->line);
04648                 eoFramePtr->line = NULL;
04649                 eoFramePtr->nline = 0;
04650                 TclStackFree(interp, eoFramePtr);
04651 
04652                 goto done;
04653             }
04654         }
04655 
04656         /*
04657          * TIP #280. Propagate context as much as we can. Especially if the
04658          * script to evaluate is a single literal it makes sense to look if
04659          * our context is one with absolute line numbers we can then track
04660          * into the literal itself too.
04661          *
04662          * See also tclCompile.c, TclInitCompileEnv, for the equivalent code
04663          * in the bytecode compiler.
04664          */
04665 
04666         if (invoker == NULL) {
04667             /*
04668              * No context, force opening of our own.
04669              */
04670 
04671             script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
04672             result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
04673         } else {
04674             /*
04675              * We have an invoker, describing the command asking for the
04676              * evaluation of a subordinate script. This script may originate
04677              * in a literal word, or from a variable, etc. Using the line
04678              * array we now check if we have good line information for the
04679              * relevant word. The type of context is relevant as well. In a
04680              * non-'source' context we don't have to try tracking lines.
04681              *
04682              * First see if the word exists and is a literal. If not we go
04683              * through the easy dynamic branch. No need to perform more
04684              * complex invokations.
04685              */
04686 
04687             if ((invoker->nline <= word) || (invoker->line[word] < 0)) {
04688                 /*
04689                  * Dynamic script, or dynamic context, force our own
04690                  * context.
04691                  */
04692 
04693                 script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
04694                 result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
04695 
04696             } else {
04697                 /*
04698                  * Try to get an absolute context for the evaluation.
04699                  */
04700 
04701                 int pc = 0;
04702                 CmdFrame *ctxPtr = (CmdFrame *)
04703                         TclStackAlloc(interp, sizeof(CmdFrame));
04704 
04705                 *ctxPtr = *invoker;
04706                 if (invoker->type == TCL_LOCATION_BC) {
04707                     /*
04708                      * Note: Type BC => ctxPtr->data.eval.path is not used.
04709                      * ctxPtr->data.tebc.codePtr is used instead.
04710                      */
04711 
04712                     TclGetSrcInfoForPc(ctxPtr);
04713                     pc = 1;
04714                 }
04715 
04716                 if (ctxPtr->type == TCL_LOCATION_SOURCE) {
04717                     /*
04718                      * Absolute context to reuse.
04719                      */
04720 
04721                     iPtr->invokeCmdFramePtr = ctxPtr;
04722                     iPtr->evalFlags |= TCL_EVAL_CTX;
04723 
04724                     script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
04725                     result = TclEvalEx(interp, script, numSrcBytes, flags,
04726                             ctxPtr->line[word]);
04727 
04728                     if (pc) {
04729                         /*
04730                          * Death of SrcInfo reference.
04731                          */
04732 
04733                         Tcl_DecrRefCount(ctxPtr->data.eval.path);
04734                     }
04735                 } else {
04736                     /*
04737                      * Dynamic context or script, easier to make our own as
04738                      * well.
04739                      */
04740 
04741                     script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
04742                     result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
04743                 }
04744 
04745                 TclStackFree(interp, ctxPtr);
04746             }
04747         }
04748     } else {
04749         /*
04750          * Let the compiler/engine subsystem do the evaluation.
04751          *
04752          * TIP #280 The invoker provides us with the context for the script.
04753          * We transfer this to the byte code compiler.
04754          */
04755 
04756         savedVarFramePtr = iPtr->varFramePtr;
04757         if (flags & TCL_EVAL_GLOBAL) {
04758             iPtr->varFramePtr = iPtr->rootFramePtr;
04759         }
04760 
04761         result = TclCompEvalObj(interp, objPtr, invoker, word);
04762 
04763         /*
04764          * If we are again at the top level, process any unusual return code
04765          * returned by the evaluated code.
04766          */
04767 
04768         if (iPtr->numLevels == 0) {
04769             if (result == TCL_RETURN) {
04770                 result = TclUpdateReturnInfo(iPtr);
04771             }
04772             if ((result != TCL_OK) && (result != TCL_ERROR)
04773                     && !allowExceptions) {
04774                 ProcessUnexpectedResult(interp, result);
04775                 result = TCL_ERROR;
04776                 script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
04777                 Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
04778             }
04779         }
04780         iPtr->evalFlags = 0;
04781         iPtr->varFramePtr = savedVarFramePtr;
04782     }
04783 
04784   done:
04785     TclDecrRefCount(objPtr);
04786     return result;
04787 }
04788 
04789 /*
04790  *----------------------------------------------------------------------
04791  *
04792  * ProcessUnexpectedResult --
04793  *
04794  *      Function called by Tcl_EvalObj to set the interpreter's result value
04795  *      to an appropriate error message when the code it evaluates returns an
04796  *      unexpected result code (not TCL_OK and not TCL_ERROR) to the topmost
04797  *      evaluation level.
04798  *
04799  * Results:
04800  *      None.
04801  *
04802  * Side effects:
04803  *      The interpreter result is set to an error message appropriate to the
04804  *      result code.
04805  *
04806  *----------------------------------------------------------------------
04807  */
04808 
04809 static void
04810 ProcessUnexpectedResult(
04811     Tcl_Interp *interp,         /* The interpreter in which the unexpected
04812                                  * result code was returned. */
04813     int returnCode)             /* The unexpected result code. */
04814 {
04815     Tcl_ResetResult(interp);
04816     if (returnCode == TCL_BREAK) {
04817         Tcl_AppendResult(interp,
04818                 "invoked \"break\" outside of a loop", NULL);
04819     } else if (returnCode == TCL_CONTINUE) {
04820         Tcl_AppendResult(interp,
04821                 "invoked \"continue\" outside of a loop", NULL);
04822     } else {
04823         Tcl_SetObjResult(interp, Tcl_ObjPrintf(
04824                 "command returned bad code: %d", returnCode));
04825     }
04826 }
04827 
04828 /*
04829  *---------------------------------------------------------------------------
04830  *
04831  * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
04832  *
04833  *      Functions to evaluate an expression and return its value in a
04834  *      particular form.
04835  *
04836  * Results:
04837  *      Each of the functions below returns a standard Tcl result. If an error
04838  *      occurs then an error message is left in the interp's result. Otherwise
04839  *      the value of the expression, in the appropriate form, is stored at
04840  *      *ptr. If the expression had a result that was incompatible with the
04841  *      desired form then an error is returned.
04842  *
04843  * Side effects:
04844  *      None.
04845  *
04846  *---------------------------------------------------------------------------
04847  */
04848 
04849 int
04850 Tcl_ExprLong(
04851     Tcl_Interp *interp,         /* Context in which to evaluate the
04852                                  * expression. */
04853     const char *exprstring,     /* Expression to evaluate. */
04854     long *ptr)                  /* Where to store result. */
04855 {
04856     register Tcl_Obj *exprPtr;
04857     int result = TCL_OK;
04858     if (*exprstring == '\0') {
04859         /*
04860          * Legacy compatibility - return 0 for the zero-length string.
04861          */
04862 
04863         *ptr = 0;
04864     } else {
04865         exprPtr = Tcl_NewStringObj(exprstring, -1);
04866         Tcl_IncrRefCount(exprPtr);
04867         result = Tcl_ExprLongObj(interp, exprPtr, ptr);
04868         Tcl_DecrRefCount(exprPtr);
04869         if (result != TCL_OK) {
04870             (void) Tcl_GetStringResult(interp);
04871         }
04872     }
04873     return result;
04874 }
04875 
04876 int
04877 Tcl_ExprDouble(
04878     Tcl_Interp *interp,         /* Context in which to evaluate the
04879                                  * expression. */
04880     const char *exprstring,     /* Expression to evaluate. */
04881     double *ptr)                /* Where to store result. */
04882 {
04883     register Tcl_Obj *exprPtr;
04884     int result = TCL_OK;
04885 
04886     if (*exprstring == '\0') {
04887         /*
04888          * Legacy compatibility - return 0 for the zero-length string.
04889          */
04890 
04891         *ptr = 0.0;
04892     } else {
04893         exprPtr = Tcl_NewStringObj(exprstring, -1);
04894         Tcl_IncrRefCount(exprPtr);
04895         result = Tcl_ExprDoubleObj(interp, exprPtr, ptr);
04896         Tcl_DecrRefCount(exprPtr);
04897                                 /* Discard the expression object. */
04898         if (result != TCL_OK) {
04899             (void) Tcl_GetStringResult(interp);
04900         }
04901     }
04902     return result;
04903 }
04904 
04905 int
04906 Tcl_ExprBoolean(
04907     Tcl_Interp *interp,         /* Context in which to evaluate the
04908                                  * expression. */
04909     const char *exprstring,     /* Expression to evaluate. */
04910     int *ptr)                   /* Where to store 0/1 result. */
04911 {
04912     if (*exprstring == '\0') {
04913         /*
04914          * An empty string. Just set the result boolean to 0 (false).
04915          */
04916 
04917         *ptr = 0;
04918         return TCL_OK;
04919     } else {
04920         int result;
04921         Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, -1);
04922 
04923         Tcl_IncrRefCount(exprPtr);
04924         result = Tcl_ExprBooleanObj(interp, exprPtr, ptr);
04925         Tcl_DecrRefCount(exprPtr);
04926         if (result != TCL_OK) {
04927             /*
04928              * Move the interpreter's object result to the string result, then
04929              * reset the object result.
04930              */
04931 
04932             (void) Tcl_GetStringResult(interp);
04933         }
04934         return result;
04935     }
04936 }
04937 
04938 /*
04939  *--------------------------------------------------------------
04940  *
04941  * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
04942  *
04943  *      Functions to evaluate an expression in an object and return its value
04944  *      in a particular form.
04945  *
04946  * Results:
04947  *      Each of the functions below returns a standard Tcl result object. If
04948  *      an error occurs then an error message is left in the interpreter's
04949  *      result. Otherwise the value of the expression, in the appropriate
04950  *      form, is stored at *ptr. If the expression had a result that was
04951  *      incompatible with the desired form then an error is returned.
04952  *
04953  * Side effects:
04954  *      None.
04955  *
04956  *--------------------------------------------------------------
04957  */
04958 
04959 int
04960 Tcl_ExprLongObj(
04961     Tcl_Interp *interp,         /* Context in which to evaluate the
04962                                  * expression. */
04963     register Tcl_Obj *objPtr,   /* Expression to evaluate. */
04964     long *ptr)                  /* Where to store long result. */
04965 {
04966     Tcl_Obj *resultPtr;
04967     int result, type;
04968     double d;
04969     ClientData internalPtr;
04970 
04971     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
04972     if (result != TCL_OK) {
04973         return TCL_ERROR;
04974     }
04975 
04976     if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type) != TCL_OK){
04977         return TCL_ERROR;
04978     }
04979 
04980     switch (type) {
04981     case TCL_NUMBER_DOUBLE: {
04982         mp_int big;
04983 
04984         d = *((const double *) internalPtr);
04985         Tcl_DecrRefCount(resultPtr);
04986         if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
04987             return TCL_ERROR;
04988         }
04989         resultPtr = Tcl_NewBignumObj(&big);
04990         /* FALLTHROUGH */
04991     }
04992     case TCL_NUMBER_LONG:
04993     case TCL_NUMBER_WIDE:
04994     case TCL_NUMBER_BIG:
04995         result = TclGetLongFromObj(interp, resultPtr, ptr);
04996         break;
04997 
04998     case TCL_NUMBER_NAN:
04999         Tcl_GetDoubleFromObj(interp, resultPtr, &d);
05000         result = TCL_ERROR;
05001     }
05002 
05003     Tcl_DecrRefCount(resultPtr);/* Discard the result object. */
05004     return result;
05005 }
05006 
05007 int
05008 Tcl_ExprDoubleObj(
05009     Tcl_Interp *interp,         /* Context in which to evaluate the
05010                                  * expression. */
05011     register Tcl_Obj *objPtr,   /* Expression to evaluate. */
05012     double *ptr)                /* Where to store double result. */
05013 {
05014     Tcl_Obj *resultPtr;
05015     int result, type;
05016     ClientData internalPtr;
05017 
05018     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
05019     if (result != TCL_OK) {
05020         return TCL_ERROR;
05021     }
05022 
05023     result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type);
05024     if (result == TCL_OK) {
05025         switch (type) {
05026         case TCL_NUMBER_NAN:
05027 #ifndef ACCEPT_NAN
05028             result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
05029             break;
05030 #endif
05031         case TCL_NUMBER_DOUBLE:
05032             *ptr = *((const double *) internalPtr);
05033             result = TCL_OK;
05034             break;
05035         default:
05036             result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
05037         }
05038     }
05039     Tcl_DecrRefCount(resultPtr);/* Discard the result object. */
05040     return result;
05041 }
05042 
05043 int
05044 Tcl_ExprBooleanObj(
05045     Tcl_Interp *interp,         /* Context in which to evaluate the
05046                                  * expression. */
05047     register Tcl_Obj *objPtr,   /* Expression to evaluate. */
05048     int *ptr)                   /* Where to store 0/1 result. */
05049 {
05050     Tcl_Obj *resultPtr;
05051     int result;
05052 
05053     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
05054     if (result == TCL_OK) {
05055         result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
05056         Tcl_DecrRefCount(resultPtr);
05057                                 /* Discard the result object. */
05058     }
05059     return result;
05060 }
05061 
05062 /*
05063  *----------------------------------------------------------------------
05064  *
05065  * TclObjInvokeNamespace --
05066  *
05067  *      Object version: Invokes a Tcl command, given an objv/objc, from either
05068  *      the exposed or hidden set of commands in the given interpreter.
05069  *      NOTE: The command is invoked in the global stack frame of the
05070  *      interpreter or namespace, thus it cannot see any current state on the
05071  *      stack of that interpreter.
05072  *
05073  * Results:
05074  *      A standard Tcl result.
05075  *
05076  * Side effects:
05077  *      Whatever the command does.
05078  *
05079  *----------------------------------------------------------------------
05080  */
05081 
05082 int
05083 TclObjInvokeNamespace(
05084     Tcl_Interp *interp,         /* Interpreter in which command is to be
05085                                  * invoked. */
05086     int objc,                   /* Count of arguments. */
05087     Tcl_Obj *const objv[],      /* Argument objects; objv[0] points to the
05088                                  * name of the command to invoke. */
05089     Tcl_Namespace *nsPtr,       /* The namespace to use. */
05090     int flags)                  /* Combination of flags controlling the call:
05091                                  * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
05092                                  * or TCL_INVOKE_NO_TRACEBACK. */
05093 {
05094     int result;
05095     Tcl_CallFrame *framePtr;
05096 
05097     /*
05098      * Make the specified namespace the current namespace and invoke the
05099      * command.
05100      */
05101 
05102     result = TclPushStackFrame(interp, &framePtr, nsPtr, /*isProcFrame*/0);
05103     if (result != TCL_OK) {
05104         return TCL_ERROR;
05105     }
05106 
05107     result = TclObjInvoke(interp, objc, objv, flags);
05108 
05109     TclPopStackFrame(interp);
05110     return result;
05111 }
05112 
05113 /*
05114  *----------------------------------------------------------------------
05115  *
05116  * TclObjInvoke --
05117  *
05118  *      Invokes a Tcl command, given an objv/objc, from either the exposed or
05119  *      the hidden sets of commands in the given interpreter.
05120  *
05121  * Results:
05122  *      A standard Tcl object result.
05123  *
05124  * Side effects:
05125  *      Whatever the command does.
05126  *
05127  *----------------------------------------------------------------------
05128  */
05129 
05130 int
05131 TclObjInvoke(
05132     Tcl_Interp *interp,         /* Interpreter in which command is to be
05133                                  * invoked. */
05134     int objc,                   /* Count of arguments. */
05135     Tcl_Obj *const objv[],      /* Argument objects; objv[0] points to the
05136                                  * name of the command to invoke. */
05137     int flags)                  /* Combination of flags controlling the call:
05138                                  * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
05139                                  * or TCL_INVOKE_NO_TRACEBACK. */
05140 {
05141     register Interp *iPtr = (Interp *) interp;
05142     Tcl_HashTable *hTblPtr;     /* Table of hidden commands. */
05143     char *cmdName;              /* Name of the command from objv[0]. */
05144     Tcl_HashEntry *hPtr = NULL;
05145     Command *cmdPtr;
05146     int result;
05147 
05148     if (interp == NULL) {
05149         return TCL_ERROR;
05150     }
05151 
05152     if ((objc < 1) || (objv == NULL)) {
05153         Tcl_AppendResult(interp, "illegal argument vector", NULL);
05154         return TCL_ERROR;
05155     }
05156 
05157     if ((flags & TCL_INVOKE_HIDDEN) == 0) {
05158         Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN");
05159     }
05160 
05161     if (TclInterpReady(interp) == TCL_ERROR) {
05162         return TCL_ERROR;
05163     }
05164 
05165     cmdName = TclGetString(objv[0]);
05166     hTblPtr = iPtr->hiddenCmdTablePtr;
05167     if (hTblPtr != NULL) {
05168         hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
05169     }
05170     if (hPtr == NULL) {
05171         Tcl_AppendResult(interp, "invalid hidden command name \"",
05172                 cmdName, "\"", NULL);
05173         return TCL_ERROR;
05174     }
05175     cmdPtr = Tcl_GetHashValue(hPtr);
05176 
05177     /*
05178      * Invoke the command function.
05179      */
05180 
05181     iPtr->cmdCount++;
05182     result = cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
05183 
05184     /*
05185      * If an error occurred, record information about what was being executed
05186      * when the error occurred.
05187      */
05188 
05189     if ((result == TCL_ERROR)
05190             && ((flags & TCL_INVOKE_NO_TRACEBACK) == 0)
05191             && ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
05192         int length;
05193         Tcl_Obj *command = Tcl_NewListObj(objc, objv);
05194         const char *cmdString;
05195 
05196         Tcl_IncrRefCount(command);
05197         cmdString = Tcl_GetStringFromObj(command, &length);
05198         Tcl_LogCommandInfo(interp, cmdString, cmdString, length);
05199         Tcl_DecrRefCount(command);
05200         iPtr->flags &= ~ERR_ALREADY_LOGGED;
05201     }
05202     return result;
05203 }
05204 
05205 /*
05206  *---------------------------------------------------------------------------
05207  *
05208  * Tcl_ExprString --
05209  *
05210  *      Evaluate an expression in a string and return its value in string
05211  *      form.
05212  *
05213  * Results:
05214  *      A standard Tcl result. If the result is TCL_OK, then the interp's
05215  *      result is set to the string value of the expression. If the result is
05216  *      TCL_ERROR, then the interp's result contains an error message.
05217  *
05218  * Side effects:
05219  *      A Tcl object is allocated to hold a copy of the expression string.
05220  *      This expression object is passed to Tcl_ExprObj and then deallocated.
05221  *
05222  *---------------------------------------------------------------------------
05223  */
05224 
05225 int
05226 Tcl_ExprString(
05227     Tcl_Interp *interp,         /* Context in which to evaluate the
05228                                  * expression. */
05229     const char *expr)           /* Expression to evaluate. */
05230 {
05231     int code = TCL_OK;
05232 
05233     if (expr[0] == '\0') {
05234         /*
05235          * An empty string. Just set the interpreter's result to 0.
05236          */
05237 
05238         Tcl_SetResult(interp, "0", TCL_VOLATILE);
05239     } else {
05240         Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, -1);
05241 
05242         Tcl_IncrRefCount(exprObj);
05243         code = Tcl_ExprObj(interp, exprObj, &resultPtr);
05244         Tcl_DecrRefCount(exprObj);
05245         if (code == TCL_OK) {
05246             Tcl_SetObjResult(interp, resultPtr);
05247             Tcl_DecrRefCount(resultPtr);
05248         }
05249 
05250         /*
05251          * Force the string rep of the interp result.
05252          */
05253 
05254         (void) Tcl_GetStringResult(interp);
05255     }
05256     return code;
05257 }
05258 
05259 /*
05260  *----------------------------------------------------------------------
05261  *
05262  * Tcl_AppendObjToErrorInfo --
05263  *
05264  *      Add a Tcl_Obj value to the errorInfo field that describes the current
05265  *      error.
05266  *
05267  * Results:
05268  *      None.
05269  *
05270  * Side effects:
05271  *      The value of the Tcl_obj is appended to the errorInfo field. If we are
05272  *      just starting to log an error, errorInfo is initialized from the error
05273  *      message in the interpreter's result.
05274  *
05275  *----------------------------------------------------------------------
05276  */
05277 
05278 void
05279 Tcl_AppendObjToErrorInfo(
05280     Tcl_Interp *interp,         /* Interpreter to which error information
05281                                  * pertains. */
05282     Tcl_Obj *objPtr)            /* Message to record. */
05283 {
05284     int length;
05285     const char *message = TclGetStringFromObj(objPtr, &length);
05286 
05287     Tcl_AddObjErrorInfo(interp, message, length);
05288     Tcl_DecrRefCount(objPtr);
05289 }
05290 
05291 /*
05292  *----------------------------------------------------------------------
05293  *
05294  * Tcl_AddErrorInfo --
05295  *
05296  *      Add information to the errorInfo field that describes the current
05297  *      error.
05298  *
05299  * Results:
05300  *      None.
05301  *
05302  * Side effects:
05303  *      The contents of message are appended to the errorInfo field. If we are
05304  *      just starting to log an error, errorInfo is initialized from the error
05305  *      message in the interpreter's result.
05306  *
05307  *----------------------------------------------------------------------
05308  */
05309 
05310 void
05311 Tcl_AddErrorInfo(
05312     Tcl_Interp *interp,         /* Interpreter to which error information
05313                                  * pertains. */
05314     const char *message)        /* Message to record. */
05315 {
05316     Tcl_AddObjErrorInfo(interp, message, -1);
05317 }
05318 
05319 /*
05320  *----------------------------------------------------------------------
05321  *
05322  * Tcl_AddObjErrorInfo --
05323  *
05324  *      Add information to the errorInfo field that describes the current
05325  *      error. This routine differs from Tcl_AddErrorInfo by taking a byte
05326  *      pointer and length.
05327  *
05328  * Results:
05329  *      None.
05330  *
05331  * Side effects:
05332  *      "length" bytes from "message" are appended to the errorInfo field. If
05333  *      "length" is negative, use bytes up to the first NULL byte. If we are
05334  *      just starting to log an error, errorInfo is initialized from the error
05335  *      message in the interpreter's result.
05336  *
05337  *----------------------------------------------------------------------
05338  */
05339 
05340 void
05341 Tcl_AddObjErrorInfo(
05342     Tcl_Interp *interp,         /* Interpreter to which error information
05343                                  * pertains. */
05344     const char *message,        /* Points to the first byte of an array of
05345                                  * bytes of the message. */
05346     int length)                 /* The number of bytes in the message. If < 0,
05347                                  * then append all bytes up to a NULL byte. */
05348 {
05349     register Interp *iPtr = (Interp *) interp;
05350 
05351     /*
05352      * If we are just starting to log an error, errorInfo is initialized from
05353      * the error message in the interpreter's result.
05354      */
05355 
05356     iPtr->flags |= ERR_LEGACY_COPY;
05357     if (iPtr->errorInfo == NULL) {
05358         if (iPtr->result[0] != 0) {
05359             /*
05360              * The interp's string result is set, apparently by some extension
05361              * making a deprecated direct write to it. That extension may
05362              * expect interp->result to continue to be set, so we'll take
05363              * special pains to avoid clearing it, until we drop support for
05364              * interp->result completely.
05365              */
05366 
05367             iPtr->errorInfo = Tcl_NewStringObj(interp->result, -1);
05368         } else {
05369             iPtr->errorInfo = iPtr->objResultPtr;
05370         }
05371         Tcl_IncrRefCount(iPtr->errorInfo);
05372         if (!iPtr->errorCode) {
05373             Tcl_SetErrorCode(interp, "NONE", NULL);
05374         }
05375     }
05376 
05377     /*
05378      * Now append "message" to the end of errorInfo.
05379      */
05380 
05381     if (length != 0) {
05382         if (Tcl_IsShared(iPtr->errorInfo)) {
05383             Tcl_DecrRefCount(iPtr->errorInfo);
05384             iPtr->errorInfo = Tcl_DuplicateObj(iPtr->errorInfo);
05385             Tcl_IncrRefCount(iPtr->errorInfo);
05386         }
05387         Tcl_AppendToObj(iPtr->errorInfo, message, length);
05388     }
05389 }
05390 
05391 /*
05392  *---------------------------------------------------------------------------
05393  *
05394  * Tcl_VarEvalVA --
05395  *
05396  *      Given a variable number of string arguments, concatenate them all
05397  *      together and execute the result as a Tcl command.
05398  *
05399  * Results:
05400  *      A standard Tcl return result. An error message or other result may be
05401  *      left in the interp's result.
05402  *
05403  * Side effects:
05404  *      Depends on what was done by the command.
05405  *
05406  *---------------------------------------------------------------------------
05407  */
05408 
05409 int
05410 Tcl_VarEvalVA(
05411     Tcl_Interp *interp,         /* Interpreter in which to evaluate command. */
05412     va_list argList)            /* Variable argument list. */
05413 {
05414     Tcl_DString buf;
05415     char *string;
05416     int result;
05417 
05418     /*
05419      * Copy the strings one after the other into a single larger string. Use
05420      * stack-allocated space for small commands, but if the command gets too
05421      * large than call ckalloc to create the space.
05422      */
05423 
05424     Tcl_DStringInit(&buf);
05425     while (1) {
05426         string = va_arg(argList, char *);
05427         if (string == NULL) {
05428             break;
05429         }
05430         Tcl_DStringAppend(&buf, string, -1);
05431     }
05432 
05433     result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
05434     Tcl_DStringFree(&buf);
05435     return result;
05436 }
05437 
05438 /*
05439  *----------------------------------------------------------------------
05440  *
05441  * Tcl_VarEval --
05442  *
05443  *      Given a variable number of string arguments, concatenate them all
05444  *      together and execute the result as a Tcl command.
05445  *
05446  * Results:
05447  *      A standard Tcl return result. An error message or other result may be
05448  *      left in interp->result.
05449  *
05450  * Side effects:
05451  *      Depends on what was done by the command.
05452  *
05453  *----------------------------------------------------------------------
05454  */
05455         /* ARGSUSED */
05456 int
05457 Tcl_VarEval(
05458     Tcl_Interp *interp,
05459     ...)
05460 {
05461     va_list argList;
05462     int result;
05463 
05464     va_start(argList, interp);
05465     result = Tcl_VarEvalVA(interp, argList);
05466     va_end(argList);
05467 
05468     return result;
05469 }
05470 
05471 /*
05472  *----------------------------------------------------------------------
05473  *
05474  * Tcl_GlobalEval --
05475  *
05476  *      Evaluate a command at global level in an interpreter.
05477  *
05478  * Results:
05479  *      A standard Tcl result is returned, and the interp's result is modified
05480  *      accordingly.
05481  *
05482  * Side effects:
05483  *      The command string is executed in interp, and the execution is carried
05484  *      out in the variable context of global level (no functions active),
05485  *      just as if an "uplevel #0" command were being executed.
05486  *
05487  *----------------------------------------------------------------------
05488  */
05489 
05490 int
05491 Tcl_GlobalEval(
05492     Tcl_Interp *interp,         /* Interpreter in which to evaluate command. */
05493     const char *command)        /* Command to evaluate. */
05494 {
05495     register Interp *iPtr = (Interp *) interp;
05496     int result;
05497     CallFrame *savedVarFramePtr;
05498 
05499     savedVarFramePtr = iPtr->varFramePtr;
05500     iPtr->varFramePtr = iPtr->rootFramePtr;
05501     result = Tcl_Eval(interp, command);
05502     iPtr->varFramePtr = savedVarFramePtr;
05503     return result;
05504 }
05505 
05506 /*
05507  *----------------------------------------------------------------------
05508  *
05509  * Tcl_SetRecursionLimit --
05510  *
05511  *      Set the maximum number of recursive calls that may be active for an
05512  *      interpreter at once.
05513  *
05514  * Results:
05515  *      The return value is the old limit on nesting for interp.
05516  *
05517  * Side effects:
05518  *      None.
05519  *
05520  *----------------------------------------------------------------------
05521  */
05522 
05523 int
05524 Tcl_SetRecursionLimit(
05525     Tcl_Interp *interp,         /* Interpreter whose nesting limit is to be
05526                                  * set. */
05527     int depth)                  /* New value for maximimum depth. */
05528 {
05529     Interp *iPtr = (Interp *) interp;
05530     int old;
05531 
05532     old = iPtr->maxNestingDepth;
05533     if (depth > 0) {
05534         iPtr->maxNestingDepth = depth;
05535     }
05536     return old;
05537 }
05538 
05539 /*
05540  *----------------------------------------------------------------------
05541  *
05542  * Tcl_AllowExceptions --
05543  *
05544  *      Sets a flag in an interpreter so that exceptions can occur in the next
05545  *      call to Tcl_Eval without them being turned into errors.
05546  *
05547  * Results:
05548  *      None.
05549  *
05550  * Side effects:
05551  *      The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's evalFlags
05552  *      structure. See the reference documentation for more details.
05553  *
05554  *----------------------------------------------------------------------
05555  */
05556 
05557 void
05558 Tcl_AllowExceptions(
05559     Tcl_Interp *interp)         /* Interpreter in which to set flag. */
05560 {
05561     Interp *iPtr = (Interp *) interp;
05562 
05563     iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS;
05564 }
05565 
05566 /*
05567  *----------------------------------------------------------------------
05568  *
05569  * Tcl_GetVersion --
05570  *
05571  *      Get the Tcl major, minor, and patchlevel version numbers and the
05572  *      release type. A patch is a release type TCL_FINAL_RELEASE with a
05573  *      patchLevel > 0.
05574  *
05575  * Results:
05576  *      None.
05577  *
05578  * Side effects:
05579  *      None.
05580  *
05581  *----------------------------------------------------------------------
05582  */
05583 
05584 void
05585 Tcl_GetVersion(
05586     int *majorV,
05587     int *minorV,
05588     int *patchLevelV,
05589     int *type)
05590 {
05591     if (majorV != NULL) {
05592         *majorV = TCL_MAJOR_VERSION;
05593     }
05594     if (minorV != NULL) {
05595         *minorV = TCL_MINOR_VERSION;
05596     }
05597     if (patchLevelV != NULL) {
05598         *patchLevelV = TCL_RELEASE_SERIAL;
05599     }
05600     if (type != NULL) {
05601         *type = TCL_RELEASE_LEVEL;
05602     }
05603 }
05604 
05605 /*
05606  *----------------------------------------------------------------------
05607  *
05608  * Math Functions --
05609  *
05610  *      This page contains the functions that implement all of the built-in
05611  *      math functions for expressions.
05612  *
05613  * Results:
05614  *      Each function returns TCL_OK if it succeeds and pushes an Tcl object
05615  *      holding the result. If it fails it returns TCL_ERROR and leaves an
05616  *      error message in the interpreter's result.
05617  *
05618  * Side effects:
05619  *      None.
05620  *
05621  *----------------------------------------------------------------------
05622  */
05623 
05624 static int
05625 ExprCeilFunc(
05626     ClientData clientData,      /* Ignored */
05627     Tcl_Interp *interp,         /* The interpreter in which to execute the
05628                                  * function. */
05629     int objc,                   /* Actual parameter count. */
05630     Tcl_Obj *const *objv)       /* Actual parameter list. */
05631 {
05632     int code;
05633     double d;
05634     mp_int big;
05635 
05636     if (objc != 2) {
05637         MathFuncWrongNumArgs(interp, 2, objc, objv);
05638         return TCL_ERROR;
05639     }
05640     code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
05641 #ifdef ACCEPT_NAN
05642     if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
05643         Tcl_SetObjResult(interp, objv[1]);
05644         return TCL_OK;
05645     }
05646 #endif
05647     if (code != TCL_OK) {
05648         return TCL_ERROR;
05649     }
05650     if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) {
05651         Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclCeil(&big)));
05652         mp_clear(&big);
05653     } else {
05654         Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ceil(d)));
05655     }
05656     return TCL_OK;
05657 }
05658 
05659 static int
05660 ExprFloorFunc(
05661     ClientData clientData,      /* Ignored */
05662     Tcl_Interp *interp,         /* The interpreter in which to execute the
05663                                  * function. */
05664     int objc,                   /* Actual parameter count. */
05665     Tcl_Obj *const *objv)       /* Actual parameter list. */
05666 {
05667     int code;
05668     double d;
05669     mp_int big;
05670 
05671     if (objc != 2) {
05672         MathFuncWrongNumArgs(interp, 2, objc, objv);
05673         return TCL_ERROR;
05674     }
05675     code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
05676 #ifdef ACCEPT_NAN
05677     if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
05678         Tcl_SetObjResult(interp, objv[1]);
05679         return TCL_OK;
05680     }
05681 #endif
05682     if (code != TCL_OK) {
05683         return TCL_ERROR;
05684     }
05685     if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) {
05686         Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclFloor(&big)));
05687         mp_clear(&big);
05688     } else {
05689         Tcl_SetObjResult(interp, Tcl_NewDoubleObj(floor(d)));
05690     }
05691     return TCL_OK;
05692 }
05693 
05694 static int
05695 ExprIsqrtFunc(
05696     ClientData clientData,      /* Ignored */
05697     Tcl_Interp *interp,         /* The interpreter in which to execute. */
05698     int objc,                   /* Actual parameter count. */
05699     Tcl_Obj *const *objv)       /* Actual parameter list. */
05700 {
05701     ClientData ptr;
05702     int type;
05703     double d;
05704     Tcl_WideInt w;
05705     mp_int big;
05706     int exact = 0;              /* Flag == 1 if the argument can be
05707                                  * represented in a double as an exact
05708                                  * integer. */
05709 
05710     /*
05711      * Check syntax.
05712      */
05713 
05714     if (objc != 2) {
05715         MathFuncWrongNumArgs(interp, 2, objc, objv);
05716         return TCL_ERROR;
05717     }
05718 
05719     /*
05720      * Make sure that the arg is a number.
05721      */
05722 
05723     if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
05724         return TCL_ERROR;
05725     }
05726 
05727     switch (type) {
05728     case TCL_NUMBER_NAN:
05729         Tcl_GetDoubleFromObj(interp, objv[1], &d);
05730         return TCL_ERROR;
05731     case TCL_NUMBER_DOUBLE:
05732         d = *((const double *) ptr);
05733         if (d < 0) {
05734             goto negarg;
05735         }
05736 #ifdef IEEE_FLOATING_POINT
05737         if (d <= MAX_EXACT) {
05738             exact = 1;
05739         }
05740 #endif
05741         if (!exact) {
05742             if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
05743                 return TCL_ERROR;
05744             }
05745         }
05746         break;
05747     case TCL_NUMBER_BIG:
05748         if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
05749             return TCL_ERROR;
05750         }
05751         if (SIGN(&big) == MP_NEG) {
05752             mp_clear(&big);
05753             goto negarg;
05754         }
05755         break;
05756     default:
05757         if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
05758             return TCL_ERROR;
05759         }
05760         if (w < 0) {
05761             goto negarg;
05762         }
05763         d = (double) w;
05764 #ifdef IEEE_FLOATING_POINT
05765         if (d < MAX_EXACT) {
05766             exact = 1;
05767         }
05768 #endif
05769         if (!exact) {
05770             Tcl_GetBignumFromObj(interp, objv[1], &big);
05771         }
05772         break;
05773     }
05774 
05775     if (exact) {
05776         Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d)));
05777     } else {
05778         mp_int root;
05779 
05780         mp_init(&root);
05781         mp_sqrt(&big, &root);
05782         mp_clear(&big);
05783         Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root));
05784     }
05785 
05786     return TCL_OK;
05787 
05788   negarg:
05789     Tcl_SetObjResult(interp,
05790             Tcl_NewStringObj("square root of negative argument", -1));
05791     return TCL_ERROR;
05792 }
05793 
05794 static int
05795 ExprSqrtFunc(
05796     ClientData clientData,      /* Ignored */
05797     Tcl_Interp *interp,         /* The interpreter in which to execute the
05798                                  * function. */
05799     int objc,                   /* Actual parameter count. */
05800     Tcl_Obj *const *objv)       /* Actual parameter list. */
05801 {
05802     int code;
05803     double d;
05804     mp_int big;
05805 
05806     if (objc != 2) {
05807         MathFuncWrongNumArgs(interp, 2, objc, objv);
05808         return TCL_ERROR;
05809     }
05810     code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
05811 #ifdef ACCEPT_NAN
05812     if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
05813         Tcl_SetObjResult(interp, objv[1]);
05814         return TCL_OK;
05815     }
05816 #endif
05817     if (code != TCL_OK) {
05818         return TCL_ERROR;
05819     }
05820     if ((d >= 0.0) && TclIsInfinite(d)
05821             && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) {
05822         mp_int root;
05823 
05824         mp_init(&root);
05825         mp_sqrt(&big, &root);
05826         mp_clear(&big);
05827         Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclBignumToDouble(&root)));
05828         mp_clear(&root);
05829     } else {
05830         Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
05831     }
05832     return TCL_OK;
05833 }
05834 
05835 static int
05836 ExprUnaryFunc(
05837     ClientData clientData,      /* Contains the address of a function that
05838                                  * takes one double argument and returns a
05839                                  * double result. */
05840     Tcl_Interp *interp,         /* The interpreter in which to execute the
05841                                  * function. */
05842     int objc,                   /* Actual parameter count */
05843     Tcl_Obj *const *objv)       /* Actual parameter list */
05844 {
05845     int code;
05846     double d;
05847     double (*func)(double) = (double (*)(double)) clientData;
05848 
05849     if (objc != 2) {
05850         MathFuncWrongNumArgs(interp, 2, objc, objv);
05851         return TCL_ERROR;
05852     }
05853     code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
05854 #ifdef ACCEPT_NAN
05855     if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
05856         d = objv[1]->internalRep.doubleValue;
05857         Tcl_ResetResult(interp);
05858         code = TCL_OK;
05859     }
05860 #endif
05861     if (code != TCL_OK) {
05862         return TCL_ERROR;
05863     }
05864     errno = 0;
05865     return CheckDoubleResult(interp, (*func)(d));
05866 }
05867 
05868 static int
05869 CheckDoubleResult(
05870     Tcl_Interp *interp,
05871     double dResult)
05872 {
05873 #ifndef ACCEPT_NAN
05874     if (TclIsNaN(dResult)) {
05875         TclExprFloatError(interp, dResult);
05876         return TCL_ERROR;
05877     }
05878 #endif
05879     if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(dResult))) {
05880         /*
05881          * When ERANGE signals under/overflow, just accept 0.0 or +/-Inf
05882          */
05883     } else if (errno != 0) {
05884         /*
05885          * Report other errno values as errors.
05886          */
05887 
05888         TclExprFloatError(interp, dResult);
05889         return TCL_ERROR;
05890     }
05891     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
05892     return TCL_OK;
05893 }
05894 
05895 static int
05896 ExprBinaryFunc(
05897     ClientData clientData,      /* Contains the address of a function that
05898                                  * takes two double arguments and returns a
05899                                  * double result. */
05900     Tcl_Interp *interp,         /* The interpreter in which to execute the
05901                                  * function. */
05902     int objc,                   /* Actual parameter count. */
05903     Tcl_Obj *const *objv)       /* Parameter vector. */
05904 {
05905     int code;
05906     double d1, d2;
05907     double (*func)(double, double) = (double (*)(double, double)) clientData;
05908 
05909     if (objc != 3) {
05910         MathFuncWrongNumArgs(interp, 3, objc, objv);
05911         return TCL_ERROR;
05912     }
05913     code = Tcl_GetDoubleFromObj(interp, objv[1], &d1);
05914 #ifdef ACCEPT_NAN
05915     if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
05916         d1 = objv[1]->internalRep.doubleValue;
05917         Tcl_ResetResult(interp);
05918         code = TCL_OK;
05919     }
05920 #endif
05921     if (code != TCL_OK) {
05922         return TCL_ERROR;
05923     }
05924     code = Tcl_GetDoubleFromObj(interp, objv[2], &d2);
05925 #ifdef ACCEPT_NAN
05926     if ((code != TCL_OK) && (objv[2]->typePtr == &tclDoubleType)) {
05927         d2 = objv[2]->internalRep.doubleValue;
05928         Tcl_ResetResult(interp);
05929         code = TCL_OK;
05930     }
05931 #endif
05932     if (code != TCL_OK) {
05933         return TCL_ERROR;
05934     }
05935     errno = 0;
05936     return CheckDoubleResult(interp, (*func)(d1, d2));
05937 }
05938 
05939 static int
05940 ExprAbsFunc(
05941     ClientData clientData,      /* Ignored. */
05942     Tcl_Interp *interp,         /* The interpreter in which to execute the
05943                                  * function. */
05944     int objc,                   /* Actual parameter count. */
05945     Tcl_Obj *const *objv)       /* Parameter vector. */
05946 {
05947     ClientData ptr;
05948     int type;
05949     mp_int big;
05950 
05951     if (objc != 2) {
05952         MathFuncWrongNumArgs(interp, 2, objc, objv);
05953         return TCL_ERROR;
05954     }
05955 
05956     if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
05957         return TCL_ERROR;
05958     }
05959 
05960     if (type == TCL_NUMBER_LONG) {
05961         long l = *((const long *) ptr);
05962         if (l < (long)0) {
05963             if (l == LONG_MIN) {
05964                 TclBNInitBignumFromLong(&big, l);
05965                 goto tooLarge;
05966             }
05967             Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
05968         } else {
05969             Tcl_SetObjResult(interp, objv[1]);
05970         }
05971         return TCL_OK;
05972     }
05973 
05974     if (type == TCL_NUMBER_DOUBLE) {
05975         double d = *((const double *) ptr);
05976         if (d < 0.0) {
05977             Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
05978         } else {
05979             Tcl_SetObjResult(interp, objv[1]);
05980         }
05981         return TCL_OK;
05982     }
05983 
05984 #ifndef NO_WIDE_TYPE
05985     if (type == TCL_NUMBER_WIDE) {
05986         Tcl_WideInt w = *((const Tcl_WideInt *) ptr);
05987         if (w < (Tcl_WideInt)0) {
05988             if (w == LLONG_MIN) {
05989                 TclBNInitBignumFromWideInt(&big, w);
05990                 goto tooLarge;
05991             }
05992             Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
05993         } else {
05994             Tcl_SetObjResult(interp, objv[1]);
05995         }
05996         return TCL_OK;
05997     }
05998 #endif
05999 
06000     if (type == TCL_NUMBER_BIG) {
06001         /* TODO: const correctness ? */
06002         if (mp_cmp_d((mp_int *) ptr, 0) == MP_LT) {
06003             Tcl_GetBignumFromObj(NULL, objv[1], &big);
06004         tooLarge:
06005             mp_neg(&big, &big);
06006             Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
06007         } else {
06008             Tcl_SetObjResult(interp, objv[1]);
06009         }
06010         return TCL_OK;
06011     }
06012 
06013     if (type == TCL_NUMBER_NAN) {
06014 #ifdef ACCEPT_NAN
06015         Tcl_SetObjResult(interp, objv[1]);
06016         return TCL_OK;
06017 #else
06018         double d;
06019         Tcl_GetDoubleFromObj(interp, objv[1], &d);
06020         return TCL_ERROR;
06021 #endif
06022     }
06023     return TCL_OK;
06024 }
06025 
06026 static int
06027 ExprBoolFunc(
06028     ClientData clientData,      /* Ignored. */
06029     Tcl_Interp *interp,         /* The interpreter in which to execute the
06030                                  * function. */
06031     int objc,                   /* Actual parameter count. */
06032     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06033 {
06034     int value;
06035 
06036     if (objc != 2) {
06037         MathFuncWrongNumArgs(interp, 2, objc, objv);
06038         return TCL_ERROR;
06039     }
06040     if (Tcl_GetBooleanFromObj(interp, objv[1], &value) != TCL_OK) {
06041         return TCL_ERROR;
06042     }
06043     Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
06044     return TCL_OK;
06045 }
06046 
06047 static int
06048 ExprDoubleFunc(
06049     ClientData clientData,      /* Ignored. */
06050     Tcl_Interp *interp,         /* The interpreter in which to execute the
06051                                  * function. */
06052     int objc,                   /* Actual parameter count. */
06053     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06054 {
06055     double dResult;
06056     if (objc != 2) {
06057         MathFuncWrongNumArgs(interp, 2, objc, objv);
06058         return TCL_ERROR;
06059     }
06060     if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
06061 #ifdef ACCEPT_NAN
06062         if (objv[1]->typePtr == &tclDoubleType) {
06063             Tcl_SetObjResult(interp, objv[1]);
06064             return TCL_OK;
06065         }
06066 #endif
06067         return TCL_ERROR;
06068     }
06069     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
06070     return TCL_OK;
06071 }
06072 
06073 static int
06074 ExprEntierFunc(
06075     ClientData clientData,      /* Ignored. */
06076     Tcl_Interp *interp,         /* The interpreter in which to execute the
06077                                  * function. */
06078     int objc,                   /* Actual parameter count. */
06079     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06080 {
06081     double d;
06082     int type;
06083     ClientData ptr;
06084 
06085     if (objc != 2) {
06086         MathFuncWrongNumArgs(interp, 2, objc, objv);
06087         return TCL_ERROR;
06088     }
06089     if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
06090         return TCL_ERROR;
06091     }
06092 
06093     if (type == TCL_NUMBER_DOUBLE) {
06094         d = *((const double *) ptr);
06095         if ((d >= (double)LONG_MAX) || (d <= (double)LONG_MIN)) {
06096             mp_int big;
06097 
06098             if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
06099                 /* Infinity */
06100                 return TCL_ERROR;
06101             }
06102             Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
06103             return TCL_OK;
06104         } else {
06105             long result = (long) d;
06106 
06107             Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
06108             return TCL_OK;
06109         }
06110     }
06111 
06112     if (type != TCL_NUMBER_NAN) {
06113         /*
06114          * All integers are already of integer type.
06115          */
06116 
06117         Tcl_SetObjResult(interp, objv[1]);
06118         return TCL_OK;
06119     }
06120 
06121     /*
06122      * Get the error message for NaN.
06123      */
06124 
06125     Tcl_GetDoubleFromObj(interp, objv[1], &d);
06126     return TCL_ERROR;
06127 }
06128 
06129 static int
06130 ExprIntFunc(
06131     ClientData clientData,      /* Ignored. */
06132     Tcl_Interp *interp,         /* The interpreter in which to execute the
06133                                  * function. */
06134     int objc,                   /* Actual parameter count. */
06135     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06136 {
06137     long iResult;
06138     Tcl_Obj *objPtr;
06139     if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) {
06140         return TCL_ERROR;
06141     }
06142     objPtr = Tcl_GetObjResult(interp);
06143     if (TclGetLongFromObj(NULL, objPtr, &iResult) != TCL_OK) {
06144         /*
06145          * Truncate the bignum; keep only bits in long range.
06146          */
06147 
06148         mp_int big;
06149 
06150         Tcl_GetBignumFromObj(NULL, objPtr, &big);
06151         mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
06152         objPtr = Tcl_NewBignumObj(&big);
06153         Tcl_IncrRefCount(objPtr);
06154         TclGetLongFromObj(NULL, objPtr, &iResult);
06155         Tcl_DecrRefCount(objPtr);
06156     }
06157     Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
06158     return TCL_OK;
06159 }
06160 
06161 static int
06162 ExprWideFunc(
06163     ClientData clientData,      /* Ignored. */
06164     Tcl_Interp *interp,         /* The interpreter in which to execute the
06165                                  * function. */
06166     int objc,                   /* Actual parameter count. */
06167     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06168 {
06169     Tcl_WideInt wResult;
06170     Tcl_Obj *objPtr;
06171     if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) {
06172         return TCL_ERROR;
06173     }
06174     objPtr = Tcl_GetObjResult(interp);
06175     if (Tcl_GetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
06176         /*
06177          * Truncate the bignum; keep only bits in wide int range.
06178          */
06179 
06180         mp_int big;
06181 
06182         Tcl_GetBignumFromObj(NULL, objPtr, &big);
06183         mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
06184         objPtr = Tcl_NewBignumObj(&big);
06185         Tcl_IncrRefCount(objPtr);
06186         Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
06187         Tcl_DecrRefCount(objPtr);
06188     }
06189     Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
06190     return TCL_OK;
06191 }
06192 
06193 static int
06194 ExprRandFunc(
06195     ClientData clientData,      /* Ignored. */
06196     Tcl_Interp *interp,         /* The interpreter in which to execute the
06197                                  * function. */
06198     int objc,                   /* Actual parameter count. */
06199     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06200 {
06201     Interp *iPtr = (Interp *) interp;
06202     double dResult;
06203     long tmp;                   /* Algorithm assumes at least 32 bits. Only
06204                                  * long guarantees that. See below. */
06205     Tcl_Obj *oResult;
06206 
06207     if (objc != 1) {
06208         MathFuncWrongNumArgs(interp, 1, objc, objv);
06209         return TCL_ERROR;
06210     }
06211 
06212     if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
06213         iPtr->flags |= RAND_SEED_INITIALIZED;
06214 
06215         /*
06216          * Take into consideration the thread this interp is running in order
06217          * to insure different seeds in different threads (bug #416643)
06218          */
06219 
06220         iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
06221 
06222         /*
06223          * Make sure 1 <= randSeed <= (2^31) - 2. See below.
06224          */
06225 
06226         iPtr->randSeed &= (unsigned long) 0x7fffffff;
06227         if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
06228             iPtr->randSeed ^= 123459876;
06229         }
06230     }
06231 
06232     /*
06233      * Generate the random number using the linear congruential generator
06234      * defined by the following recurrence:
06235      *          seed = ( IA * seed ) mod IM
06236      * where IA is 16807 and IM is (2^31) - 1. The recurrence maps a seed in
06237      * the range [1, IM - 1] to a new seed in that same range. The recurrence
06238      * maps IM to 0, and maps 0 back to 0, so those two values must not be
06239      * allowed as initial values of seed.
06240      *
06241      * In order to avoid potential problems with integer overflow, the
06242      * recurrence is implemented in terms of additional constants IQ and IR
06243      * such that
06244      *          IM = IA*IQ + IR
06245      * None of the operations in the implementation overflows a 32-bit signed
06246      * integer, and the C type long is guaranteed to be at least 32 bits wide.
06247      *
06248      * For more details on how this algorithm works, refer to the following
06249      * papers:
06250      *
06251      *  S.K. Park & K.W. Miller, "Random number generators: good ones are hard
06252      *  to find," Comm ACM 31(10):1192-1201, Oct 1988
06253      *
06254      *  W.H. Press & S.A. Teukolsky, "Portable random number generators,"
06255      *  Computers in Physics 6(5):522-524, Sep/Oct 1992.
06256      */
06257 
06258 #define RAND_IA         16807
06259 #define RAND_IM         2147483647
06260 #define RAND_IQ         127773
06261 #define RAND_IR         2836
06262 #define RAND_MASK       123459876
06263 
06264     tmp = iPtr->randSeed/RAND_IQ;
06265     iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
06266     if (iPtr->randSeed < 0) {
06267         iPtr->randSeed += RAND_IM;
06268     }
06269 
06270     /*
06271      * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
06272      * dividing by RAND_IM yields a double in the range (0, 1).
06273      */
06274 
06275     dResult = iPtr->randSeed * (1.0/RAND_IM);
06276 
06277     /*
06278      * Push a Tcl object with the result.
06279      */
06280 
06281     TclNewDoubleObj(oResult, dResult);
06282     Tcl_SetObjResult(interp, oResult);
06283     return TCL_OK;
06284 }
06285 
06286 static int
06287 ExprRoundFunc(
06288     ClientData clientData,      /* Ignored. */
06289     Tcl_Interp *interp,         /* The interpreter in which to execute the
06290                                  * function. */
06291     int objc,                   /* Actual parameter count. */
06292     Tcl_Obj *const *objv)       /* Parameter vector. */
06293 {
06294     double d;
06295     ClientData ptr;
06296     int type;
06297 
06298     if (objc != 2) {
06299         MathFuncWrongNumArgs(interp, 1, objc, objv);
06300         return TCL_ERROR;
06301     }
06302 
06303     if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
06304         return TCL_ERROR;
06305     }
06306 
06307     if (type == TCL_NUMBER_DOUBLE) {
06308         double fractPart, intPart;
06309         long max = LONG_MAX, min = LONG_MIN;
06310 
06311         fractPart = modf(*((const double *) ptr), &intPart);
06312         if (fractPart <= -0.5) {
06313             min++;
06314         } else if (fractPart >= 0.5) {
06315             max--;
06316         }
06317         if ((intPart >= (double)max) || (intPart <= (double)min)) {
06318             mp_int big;
06319 
06320             if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) {
06321                 /* Infinity */
06322                 return TCL_ERROR;
06323             }
06324             if (fractPart <= -0.5) {
06325                 mp_sub_d(&big, 1, &big);
06326             } else if (fractPart >= 0.5) {
06327                 mp_add_d(&big, 1, &big);
06328             }
06329             Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
06330             return TCL_OK;
06331         } else {
06332             long result = (long)intPart;
06333 
06334             if (fractPart <= -0.5) {
06335                 result--;
06336             } else if (fractPart >= 0.5) {
06337                 result++;
06338             }
06339             Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
06340             return TCL_OK;
06341         }
06342     }
06343 
06344     if (type != TCL_NUMBER_NAN) {
06345         /*
06346          * All integers are already rounded
06347          */
06348 
06349         Tcl_SetObjResult(interp, objv[1]);
06350         return TCL_OK;
06351     }
06352 
06353     /*
06354      * Get the error message for NaN.
06355      */
06356 
06357     Tcl_GetDoubleFromObj(interp, objv[1], &d);
06358     return TCL_ERROR;
06359 }
06360 
06361 static int
06362 ExprSrandFunc(
06363     ClientData clientData,      /* Ignored. */
06364     Tcl_Interp *interp,         /* The interpreter in which to execute the
06365                                  * function. */
06366     int objc,                   /* Actual parameter count. */
06367     Tcl_Obj *const *objv)       /* Parameter vector. */
06368 {
06369     Interp *iPtr = (Interp *) interp;
06370     long i = 0;                 /* Initialized to avoid compiler warning. */
06371 
06372     /*
06373      * Convert argument and use it to reset the seed.
06374      */
06375 
06376     if (objc != 2) {
06377         MathFuncWrongNumArgs(interp, 2, objc, objv);
06378         return TCL_ERROR;
06379     }
06380 
06381     if (TclGetLongFromObj(NULL, objv[1], &i) != TCL_OK) {
06382         Tcl_Obj *objPtr;
06383         mp_int big;
06384 
06385         if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
06386             /* TODO: more ::errorInfo here? or in caller? */
06387             return TCL_ERROR;
06388         }
06389 
06390         mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
06391         objPtr = Tcl_NewBignumObj(&big);
06392         Tcl_IncrRefCount(objPtr);
06393         TclGetLongFromObj(NULL, objPtr, &i);
06394         Tcl_DecrRefCount(objPtr);
06395     }
06396 
06397     /*
06398      * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2. See comments in
06399      * ExprRandFunc() for more details.
06400      */
06401 
06402     iPtr->flags |= RAND_SEED_INITIALIZED;
06403     iPtr->randSeed = i;
06404     iPtr->randSeed &= (unsigned long) 0x7fffffff;
06405     if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
06406         iPtr->randSeed ^= 123459876;
06407     }
06408 
06409     /*
06410      * To avoid duplicating the random number generation code we simply clean
06411      * up our state and call the real random number function. That function
06412      * will always succeed.
06413      */
06414 
06415     return ExprRandFunc(clientData, interp, 1, objv);
06416 }
06417 
06418 /*
06419  *----------------------------------------------------------------------
06420  *
06421  * MathFuncWrongNumArgs --
06422  *
06423  *      Generate an error message when a math function presents the wrong
06424  *      number of arguments.
06425  *
06426  * Results:
06427  *      None.
06428  *
06429  * Side effects:
06430  *      An error message is stored in the interpreter result.
06431  *
06432  *----------------------------------------------------------------------
06433  */
06434 
06435 static void
06436 MathFuncWrongNumArgs(
06437     Tcl_Interp *interp,         /* Tcl interpreter */
06438     int expected,               /* Formal parameter count. */
06439     int found,                  /* Actual parameter count. */
06440     Tcl_Obj *const *objv)       /* Actual parameter vector. */
06441 {
06442     const char *name = Tcl_GetString(objv[0]);
06443     const char *tail = name + strlen(name);
06444 
06445     while (tail > name+1) {
06446         --tail;
06447         if (*tail == ':' && tail[-1] == ':') {
06448             name = tail+1;
06449             break;
06450         }
06451     }
06452     Tcl_SetObjResult(interp, Tcl_ObjPrintf(
06453             "too %s arguments for math function \"%s\"",
06454             (found < expected ? "few" : "many"), name));
06455 }
06456 #ifdef USE_DTRACE
06457 
06458 /*
06459  *----------------------------------------------------------------------
06460  *
06461  * DTraceObjCmd --
06462  *
06463  *      This function is invoked to process the "::tcl::dtrace" Tcl command.
06464  *
06465  * Results:
06466  *      A standard Tcl object result.
06467  *
06468  * Side effects:
06469  *      The 'tcl-probe' DTrace probe is triggered (if it is enabled).
06470  *
06471  *----------------------------------------------------------------------
06472  */
06473 
06474 static int
06475 DTraceObjCmd(
06476     ClientData dummy,           /* Not used. */
06477     Tcl_Interp *interp,         /* Current interpreter. */
06478     int objc,                   /* Number of arguments. */
06479     Tcl_Obj *const objv[])      /* Argument objects. */
06480 {
06481     if (TCL_DTRACE_TCL_PROBE_ENABLED()) {
06482         char *a[10];
06483         int i = 0;
06484 
06485         while (i++ < 10) {
06486             a[i-1] = i < objc ? TclGetString(objv[i]) : NULL;
06487         }
06488         TCL_DTRACE_TCL_PROBE(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
06489                 a[8], a[9]);
06490     }
06491     return TCL_OK;
06492 }
06493 
06494 /*
06495  *----------------------------------------------------------------------
06496  *
06497  * TclDTraceInfo --
06498  *
06499  *      Extract information from a TIP280 dict for use by DTrace probes.
06500  *
06501  * Results:
06502  *      None.
06503  *
06504  * Side effects:
06505  *      None.
06506  *
06507  *----------------------------------------------------------------------
06508  */
06509 
06510 void
06511 TclDTraceInfo(
06512     Tcl_Obj *info,
06513     char **args,
06514     int *argsi)
06515 {
06516     static Tcl_Obj *keys[7] = { NULL };
06517     Tcl_Obj **k = keys, *val;
06518     int i;
06519 
06520     if (!*k) {
06521         TclNewLiteralStringObj(keys[0], "cmd");
06522         TclNewLiteralStringObj(keys[1], "type");
06523         TclNewLiteralStringObj(keys[2], "proc");
06524         TclNewLiteralStringObj(keys[3], "file");
06525         TclNewLiteralStringObj(keys[4], "lambda");
06526         TclNewLiteralStringObj(keys[5], "line");
06527         TclNewLiteralStringObj(keys[6], "level");
06528     }
06529     for (i = 0; i < 4; i++) {
06530         Tcl_DictObjGet(NULL, info, *k++, &val);
06531         args[i] = val ? TclGetString(val) : NULL;
06532     }
06533     if (!args[2]) {
06534         Tcl_DictObjGet(NULL, info, *k, &val);
06535         args[2] = val ? TclGetString(val) : NULL;
06536     }
06537     k++;
06538     for (i = 0; i < 2; i++) {
06539         Tcl_DictObjGet(NULL, info, *k++, &val);
06540         if (val) {
06541             TclGetIntFromObj(NULL, val, &(argsi[i]));
06542         } else {
06543             argsi[i] = 0;
06544         }
06545     }
06546 }
06547 #endif /* USE_DTRACE */
06548 
06549 /*
06550  * Local Variables:
06551  * mode: c
06552  * c-basic-offset: 4
06553  * fill-column: 78
06554  * End:
06555  */



Generated on Wed Mar 12 12:18:11 2008 by  doxygen 1.5.1