tclBasic.cGo 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 ![]() |