tclBasic.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:180k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclBasic.c --
  3.  *
  4.  * Contains the basic facilities for TCL command interpretation,
  5.  * including interpreter creation and deletion, command creation
  6.  * and deletion, and command/script execution. 
  7.  *
  8.  * Copyright (c) 1987-1994 The Regents of the University of California.
  9.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  10.  * Copyright (c) 1998-1999 by Scriptics Corporation.
  11.  * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
  12.  * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
  13.  *
  14.  * See the file "license.terms" for information on usage and redistribution
  15.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  16.  *
  17.  * RCS: @(#) $Id: tclBasic.c,v 1.75.2.28 2007/09/13 16:13:19 das Exp $
  18.  */
  19. #include "tclInt.h"
  20. #include "tclCompile.h"
  21. #ifndef TCL_GENERIC_ONLY
  22. #   include "tclPort.h"
  23. #endif
  24. /*
  25.  * Static procedures in this file:
  26.  */
  27. static char * CallCommandTraces _ANSI_ARGS_((Interp *iPtr, 
  28.     Command *cmdPtr, CONST char *oldName, 
  29.     CONST char* newName, int flags));
  30. static void DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
  31. static void ProcessUnexpectedResult _ANSI_ARGS_((
  32.     Tcl_Interp *interp, int returnCode));
  33. static int         StringTraceProc _ANSI_ARGS_((ClientData clientData,
  34.      Tcl_Interp* interp,
  35.      int level,
  36.      CONST char* command,
  37.     Tcl_Command commandInfo,
  38.     int objc,
  39.     Tcl_Obj *CONST objv[]));
  40. static void           StringTraceDeleteProc _ANSI_ARGS_((ClientData clientData));
  41. #ifdef TCL_TIP280
  42. /* TIP #280 - Modified token based evulation, with line information */
  43. static int            EvalEx _ANSI_ARGS_((Tcl_Interp *interp, CONST char *script,
  44.   int numBytes, int flags, int line));
  45. static int            EvalTokensStandard _ANSI_ARGS_((Tcl_Interp *interp,
  46.       Tcl_Token *tokenPtr,
  47.       int count, int line));
  48. #endif
  49. #ifdef USE_DTRACE
  50. static int DTraceObjCmd(ClientData dummy, Tcl_Interp *interp, int objc,
  51.     Tcl_Obj *CONST objv[]);
  52. #endif
  53. extern TclStubs tclStubs;
  54. /*
  55.  * The following structure defines the commands in the Tcl core.
  56.  */
  57. typedef struct {
  58.     char *name; /* Name of object-based command. */
  59.     Tcl_CmdProc *proc; /* String-based procedure for command. */
  60.     Tcl_ObjCmdProc *objProc; /* Object-based procedure for command. */
  61.     CompileProc *compileProc; /* Procedure called to compile command. */
  62.     int isSafe; /* If non-zero, command will be present
  63.                                  * in safe interpreter. Otherwise it will
  64.                                  * be hidden. */
  65. } CmdInfo;
  66. /*
  67.  * The built-in commands, and the procedures that implement them:
  68.  */
  69. static CmdInfo builtInCmds[] = {
  70.     /*
  71.      * Commands in the generic core. Note that at least one of the proc or
  72.      * objProc members should be non-NULL. This avoids infinitely recursive
  73.      * calls between TclInvokeObjectCommand and TclInvokeStringCommand if a
  74.      * command name is computed at runtime and results in the name of a
  75.      * compiled command.
  76.      */
  77.     {"append", (Tcl_CmdProc *) NULL, Tcl_AppendObjCmd,
  78. TclCompileAppendCmd, 1},
  79.     {"array", (Tcl_CmdProc *) NULL, Tcl_ArrayObjCmd,
  80.         (CompileProc *) NULL, 1},
  81.     {"binary", (Tcl_CmdProc *) NULL, Tcl_BinaryObjCmd,
  82.         (CompileProc *) NULL, 1},
  83.     {"break", (Tcl_CmdProc *) NULL, Tcl_BreakObjCmd,
  84.         TclCompileBreakCmd, 1},
  85.     {"case", (Tcl_CmdProc *) NULL, Tcl_CaseObjCmd,
  86.         (CompileProc *) NULL, 1},
  87.     {"catch", (Tcl_CmdProc *) NULL, Tcl_CatchObjCmd,
  88.         TclCompileCatchCmd, 1},
  89.     {"clock", (Tcl_CmdProc *) NULL, Tcl_ClockObjCmd,
  90.         (CompileProc *) NULL, 1},
  91.     {"concat", (Tcl_CmdProc *) NULL, Tcl_ConcatObjCmd,
  92.         (CompileProc *) NULL, 1},
  93.     {"continue", (Tcl_CmdProc *) NULL, Tcl_ContinueObjCmd,
  94.         TclCompileContinueCmd, 1},
  95.     {"encoding", (Tcl_CmdProc *) NULL, Tcl_EncodingObjCmd,
  96.         (CompileProc *) NULL, 0},
  97.     {"error", (Tcl_CmdProc *) NULL, Tcl_ErrorObjCmd,
  98.         (CompileProc *) NULL, 1},
  99.     {"eval", (Tcl_CmdProc *) NULL, Tcl_EvalObjCmd,
  100.         (CompileProc *) NULL, 1},
  101.     {"exit", (Tcl_CmdProc *) NULL, Tcl_ExitObjCmd,
  102.         (CompileProc *) NULL, 0},
  103.     {"expr", (Tcl_CmdProc *) NULL, Tcl_ExprObjCmd,
  104.         TclCompileExprCmd, 1},
  105.     {"fcopy", (Tcl_CmdProc *) NULL, Tcl_FcopyObjCmd,
  106.         (CompileProc *) NULL, 1},
  107.     {"fileevent", (Tcl_CmdProc *) NULL, Tcl_FileEventObjCmd,
  108.         (CompileProc *) NULL, 1},
  109.     {"for", (Tcl_CmdProc *) NULL, Tcl_ForObjCmd,
  110.         TclCompileForCmd, 1},
  111.     {"foreach", (Tcl_CmdProc *) NULL, Tcl_ForeachObjCmd,
  112.         TclCompileForeachCmd, 1},
  113.     {"format", (Tcl_CmdProc *) NULL, Tcl_FormatObjCmd,
  114.         (CompileProc *) NULL, 1},
  115.     {"global", (Tcl_CmdProc *) NULL, Tcl_GlobalObjCmd,
  116.         (CompileProc *) NULL, 1},
  117.     {"if", (Tcl_CmdProc *) NULL, Tcl_IfObjCmd,
  118.         TclCompileIfCmd, 1},
  119.     {"incr", (Tcl_CmdProc *) NULL, Tcl_IncrObjCmd,
  120.         TclCompileIncrCmd, 1},
  121.     {"info", (Tcl_CmdProc *) NULL, Tcl_InfoObjCmd,
  122.         (CompileProc *) NULL, 1},
  123.     {"join", (Tcl_CmdProc *) NULL, Tcl_JoinObjCmd,
  124.         (CompileProc *) NULL, 1},
  125.     {"lappend", (Tcl_CmdProc *) NULL, Tcl_LappendObjCmd,
  126.         TclCompileLappendCmd, 1},
  127.     {"lindex", (Tcl_CmdProc *) NULL, Tcl_LindexObjCmd,
  128.         TclCompileLindexCmd, 1},
  129.     {"linsert", (Tcl_CmdProc *) NULL, Tcl_LinsertObjCmd,
  130.         (CompileProc *) NULL, 1},
  131.     {"list", (Tcl_CmdProc *) NULL, Tcl_ListObjCmd,
  132.         TclCompileListCmd, 1},
  133.     {"llength", (Tcl_CmdProc *) NULL, Tcl_LlengthObjCmd,
  134.         TclCompileLlengthCmd, 1},
  135.     {"load", (Tcl_CmdProc *) NULL, Tcl_LoadObjCmd,
  136.         (CompileProc *) NULL, 0},
  137.     {"lrange", (Tcl_CmdProc *) NULL, Tcl_LrangeObjCmd,
  138.         (CompileProc *) NULL, 1},
  139.     {"lreplace", (Tcl_CmdProc *) NULL, Tcl_LreplaceObjCmd,
  140.         (CompileProc *) NULL, 1},
  141.     {"lsearch", (Tcl_CmdProc *) NULL, Tcl_LsearchObjCmd,
  142.         (CompileProc *) NULL, 1},
  143.     {"lset",            (Tcl_CmdProc *) NULL,   Tcl_LsetObjCmd,
  144.         TclCompileLsetCmd,            1},
  145.     {"lsort", (Tcl_CmdProc *) NULL, Tcl_LsortObjCmd,
  146.         (CompileProc *) NULL, 1},
  147.     {"namespace", (Tcl_CmdProc *) NULL, Tcl_NamespaceObjCmd,
  148.         (CompileProc *) NULL, 1},
  149.     {"package", (Tcl_CmdProc *) NULL, Tcl_PackageObjCmd,
  150.         (CompileProc *) NULL, 1},
  151.     {"proc", (Tcl_CmdProc *) NULL, Tcl_ProcObjCmd,
  152.         (CompileProc *) NULL, 1},
  153.     {"regexp", (Tcl_CmdProc *) NULL, Tcl_RegexpObjCmd,
  154.         TclCompileRegexpCmd, 1},
  155.     {"regsub", (Tcl_CmdProc *) NULL, Tcl_RegsubObjCmd,
  156.         (CompileProc *) NULL, 1},
  157.     {"rename", (Tcl_CmdProc *) NULL, Tcl_RenameObjCmd,
  158.         (CompileProc *) NULL, 1},
  159.     {"return", (Tcl_CmdProc *) NULL, Tcl_ReturnObjCmd,
  160.         TclCompileReturnCmd, 1},
  161.     {"scan", (Tcl_CmdProc *) NULL, Tcl_ScanObjCmd,
  162.         (CompileProc *) NULL, 1},
  163.     {"set", (Tcl_CmdProc *) NULL, Tcl_SetObjCmd,
  164.         TclCompileSetCmd, 1},
  165.     {"split", (Tcl_CmdProc *) NULL, Tcl_SplitObjCmd,
  166.         (CompileProc *) NULL, 1},
  167.     {"string", (Tcl_CmdProc *) NULL, Tcl_StringObjCmd,
  168.         TclCompileStringCmd, 1},
  169.     {"subst", (Tcl_CmdProc *) NULL, Tcl_SubstObjCmd,
  170.         (CompileProc *) NULL, 1},
  171.     {"switch", (Tcl_CmdProc *) NULL, Tcl_SwitchObjCmd,
  172.         (CompileProc *) NULL, 1},
  173.     {"trace", (Tcl_CmdProc *) NULL, Tcl_TraceObjCmd,
  174.         (CompileProc *) NULL, 1},
  175.     {"unset", (Tcl_CmdProc *) NULL, Tcl_UnsetObjCmd,
  176.         (CompileProc *) NULL, 1},
  177.     {"uplevel", (Tcl_CmdProc *) NULL, Tcl_UplevelObjCmd,
  178.         (CompileProc *) NULL, 1},
  179.     {"upvar", (Tcl_CmdProc *) NULL, Tcl_UpvarObjCmd,
  180.         (CompileProc *) NULL, 1},
  181.     {"variable", (Tcl_CmdProc *) NULL, Tcl_VariableObjCmd,
  182.         (CompileProc *) NULL, 1},
  183.     {"while", (Tcl_CmdProc *) NULL, Tcl_WhileObjCmd,
  184.         TclCompileWhileCmd, 1},
  185.     /*
  186.      * Commands in the UNIX core:
  187.      */
  188. #ifndef TCL_GENERIC_ONLY
  189.     {"after", (Tcl_CmdProc *) NULL, Tcl_AfterObjCmd,
  190.         (CompileProc *) NULL, 1},
  191.     {"cd", (Tcl_CmdProc *) NULL, Tcl_CdObjCmd,
  192.         (CompileProc *) NULL, 0},
  193.     {"close", (Tcl_CmdProc *) NULL, Tcl_CloseObjCmd,
  194.         (CompileProc *) NULL, 1},
  195.     {"eof", (Tcl_CmdProc *) NULL, Tcl_EofObjCmd,
  196.         (CompileProc *) NULL, 1},
  197.     {"fblocked", (Tcl_CmdProc *) NULL, Tcl_FblockedObjCmd,
  198.         (CompileProc *) NULL, 1},
  199.     {"fconfigure", (Tcl_CmdProc *) NULL, Tcl_FconfigureObjCmd,
  200.         (CompileProc *) NULL, 0},
  201.     {"file", (Tcl_CmdProc *) NULL, Tcl_FileObjCmd,
  202.         (CompileProc *) NULL, 0},
  203.     {"flush", (Tcl_CmdProc *) NULL, Tcl_FlushObjCmd,
  204.         (CompileProc *) NULL, 1},
  205.     {"gets", (Tcl_CmdProc *) NULL, Tcl_GetsObjCmd,
  206.         (CompileProc *) NULL, 1},
  207.     {"glob", (Tcl_CmdProc *) NULL, Tcl_GlobObjCmd,
  208.         (CompileProc *) NULL, 0},
  209.     {"open", (Tcl_CmdProc *) NULL, Tcl_OpenObjCmd,
  210.         (CompileProc *) NULL, 0},
  211.     {"pid", (Tcl_CmdProc *) NULL, Tcl_PidObjCmd,
  212.         (CompileProc *) NULL, 1},
  213.     {"puts", (Tcl_CmdProc *) NULL, Tcl_PutsObjCmd,
  214.         (CompileProc *) NULL, 1},
  215.     {"pwd", (Tcl_CmdProc *) NULL, Tcl_PwdObjCmd,
  216.         (CompileProc *) NULL, 0},
  217.     {"read", (Tcl_CmdProc *) NULL, Tcl_ReadObjCmd,
  218.         (CompileProc *) NULL, 1},
  219.     {"seek", (Tcl_CmdProc *) NULL, Tcl_SeekObjCmd,
  220.         (CompileProc *) NULL, 1},
  221.     {"socket", (Tcl_CmdProc *) NULL, Tcl_SocketObjCmd,
  222.         (CompileProc *) NULL, 0},
  223.     {"tell", (Tcl_CmdProc *) NULL, Tcl_TellObjCmd,
  224.         (CompileProc *) NULL, 1},
  225.     {"time", (Tcl_CmdProc *) NULL, Tcl_TimeObjCmd,
  226.         (CompileProc *) NULL, 1},
  227.     {"update", (Tcl_CmdProc *) NULL, Tcl_UpdateObjCmd,
  228.         (CompileProc *) NULL, 1},
  229.     {"vwait", (Tcl_CmdProc *) NULL, Tcl_VwaitObjCmd,
  230.         (CompileProc *) NULL, 1},
  231.     
  232. #ifdef MAC_TCL
  233.     {"beep", (Tcl_CmdProc *) NULL, Tcl_BeepObjCmd,
  234.         (CompileProc *) NULL, 0},
  235.     {"echo", Tcl_EchoCmd, (Tcl_ObjCmdProc *) NULL,
  236.         (CompileProc *) NULL, 0},
  237.     {"ls", (Tcl_CmdProc *) NULL,  Tcl_LsObjCmd,
  238.         (CompileProc *) NULL, 0},
  239.     {"resource", (Tcl_CmdProc *) NULL, Tcl_ResourceObjCmd,
  240.         (CompileProc *) NULL, 1},
  241.     {"source", (Tcl_CmdProc *) NULL, Tcl_MacSourceObjCmd,
  242.         (CompileProc *) NULL, 0},
  243. #else
  244.     {"exec", (Tcl_CmdProc *) NULL, Tcl_ExecObjCmd,
  245.         (CompileProc *) NULL, 0},
  246.     {"source", (Tcl_CmdProc *) NULL, Tcl_SourceObjCmd,
  247.         (CompileProc *) NULL, 0},
  248. #endif /* MAC_TCL */
  249.     
  250. #endif /* TCL_GENERIC_ONLY */
  251.     {NULL, (Tcl_CmdProc *) NULL, (Tcl_ObjCmdProc *) NULL,
  252.         (CompileProc *) NULL, 0}
  253. };
  254. /*
  255.  * The following structure holds the client data for string-based
  256.  * trace procs
  257.  */
  258. typedef struct StringTraceData {
  259.     ClientData clientData; /* Client data from Tcl_CreateTrace */
  260.     Tcl_CmdTraceProc* proc; /* Trace procedure from Tcl_CreateTrace */
  261. } StringTraceData;
  262. /*
  263.  *----------------------------------------------------------------------
  264.  *
  265.  * Tcl_CreateInterp --
  266.  *
  267.  * Create a new TCL command interpreter.
  268.  *
  269.  * Results:
  270.  * The return value is a token for the interpreter, which may be
  271.  * used in calls to procedures like Tcl_CreateCmd, Tcl_Eval, or
  272.  * Tcl_DeleteInterp.
  273.  *
  274.  * Side effects:
  275.  * The command interpreter is initialized with the built-in commands
  276.  *      and with the variables documented in tclvars(n).
  277.  *
  278.  *----------------------------------------------------------------------
  279.  */
  280. Tcl_Interp *
  281. Tcl_CreateInterp()
  282. {
  283.     Interp *iPtr;
  284.     Tcl_Interp *interp;
  285.     Command *cmdPtr;
  286.     BuiltinFunc *builtinFuncPtr;
  287.     MathFunc *mathFuncPtr;
  288.     Tcl_HashEntry *hPtr;
  289.     CmdInfo *cmdInfoPtr;
  290.     int i;
  291.     union {
  292. char c[sizeof(short)];
  293. short s;
  294.     } order;
  295. #ifdef TCL_COMPILE_STATS
  296.     ByteCodeStats *statsPtr;
  297. #endif /* TCL_COMPILE_STATS */
  298.     TclInitSubsystems(NULL);
  299.     /*
  300.      * Panic if someone updated the CallFrame structure without
  301.      * also updating the Tcl_CallFrame structure (or vice versa).
  302.      */  
  303.     if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
  304. /*NOTREACHED*/
  305.         panic("Tcl_CallFrame and CallFrame are not the same size");
  306.     }
  307.     /*
  308.      * Initialize support for namespaces and create the global namespace
  309.      * (whose name is ""; an alias is "::"). This also initializes the
  310.      * Tcl object type table and other object management code.
  311.      */
  312.     iPtr = (Interp *) ckalloc(sizeof(Interp));
  313.     interp = (Tcl_Interp *) iPtr;
  314.     iPtr->result = iPtr->resultSpace;
  315.     iPtr->freeProc = NULL;
  316.     iPtr->errorLine = 0;
  317.     iPtr->objResultPtr = Tcl_NewObj();
  318.     Tcl_IncrRefCount(iPtr->objResultPtr);
  319.     iPtr->handle = TclHandleCreate(iPtr);
  320.     iPtr->globalNsPtr = NULL;
  321.     iPtr->hiddenCmdTablePtr = NULL;
  322.     iPtr->interpInfo = NULL;
  323.     Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS);
  324.     iPtr->numLevels = 0;
  325.     iPtr->maxNestingDepth = MAX_NESTING_DEPTH;
  326.     iPtr->framePtr = NULL;
  327.     iPtr->varFramePtr = NULL;
  328. #ifdef TCL_TIP280
  329.     /*
  330.      * TIP #280 - Initialize the arrays used to extend the ByteCode and
  331.      * Proc structures.
  332.      */
  333.     iPtr->cmdFramePtr  = NULL;
  334.     iPtr->linePBodyPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
  335.     iPtr->lineBCPtr    = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
  336.     Tcl_InitHashTable(iPtr->linePBodyPtr, TCL_ONE_WORD_KEYS);
  337.     Tcl_InitHashTable(iPtr->lineBCPtr,    TCL_ONE_WORD_KEYS);
  338. #endif
  339.     iPtr->activeVarTracePtr = NULL;
  340.     iPtr->returnCode = TCL_OK;
  341.     iPtr->errorInfo = NULL;
  342.     iPtr->errorCode = NULL;
  343.     iPtr->appendResult = NULL;
  344.     iPtr->appendAvl = 0;
  345.     iPtr->appendUsed = 0;
  346.     Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
  347.     iPtr->packageUnknown = NULL;
  348. #ifdef TCL_TIP268
  349.     /* TIP #268 */
  350.     iPtr->packagePrefer = (getenv ("TCL_PKG_PREFER_LATEST") == NULL ? 
  351.    PKG_PREFER_STABLE   :
  352.    PKG_PREFER_LATEST);
  353. #endif
  354.     iPtr->cmdCount = 0;
  355.     iPtr->termOffset = 0;
  356.     TclInitLiteralTable(&(iPtr->literalTable));
  357.     iPtr->compileEpoch = 0;
  358.     iPtr->compiledProcPtr = NULL;
  359.     iPtr->resolverPtr = NULL;
  360.     iPtr->evalFlags = 0;
  361.     iPtr->scriptFile = NULL;
  362.     iPtr->flags = 0;
  363.     iPtr->tracePtr = NULL;
  364.     iPtr->tracesForbiddingInline = 0;
  365.     iPtr->activeCmdTracePtr = NULL;
  366.     iPtr->activeInterpTracePtr = NULL;
  367.     iPtr->assocData = (Tcl_HashTable *) NULL;
  368.     iPtr->execEnvPtr = NULL;       /* set after namespaces initialized */
  369.     iPtr->emptyObjPtr = Tcl_NewObj(); /* another empty object */
  370.     Tcl_IncrRefCount(iPtr->emptyObjPtr);
  371.     iPtr->resultSpace[0] = 0;
  372.     iPtr->threadId = Tcl_GetCurrentThread();
  373.     iPtr->globalNsPtr = NULL; /* force creation of global ns below */
  374.     iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
  375.     (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
  376.     if (iPtr->globalNsPtr == NULL) {
  377.         panic("Tcl_CreateInterp: can't create global namespace");
  378.     }
  379.     /*
  380.      * Initialize support for code compilation and execution. We call
  381.      * TclCreateExecEnv after initializing namespaces since it tries to
  382.      * reference a Tcl variable (it links to the Tcl "tcl_traceExec"
  383.      * variable).
  384.      */
  385.     iPtr->execEnvPtr = TclCreateExecEnv(interp);
  386.     /*
  387.      * Initialize the compilation and execution statistics kept for this
  388.      * interpreter.
  389.      */
  390. #ifdef TCL_COMPILE_STATS
  391.     statsPtr = &(iPtr->stats);
  392.     statsPtr->numExecutions = 0;
  393.     statsPtr->numCompilations = 0;
  394.     statsPtr->numByteCodesFreed = 0;
  395.     (VOID *) memset(statsPtr->instructionCount, 0,
  396.     sizeof(statsPtr->instructionCount));
  397.     statsPtr->totalSrcBytes = 0.0;
  398.     statsPtr->totalByteCodeBytes = 0.0;
  399.     statsPtr->currentSrcBytes = 0.0;
  400.     statsPtr->currentByteCodeBytes = 0.0;
  401.     (VOID *) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
  402.     (VOID *) memset(statsPtr->byteCodeCount, 0,
  403.     sizeof(statsPtr->byteCodeCount));
  404.     (VOID *) memset(statsPtr->lifetimeCount, 0,
  405.     sizeof(statsPtr->lifetimeCount));
  406.     
  407.     statsPtr->currentInstBytes   = 0.0;
  408.     statsPtr->currentLitBytes    = 0.0;
  409.     statsPtr->currentExceptBytes = 0.0;
  410.     statsPtr->currentAuxBytes    = 0.0;
  411.     statsPtr->currentCmdMapBytes = 0.0;
  412.     
  413.     statsPtr->numLiteralsCreated    = 0;
  414.     statsPtr->totalLitStringBytes   = 0.0;
  415.     statsPtr->currentLitStringBytes = 0.0;
  416.     (VOID *) memset(statsPtr->literalCount, 0,
  417.             sizeof(statsPtr->literalCount));
  418. #endif /* TCL_COMPILE_STATS */    
  419.     /*
  420.      * Initialise the stub table pointer.
  421.      */
  422.     iPtr->stubTable = &tclStubs;
  423.     
  424.     /*
  425.      * Create the core commands. Do it here, rather than calling
  426.      * Tcl_CreateCommand, because it's faster (there's no need to check for
  427.      * a pre-existing command by the same name). If a command has a
  428.      * Tcl_CmdProc but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
  429.      * TclInvokeStringCommand. This is an object-based wrapper procedure
  430.      * that extracts strings, calls the string procedure, and creates an
  431.      * object for the result. Similarly, if a command has a Tcl_ObjCmdProc
  432.      * but no Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
  433.      */
  434.     for (cmdInfoPtr = builtInCmds;  cmdInfoPtr->name != NULL;
  435.     cmdInfoPtr++) {
  436. int new;
  437. Tcl_HashEntry *hPtr;
  438. if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)
  439.         && (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
  440.         && (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
  441.     panic("Tcl_CreateInterp: builtin command with NULL string and object command procs and a NULL compile procn");
  442. }
  443. hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
  444.         cmdInfoPtr->name, &new);
  445. if (new) {
  446.     cmdPtr = (Command *) ckalloc(sizeof(Command));
  447.     cmdPtr->hPtr = hPtr;
  448.     cmdPtr->nsPtr = iPtr->globalNsPtr;
  449.     cmdPtr->refCount = 1;
  450.     cmdPtr->cmdEpoch = 0;
  451.     cmdPtr->compileProc = cmdInfoPtr->compileProc;
  452.     if (cmdInfoPtr->proc == (Tcl_CmdProc *) NULL) {
  453. cmdPtr->proc = TclInvokeObjectCommand;
  454. cmdPtr->clientData = (ClientData) cmdPtr;
  455.     } else {
  456. cmdPtr->proc = cmdInfoPtr->proc;
  457. cmdPtr->clientData = (ClientData) NULL;
  458.     }
  459.     if (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
  460. cmdPtr->objProc = TclInvokeStringCommand;
  461. cmdPtr->objClientData = (ClientData) cmdPtr;
  462.     } else {
  463. cmdPtr->objProc = cmdInfoPtr->objProc;
  464. cmdPtr->objClientData = (ClientData) NULL;
  465.     }
  466.     cmdPtr->deleteProc = NULL;
  467.     cmdPtr->deleteData = (ClientData) NULL;
  468.     cmdPtr->flags = 0;
  469.     cmdPtr->importRefPtr = NULL;
  470.     cmdPtr->tracePtr = NULL;
  471.     Tcl_SetHashValue(hPtr, cmdPtr);
  472. }
  473.     }
  474. #ifdef USE_DTRACE
  475.     /*
  476.      * Register the tcl::dtrace command.
  477.      */
  478.     Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL);
  479. #endif /* USE_DTRACE */
  480.     /*
  481.      * Register the builtin math functions.
  482.      */
  483.     i = 0;
  484.     for (builtinFuncPtr = tclBuiltinFuncTable;  builtinFuncPtr->name != NULL;
  485.     builtinFuncPtr++) {
  486. Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name,
  487. builtinFuncPtr->numArgs, builtinFuncPtr->argTypes,
  488. (Tcl_MathProc *) NULL, (ClientData) 0);
  489. hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
  490. builtinFuncPtr->name);
  491. if (hPtr == NULL) {
  492.     panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);
  493.     return NULL;
  494. }
  495. mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
  496. mathFuncPtr->builtinFuncIndex = i;
  497. i++;
  498.     }
  499.     iPtr->flags |= EXPR_INITIALIZED;
  500.     /*
  501.      * Do Multiple/Safe Interps Tcl init stuff
  502.      */
  503.     TclInterpInit(interp);
  504.     /*
  505.      * We used to create the "errorInfo" and "errorCode" global vars at this
  506.      * point because so much of the Tcl implementation assumes they already
  507.      * exist. This is not quite enough, however, since they can be unset
  508.      * at any time.
  509.      *
  510.      * There are 2 choices:
  511.      *    + Check every place where a GetVar of those is used 
  512.      *      and the NULL result is not checked (like in tclLoad.c)
  513.      *    + Make SetVar,... NULL friendly
  514.      * We choose the second option because :
  515.      *    + It is easy and low cost to check for NULL pointer before
  516.      *      calling strlen()
  517.      *    + It can be helpfull to other people using those API
  518.      *    + Passing a NULL value to those closest 'meaning' is empty string
  519.      *      (specially with the new objects where 0 bytes strings are ok)
  520.      * So the following init is commented out:              -- dl
  521.      *
  522.      * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL,
  523.      *       "", TCL_GLOBAL_ONLY);
  524.      * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL,
  525.      *       "NONE", TCL_GLOBAL_ONLY);
  526.      */
  527. #ifndef TCL_GENERIC_ONLY
  528.     TclSetupEnv(interp);
  529. #endif
  530.     /*
  531.      * Compute the byte order of this machine.
  532.      */
  533.     order.s = 1;
  534.     Tcl_SetVar2(interp, "tcl_platform", "byteOrder",
  535.     ((order.c[0] == 1) ? "littleEndian" : "bigEndian"),
  536.     TCL_GLOBAL_ONLY);
  537.     Tcl_SetVar2Ex(interp, "tcl_platform", "wordSize",
  538.     Tcl_NewLongObj((long) sizeof(long)), TCL_GLOBAL_ONLY);
  539.     /*
  540.      * Set up other variables such as tcl_version and tcl_library
  541.      */
  542.     Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
  543.     Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
  544.     Tcl_TraceVar2(interp, "tcl_precision", (char *) NULL,
  545.     TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
  546.     TclPrecTraceProc, (ClientData) NULL);
  547.     TclpSetVariables(interp);
  548. #ifdef TCL_THREADS
  549.     /*
  550.      * The existence of the "threaded" element of the tcl_platform array indicates
  551.      * that this particular Tcl shell has been compiled with threads turned on.
  552.      * Using "info exists tcl_platform(threaded)" a Tcl script can introspect on the 
  553.      * interpreter level of thread safety.
  554.      */
  555.     Tcl_SetVar2(interp, "tcl_platform", "threaded", "1",
  556.     TCL_GLOBAL_ONLY);
  557. #endif
  558.     /*
  559.      * Register Tcl's version number.
  560.      * TIP#268: Expose information about its status,
  561.      *          for runtime switches in the core library
  562.      *          and tests.
  563.      */
  564.     Tcl_PkgProvideEx(interp, "Tcl", TCL_VERSION, (ClientData) &tclStubs);
  565. #ifdef TCL_TIP268
  566.     Tcl_SetVar2(interp, "tcl_platform", "tip,268", "1",
  567.     TCL_GLOBAL_ONLY);
  568. #endif
  569. #ifdef TCL_TIP280
  570.     Tcl_SetVar2(interp, "tcl_platform", "tip,280", "1",
  571.     TCL_GLOBAL_ONLY);
  572. #endif
  573. #ifdef Tcl_InitStubs
  574. #undef Tcl_InitStubs
  575. #endif
  576.     Tcl_InitStubs(interp, TCL_VERSION, 1);
  577.     return interp;
  578. }
  579. /*
  580.  *----------------------------------------------------------------------
  581.  *
  582.  * TclHideUnsafeCommands --
  583.  *
  584.  * Hides base commands that are not marked as safe from this
  585.  * interpreter.
  586.  *
  587.  * Results:
  588.  * TCL_OK if it succeeds, TCL_ERROR else.
  589.  *
  590.  * Side effects:
  591.  * Hides functionality in an interpreter.
  592.  *
  593.  *----------------------------------------------------------------------
  594.  */
  595. int
  596. TclHideUnsafeCommands(interp)
  597.     Tcl_Interp *interp; /* Hide commands in this interpreter. */
  598. {
  599.     register CmdInfo *cmdInfoPtr;
  600.     if (interp == (Tcl_Interp *) NULL) {
  601.         return TCL_ERROR;
  602.     }
  603.     for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
  604.         if (!cmdInfoPtr->isSafe) {
  605.             Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
  606.         }
  607.     }
  608.     return TCL_OK;
  609. }
  610. /*
  611.  *--------------------------------------------------------------
  612.  *
  613.  * Tcl_CallWhenDeleted --
  614.  *
  615.  * Arrange for a procedure to be called before a given
  616.  * interpreter is deleted. The procedure is called as soon
  617.  * as Tcl_DeleteInterp is called; if Tcl_CallWhenDeleted is
  618.  * called on an interpreter that has already been deleted,
  619.  * the procedure will be called when the last Tcl_Release is
  620.  * done on the interpreter.
  621.  *
  622.  * Results:
  623.  * None.
  624.  *
  625.  * Side effects:
  626.  * When Tcl_DeleteInterp is invoked to delete interp,
  627.  * proc will be invoked.  See the manual entry for
  628.  * details.
  629.  *
  630.  *--------------------------------------------------------------
  631.  */
  632. void
  633. Tcl_CallWhenDeleted(interp, proc, clientData)
  634.     Tcl_Interp *interp; /* Interpreter to watch. */
  635.     Tcl_InterpDeleteProc *proc; /* Procedure to call when interpreter
  636.  * is about to be deleted. */
  637.     ClientData clientData; /* One-word value to pass to proc. */
  638. {
  639.     Interp *iPtr = (Interp *) interp;
  640.     static Tcl_ThreadDataKey assocDataCounterKey;
  641.     int *assocDataCounterPtr =
  642.     Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int));
  643.     int new;
  644.     char buffer[32 + TCL_INTEGER_SPACE];
  645.     AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));
  646.     Tcl_HashEntry *hPtr;
  647.     sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr);
  648.     (*assocDataCounterPtr)++;
  649.     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
  650.         iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
  651.         Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
  652.     }
  653.     hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &new);
  654.     dPtr->proc = proc;
  655.     dPtr->clientData = clientData;
  656.     Tcl_SetHashValue(hPtr, dPtr);
  657. }
  658. /*
  659.  *--------------------------------------------------------------
  660.  *
  661.  * Tcl_DontCallWhenDeleted --
  662.  *
  663.  * Cancel the arrangement for a procedure to be called when
  664.  * a given interpreter is deleted.
  665.  *
  666.  * Results:
  667.  * None.
  668.  *
  669.  * Side effects:
  670.  * If proc and clientData were previously registered as a
  671.  * callback via Tcl_CallWhenDeleted, they are unregistered.
  672.  * If they weren't previously registered then nothing
  673.  * happens.
  674.  *
  675.  *--------------------------------------------------------------
  676.  */
  677. void
  678. Tcl_DontCallWhenDeleted(interp, proc, clientData)
  679.     Tcl_Interp *interp; /* Interpreter to watch. */
  680.     Tcl_InterpDeleteProc *proc; /* Procedure to call when interpreter
  681.  * is about to be deleted. */
  682.     ClientData clientData; /* One-word value to pass to proc. */
  683. {
  684.     Interp *iPtr = (Interp *) interp;
  685.     Tcl_HashTable *hTablePtr;
  686.     Tcl_HashSearch hSearch;
  687.     Tcl_HashEntry *hPtr;
  688.     AssocData *dPtr;
  689.     hTablePtr = iPtr->assocData;
  690.     if (hTablePtr == (Tcl_HashTable *) NULL) {
  691.         return;
  692.     }
  693.     for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
  694.     hPtr = Tcl_NextHashEntry(&hSearch)) {
  695.         dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
  696.         if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
  697.             ckfree((char *) dPtr);
  698.             Tcl_DeleteHashEntry(hPtr);
  699.             return;
  700.         }
  701.     }
  702. }
  703. /*
  704.  *----------------------------------------------------------------------
  705.  *
  706.  * Tcl_SetAssocData --
  707.  *
  708.  * Creates a named association between user-specified data, a delete
  709.  * function and this interpreter. If the association already exists
  710.  * the data is overwritten with the new data. The delete function will
  711.  * be invoked when the interpreter is deleted.
  712.  *
  713.  * Results:
  714.  * None.
  715.  *
  716.  * Side effects:
  717.  * Sets the associated data, creates the association if needed.
  718.  *
  719.  *----------------------------------------------------------------------
  720.  */
  721. void
  722. Tcl_SetAssocData(interp, name, proc, clientData)
  723.     Tcl_Interp *interp; /* Interpreter to associate with. */
  724.     CONST char *name; /* Name for association. */
  725.     Tcl_InterpDeleteProc *proc; /* Proc to call when interpreter is
  726.                                  * about to be deleted. */
  727.     ClientData clientData; /* One-word value to pass to proc. */
  728. {
  729.     Interp *iPtr = (Interp *) interp;
  730.     AssocData *dPtr;
  731.     Tcl_HashEntry *hPtr;
  732.     int new;
  733.     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
  734.         iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
  735.         Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
  736.     }
  737.     hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &new);
  738.     if (new == 0) {
  739.         dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
  740.     } else {
  741.         dPtr = (AssocData *) ckalloc(sizeof(AssocData));
  742.     }
  743.     dPtr->proc = proc;
  744.     dPtr->clientData = clientData;
  745.     Tcl_SetHashValue(hPtr, dPtr);
  746. }
  747. /*
  748.  *----------------------------------------------------------------------
  749.  *
  750.  * Tcl_DeleteAssocData --
  751.  *
  752.  * Deletes a named association of user-specified data with
  753.  * the specified interpreter.
  754.  *
  755.  * Results:
  756.  * None.
  757.  *
  758.  * Side effects:
  759.  * Deletes the association.
  760.  *
  761.  *----------------------------------------------------------------------
  762.  */
  763. void
  764. Tcl_DeleteAssocData(interp, name)
  765.     Tcl_Interp *interp; /* Interpreter to associate with. */
  766.     CONST char *name; /* Name of association. */
  767. {
  768.     Interp *iPtr = (Interp *) interp;
  769.     AssocData *dPtr;
  770.     Tcl_HashEntry *hPtr;
  771.     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
  772.         return;
  773.     }
  774.     hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
  775.     if (hPtr == (Tcl_HashEntry *) NULL) {
  776.         return;
  777.     }
  778.     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
  779.     if (dPtr->proc != NULL) {
  780.         (dPtr->proc) (dPtr->clientData, interp);
  781.     }
  782.     ckfree((char *) dPtr);
  783.     Tcl_DeleteHashEntry(hPtr);
  784. }
  785. /*
  786.  *----------------------------------------------------------------------
  787.  *
  788.  * Tcl_GetAssocData --
  789.  *
  790.  * Returns the client data associated with this name in the
  791.  * specified interpreter.
  792.  *
  793.  * Results:
  794.  * The client data in the AssocData record denoted by the named
  795.  * association, or NULL.
  796.  *
  797.  * Side effects:
  798.  * None.
  799.  *
  800.  *----------------------------------------------------------------------
  801.  */
  802. ClientData
  803. Tcl_GetAssocData(interp, name, procPtr)
  804.     Tcl_Interp *interp; /* Interpreter associated with. */
  805.     CONST char *name; /* Name of association. */
  806.     Tcl_InterpDeleteProc **procPtr; /* Pointer to place to store address
  807.  * of current deletion callback. */
  808. {
  809.     Interp *iPtr = (Interp *) interp;
  810.     AssocData *dPtr;
  811.     Tcl_HashEntry *hPtr;
  812.     if (iPtr->assocData == (Tcl_HashTable *) NULL) {
  813.         return (ClientData) NULL;
  814.     }
  815.     hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
  816.     if (hPtr == (Tcl_HashEntry *) NULL) {
  817.         return (ClientData) NULL;
  818.     }
  819.     dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
  820.     if (procPtr != (Tcl_InterpDeleteProc **) NULL) {
  821.         *procPtr = dPtr->proc;
  822.     }
  823.     return dPtr->clientData;
  824. }
  825. /*
  826.  *----------------------------------------------------------------------
  827.  *
  828.  * Tcl_InterpDeleted --
  829.  *
  830.  * Returns nonzero if the interpreter has been deleted with a call
  831.  * to Tcl_DeleteInterp.
  832.  *
  833.  * Results:
  834.  * Nonzero if the interpreter is deleted, zero otherwise.
  835.  *
  836.  * Side effects:
  837.  * None.
  838.  *
  839.  *----------------------------------------------------------------------
  840.  */
  841. int
  842. Tcl_InterpDeleted(interp)
  843.     Tcl_Interp *interp;
  844. {
  845.     return (((Interp *) interp)->flags & DELETED) ? 1 : 0;
  846. }
  847. /*
  848.  *----------------------------------------------------------------------
  849.  *
  850.  * Tcl_DeleteInterp --
  851.  *
  852.  * Ensures that the interpreter will be deleted eventually. If there
  853.  * are no Tcl_Preserve calls in effect for this interpreter, it is
  854.  * deleted immediately, otherwise the interpreter is deleted when
  855.  * the last Tcl_Preserve is matched by a call to Tcl_Release. In either
  856.  * case, the procedure runs the currently registered deletion callbacks. 
  857.  *
  858.  * Results:
  859.  * None.
  860.  *
  861.  * Side effects:
  862.  * The interpreter is marked as deleted. The caller may still use it
  863.  * safely if there are calls to Tcl_Preserve in effect for the
  864.  * interpreter, but further calls to Tcl_Eval etc in this interpreter
  865.  * will fail.
  866.  *
  867.  *----------------------------------------------------------------------
  868.  */
  869. void
  870. Tcl_DeleteInterp(interp)
  871.     Tcl_Interp *interp; /* Token for command interpreter (returned
  872.  * by a previous call to Tcl_CreateInterp). */
  873. {
  874.     Interp *iPtr = (Interp *) interp;
  875.     /*
  876.      * If the interpreter has already been marked deleted, just punt.
  877.      */
  878.     if (iPtr->flags & DELETED) {
  879.         return;
  880.     }
  881.     
  882.     /*
  883.      * Mark the interpreter as deleted. No further evals will be allowed.
  884.      */
  885.     iPtr->flags |= DELETED;
  886.     /*
  887.      * Ensure that the interpreter is eventually deleted.
  888.      */
  889.     Tcl_EventuallyFree((ClientData) interp,
  890.             (Tcl_FreeProc *) DeleteInterpProc);
  891. }
  892. /*
  893.  *----------------------------------------------------------------------
  894.  *
  895.  * DeleteInterpProc --
  896.  *
  897.  * Helper procedure to delete an interpreter. This procedure is
  898.  * called when the last call to Tcl_Preserve on this interpreter
  899.  * is matched by a call to Tcl_Release. The procedure cleans up
  900.  * all resources used in the interpreter and calls all currently
  901.  * registered interpreter deletion callbacks.
  902.  *
  903.  * Results:
  904.  * None.
  905.  *
  906.  * Side effects:
  907.  * Whatever the interpreter deletion callbacks do. Frees resources
  908.  * used by the interpreter.
  909.  *
  910.  *----------------------------------------------------------------------
  911.  */
  912. static void
  913. DeleteInterpProc(interp)
  914.     Tcl_Interp *interp; /* Interpreter to delete. */
  915. {
  916.     Interp *iPtr = (Interp *) interp;
  917.     Tcl_HashEntry *hPtr;
  918.     Tcl_HashSearch search;
  919.     Tcl_HashTable *hTablePtr;
  920.     ResolverScheme *resPtr, *nextResPtr;
  921.     /*
  922.      * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
  923.      */
  924.     
  925.     if (iPtr->numLevels > 0) {
  926.         panic("DeleteInterpProc called with active evals");
  927.     }
  928.     /*
  929.      * The interpreter should already be marked deleted; otherwise how
  930.      * did we get here?
  931.      */
  932.     if (!(iPtr->flags & DELETED)) {
  933.         panic("DeleteInterpProc called on interpreter not marked deleted");
  934.     }
  935.     TclHandleFree(iPtr->handle);
  936.     /*
  937.      * Dismantle everything in the global namespace except for the
  938.      * "errorInfo" and "errorCode" variables. These remain until the
  939.      * namespace is actually destroyed, in case any errors occur.
  940.      *   
  941.      * Dismantle the namespace here, before we clear the assocData. If any
  942.      * background errors occur here, they will be deleted below.
  943.      */
  944.     
  945.     TclTeardownNamespace(iPtr->globalNsPtr);
  946.     /*
  947.      * Delete all the hidden commands.
  948.      */
  949.      
  950.     hTablePtr = iPtr->hiddenCmdTablePtr;
  951.     if (hTablePtr != NULL) {
  952. /*
  953.  * Non-pernicious deletion.  The deletion callbacks will not be
  954.  * allowed to create any new hidden or non-hidden commands.
  955.  * Tcl_DeleteCommandFromToken() will remove the entry from the
  956.  * hiddenCmdTablePtr.
  957.  */
  958.  
  959. hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
  960. for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  961.     Tcl_DeleteCommandFromToken(interp,
  962.     (Tcl_Command) Tcl_GetHashValue(hPtr));
  963. }
  964. Tcl_DeleteHashTable(hTablePtr);
  965. ckfree((char *) hTablePtr);
  966.     }
  967.     /*
  968.      * Tear down the math function table.
  969.      */
  970.     for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search);
  971.      hPtr != NULL;
  972.              hPtr = Tcl_NextHashEntry(&search)) {
  973. ckfree((char *) Tcl_GetHashValue(hPtr));
  974.     }
  975.     Tcl_DeleteHashTable(&iPtr->mathFuncTable);
  976.     /*
  977.      * Invoke deletion callbacks; note that a callback can create new
  978.      * callbacks, so we iterate.
  979.      */
  980.     while (iPtr->assocData != (Tcl_HashTable *) NULL) {
  981. AssocData *dPtr;
  982.         hTablePtr = iPtr->assocData;
  983.         iPtr->assocData = (Tcl_HashTable *) NULL;
  984.         for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
  985.                  hPtr != NULL;
  986.                  hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
  987.             dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
  988.             Tcl_DeleteHashEntry(hPtr);
  989.             if (dPtr->proc != NULL) {
  990.                 (*dPtr->proc)(dPtr->clientData, interp);
  991.             }
  992.             ckfree((char *) dPtr);
  993.         }
  994.         Tcl_DeleteHashTable(hTablePtr);
  995.         ckfree((char *) hTablePtr);
  996.     }
  997.     /*
  998.      * Finish deleting the global namespace.
  999.      */
  1000.     
  1001.     Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
  1002.     /*
  1003.      * Free up the result *after* deleting variables, since variable
  1004.      * deletion could have transferred ownership of the result string
  1005.      * to Tcl.
  1006.      */
  1007.     Tcl_FreeResult(interp);
  1008.     interp->result = NULL;
  1009.     Tcl_DecrRefCount(iPtr->objResultPtr);
  1010.     iPtr->objResultPtr = NULL;
  1011.     if (iPtr->errorInfo != NULL) {
  1012. ckfree(iPtr->errorInfo);
  1013.         iPtr->errorInfo = NULL;
  1014.     }
  1015.     if (iPtr->errorCode != NULL) {
  1016. ckfree(iPtr->errorCode);
  1017.         iPtr->errorCode = NULL;
  1018.     }
  1019.     if (iPtr->appendResult != NULL) {
  1020. ckfree(iPtr->appendResult);
  1021.         iPtr->appendResult = NULL;
  1022.     }
  1023.     TclFreePackageInfo(iPtr);
  1024.     while (iPtr->tracePtr != NULL) {
  1025. Tcl_DeleteTrace((Tcl_Interp*) iPtr, (Tcl_Trace) iPtr->tracePtr);
  1026.     }
  1027.     if (iPtr->execEnvPtr != NULL) {
  1028. TclDeleteExecEnv(iPtr->execEnvPtr);
  1029.     }
  1030.     Tcl_DecrRefCount(iPtr->emptyObjPtr);
  1031.     iPtr->emptyObjPtr = NULL;
  1032.     resPtr = iPtr->resolverPtr;
  1033.     while (resPtr) {
  1034. nextResPtr = resPtr->nextPtr;
  1035. ckfree(resPtr->name);
  1036. ckfree((char *) resPtr);
  1037.         resPtr = nextResPtr;
  1038.     }
  1039.     
  1040.     /*
  1041.      * Free up literal objects created for scripts compiled by the
  1042.      * interpreter.
  1043.      */
  1044.     TclDeleteLiteralTable(interp, &(iPtr->literalTable));
  1045. #ifdef TCL_TIP280
  1046.     /* TIP #280 - Release the arrays for ByteCode/Proc extension, and contents.
  1047.      */
  1048.     {
  1049.         Tcl_HashEntry *hPtr;
  1050. Tcl_HashSearch hSearch;
  1051. CmdFrame*      cfPtr;
  1052. ExtCmdLoc*     eclPtr;
  1053. int            i;
  1054. for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &hSearch);
  1055.      hPtr != NULL;
  1056.      hPtr = Tcl_NextHashEntry(&hSearch)) {
  1057.     cfPtr = (CmdFrame*) Tcl_GetHashValue (hPtr);
  1058.     if (cfPtr->type == TCL_LOCATION_SOURCE) {
  1059.         Tcl_DecrRefCount (cfPtr->data.eval.path);
  1060.     }
  1061.     ckfree ((char*) cfPtr->line);
  1062.     ckfree ((char*) cfPtr);
  1063.     Tcl_DeleteHashEntry (hPtr);
  1064. }
  1065. Tcl_DeleteHashTable (iPtr->linePBodyPtr);
  1066. ckfree ((char*) iPtr->linePBodyPtr);
  1067. iPtr->linePBodyPtr = NULL;
  1068. /* See also tclCompile.c, TclCleanupByteCode */
  1069. for (hPtr = Tcl_FirstHashEntry(iPtr->lineBCPtr, &hSearch);
  1070.      hPtr != NULL;
  1071.      hPtr = Tcl_NextHashEntry(&hSearch)) {
  1072.     eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hPtr);
  1073.     if (eclPtr->type == TCL_LOCATION_SOURCE) {
  1074.         Tcl_DecrRefCount (eclPtr->path);
  1075.     }
  1076.     for (i=0; i< eclPtr->nuloc; i++) {
  1077.         ckfree ((char*) eclPtr->loc[i].line);
  1078.     }
  1079.             if (eclPtr->loc != NULL) {
  1080. ckfree ((char*) eclPtr->loc);
  1081.     }
  1082.     ckfree ((char*) eclPtr);
  1083.     Tcl_DeleteHashEntry (hPtr);
  1084. }
  1085. Tcl_DeleteHashTable (iPtr->lineBCPtr);
  1086. ckfree((char*) iPtr->lineBCPtr);
  1087. iPtr->lineBCPtr = NULL;
  1088.     }
  1089. #endif
  1090.     ckfree((char *) iPtr);
  1091. }
  1092. /*
  1093.  *---------------------------------------------------------------------------
  1094.  *
  1095.  * Tcl_HideCommand --
  1096.  *
  1097.  * Makes a command hidden so that it cannot be invoked from within
  1098.  * an interpreter, only from within an ancestor.
  1099.  *
  1100.  * Results:
  1101.  * A standard Tcl result; also leaves a message in the interp's result
  1102.  * if an error occurs.
  1103.  *
  1104.  * Side effects:
  1105.  * Removes a command from the command table and create an entry
  1106.  *      into the hidden command table under the specified token name.
  1107.  *
  1108.  *---------------------------------------------------------------------------
  1109.  */
  1110. int
  1111. Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
  1112.     Tcl_Interp *interp; /* Interpreter in which to hide command. */
  1113.     CONST char *cmdName; /* Name of command to hide. */
  1114.     CONST char *hiddenCmdToken; /* Token name of the to-be-hidden command. */
  1115. {
  1116.     Interp *iPtr = (Interp *) interp;
  1117.     Tcl_Command cmd;
  1118.     Command *cmdPtr;
  1119.     Tcl_HashTable *hiddenCmdTablePtr;
  1120.     Tcl_HashEntry *hPtr;
  1121.     int new;
  1122.     if (iPtr->flags & DELETED) {
  1123.         /*
  1124.          * The interpreter is being deleted. Do not create any new
  1125.          * structures, because it is not safe to modify the interpreter.
  1126.          */
  1127.         
  1128.         return TCL_ERROR;
  1129.     }
  1130.     /*
  1131.      * Disallow hiding of commands that are currently in a namespace or
  1132.      * renaming (as part of hiding) into a namespace.
  1133.      *
  1134.      * (because the current implementation with a single global table
  1135.      *  and the needed uniqueness of names cause problems with namespaces)
  1136.      *
  1137.      * we don't need to check for "::" in cmdName because the real check is
  1138.      * on the nsPtr below.
  1139.      *
  1140.      * hiddenCmdToken is just a string which is not interpreted in any way.
  1141.      * It may contain :: but the string is not interpreted as a namespace
  1142.      * qualifier command name. Thus, hiding foo::bar to foo::bar and then
  1143.      * trying to expose or invoke ::foo::bar will NOT work; but if the
  1144.      * application always uses the same strings it will get consistent
  1145.      * behaviour.
  1146.      *
  1147.      * But as we currently limit ourselves to the global namespace only
  1148.      * for the source, in order to avoid potential confusion,
  1149.      * lets prevent "::" in the token too.  --dl
  1150.      */
  1151.     if (strstr(hiddenCmdToken, "::") != NULL) {
  1152.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1153.                 "cannot use namespace qualifiers in hidden command",
  1154. " token (rename)", (char *) NULL);
  1155.         return TCL_ERROR;
  1156.     }
  1157.     /*
  1158.      * Find the command to hide. An error is returned if cmdName can't
  1159.      * be found. Look up the command only from the global namespace.
  1160.      * Full path of the command must be given if using namespaces.
  1161.      */
  1162.     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
  1163.     /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  1164.     if (cmd == (Tcl_Command) NULL) {
  1165. return TCL_ERROR;
  1166.     }
  1167.     cmdPtr = (Command *) cmd;
  1168.     /*
  1169.      * Check that the command is really in global namespace
  1170.      */
  1171.     if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
  1172.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1173.                 "can only hide global namespace commands",
  1174. " (use rename then hide)", (char *) NULL);
  1175.         return TCL_ERROR;
  1176.     }
  1177.     
  1178.     /*
  1179.      * Initialize the hidden command table if necessary.
  1180.      */
  1181.     hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
  1182.     if (hiddenCmdTablePtr == NULL) {
  1183.         hiddenCmdTablePtr = (Tcl_HashTable *)
  1184.         ckalloc((unsigned) sizeof(Tcl_HashTable));
  1185.         Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
  1186. iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr;
  1187.     }
  1188.     /*
  1189.      * It is an error to move an exposed command to a hidden command with
  1190.      * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
  1191.      * exists.
  1192.      */
  1193.     
  1194.     hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &new);
  1195.     if (!new) {
  1196.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1197.                 "hidden command named "", hiddenCmdToken, "" already exists",
  1198.                 (char *) NULL);
  1199.         return TCL_ERROR;
  1200.     }
  1201.     /*
  1202.      * Nb : This code is currently 'like' a rename to a specialy set apart
  1203.      * name table. Changes here and in TclRenameCommand must
  1204.      * be kept in synch untill the common parts are actually
  1205.      * factorized out.
  1206.      */
  1207.     /*
  1208.      * Remove the hash entry for the command from the interpreter command
  1209.      * table. This is like deleting the command, so bump its command epoch;
  1210.      * this invalidates any cached references that point to the command.
  1211.      */
  1212.     if (cmdPtr->hPtr != NULL) {
  1213.         Tcl_DeleteHashEntry(cmdPtr->hPtr);
  1214.         cmdPtr->hPtr = (Tcl_HashEntry *) NULL;
  1215. cmdPtr->cmdEpoch++;
  1216.     }
  1217.     /*
  1218.      * Now link the hash table entry with the command structure.
  1219.      * We ensured above that the nsPtr was right.
  1220.      */
  1221.     
  1222.     cmdPtr->hPtr = hPtr;
  1223.     Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
  1224.     /*
  1225.      * If the command being hidden has a compile procedure, increment the
  1226.      * interpreter's compileEpoch to invalidate its compiled code. This
  1227.      * makes sure that we don't later try to execute old code compiled with
  1228.      * command-specific (i.e., inline) bytecodes for the now-hidden
  1229.      * command. This field is checked in Tcl_EvalObj and ObjInterpProc,
  1230.      * and code whose compilation epoch doesn't match is recompiled.
  1231.      */
  1232.     if (cmdPtr->compileProc != NULL) {
  1233. iPtr->compileEpoch++;
  1234.     }
  1235.     return TCL_OK;
  1236. }
  1237. /*
  1238.  *----------------------------------------------------------------------
  1239.  *
  1240.  * Tcl_ExposeCommand --
  1241.  *
  1242.  * Makes a previously hidden command callable from inside the
  1243.  * interpreter instead of only by its ancestors.
  1244.  *
  1245.  * Results:
  1246.  * A standard Tcl result. If an error occurs, a message is left
  1247.  * in the interp's result.
  1248.  *
  1249.  * Side effects:
  1250.  * Moves commands from one hash table to another.
  1251.  *
  1252.  *----------------------------------------------------------------------
  1253.  */
  1254. int
  1255. Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
  1256.     Tcl_Interp *interp; /* Interpreter in which to make command
  1257.                                  * callable. */
  1258.     CONST char *hiddenCmdToken; /* Name of hidden command. */
  1259.     CONST char *cmdName; /* Name of to-be-exposed command. */
  1260. {
  1261.     Interp *iPtr = (Interp *) interp;
  1262.     Command *cmdPtr;
  1263.     Namespace *nsPtr;
  1264.     Tcl_HashEntry *hPtr;
  1265.     Tcl_HashTable *hiddenCmdTablePtr;
  1266.     int new;
  1267.     if (iPtr->flags & DELETED) {
  1268.         /*
  1269.          * The interpreter is being deleted. Do not create any new
  1270.          * structures, because it is not safe to modify the interpreter.
  1271.          */
  1272.         
  1273.         return TCL_ERROR;
  1274.     }
  1275.     /*
  1276.      * Check that we have a regular name for the command
  1277.      * (that the user is not trying to do an expose and a rename
  1278.      *  (to another namespace) at the same time)
  1279.      */
  1280.     if (strstr(cmdName, "::") != NULL) {
  1281.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1282.                 "can not expose to a namespace ",
  1283. "(use expose to toplevel, then rename)",
  1284.                  (char *) NULL);
  1285.         return TCL_ERROR;
  1286.     }
  1287.     /*
  1288.      * Get the command from the hidden command table:
  1289.      */
  1290.     hPtr = NULL;
  1291.     hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
  1292.     if (hiddenCmdTablePtr != NULL) {
  1293. hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
  1294.     }
  1295.     if (hPtr == (Tcl_HashEntry *) NULL) {
  1296.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1297.                 "unknown hidden command "", hiddenCmdToken,
  1298.                 """, (char *) NULL);
  1299.         return TCL_ERROR;
  1300.     }
  1301.     cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
  1302.     
  1303.     /*
  1304.      * Check that we have a true global namespace
  1305.      * command (enforced by Tcl_HideCommand() but let's double
  1306.      * check. (If it was not, we would not really know how to
  1307.      * handle it).
  1308.      */
  1309.     if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
  1310. /* 
  1311.  * This case is theoritically impossible,
  1312.  * we might rather panic() than 'nicely' erroring out ?
  1313.  */
  1314.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1315.                 "trying to expose a non global command name space command",
  1316. (char *) NULL);
  1317.         return TCL_ERROR;
  1318.     }
  1319.     
  1320.     /* This is the global table */
  1321.     nsPtr = cmdPtr->nsPtr;
  1322.     /*
  1323.      * It is an error to overwrite an existing exposed command as a result
  1324.      * of exposing a previously hidden command.
  1325.      */
  1326.     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &new);
  1327.     if (!new) {
  1328.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1329.                 "exposed command "", cmdName,
  1330.                 "" already exists", (char *) NULL);
  1331.         return TCL_ERROR;
  1332.     }
  1333.     /*
  1334.      * Remove the hash entry for the command from the interpreter hidden
  1335.      * command table.
  1336.      */
  1337.     if (cmdPtr->hPtr != NULL) {
  1338.         Tcl_DeleteHashEntry(cmdPtr->hPtr);
  1339.         cmdPtr->hPtr = NULL;
  1340.     }
  1341.     /*
  1342.      * Now link the hash table entry with the command structure.
  1343.      * This is like creating a new command, so deal with any shadowing
  1344.      * of commands in the global namespace.
  1345.      */
  1346.     
  1347.     cmdPtr->hPtr = hPtr;
  1348.     Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
  1349.     /*
  1350.      * Not needed as we are only in the global namespace
  1351.      * (but would be needed again if we supported namespace command hiding)
  1352.      *
  1353.      * TclResetShadowedCmdRefs(interp, cmdPtr);
  1354.      */
  1355.     /*
  1356.      * If the command being exposed has a compile procedure, increment
  1357.      * interpreter's compileEpoch to invalidate its compiled code. This
  1358.      * makes sure that we don't later try to execute old code compiled
  1359.      * assuming the command is hidden. This field is checked in Tcl_EvalObj
  1360.      * and ObjInterpProc, and code whose compilation epoch doesn't match is
  1361.      * recompiled.
  1362.      */
  1363.     if (cmdPtr->compileProc != NULL) {
  1364. iPtr->compileEpoch++;
  1365.     }
  1366.     return TCL_OK;
  1367. }
  1368. /*
  1369.  *----------------------------------------------------------------------
  1370.  *
  1371.  * Tcl_CreateCommand --
  1372.  *
  1373.  * Define a new command in a command table.
  1374.  *
  1375.  * Results:
  1376.  * The return value is a token for the command, which can
  1377.  * be used in future calls to Tcl_GetCommandName.
  1378.  *
  1379.  * Side effects:
  1380.  * If a command named cmdName already exists for interp, it is deleted.
  1381.  * In the future, when cmdName is seen as the name of a command by
  1382.  * Tcl_Eval, proc will be called. To support the bytecode interpreter,
  1383.  * the command is created with a wrapper Tcl_ObjCmdProc
  1384.  * (TclInvokeStringCommand) that eventially calls proc. When the
  1385.  * command is deleted from the table, deleteProc will be called.
  1386.  * See the manual entry for details on the calling sequence.
  1387.  *
  1388.  *----------------------------------------------------------------------
  1389.  */
  1390. Tcl_Command
  1391. Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
  1392.     Tcl_Interp *interp; /* Token for command interpreter returned by
  1393.  * a previous call to Tcl_CreateInterp. */
  1394.     CONST char *cmdName; /* Name of command. If it contains namespace
  1395.  * qualifiers, the new command is put in the
  1396.  * specified namespace; otherwise it is put
  1397.  * in the global namespace. */
  1398.     Tcl_CmdProc *proc; /* Procedure to associate with cmdName. */
  1399.     ClientData clientData; /* Arbitrary value passed to string proc. */
  1400.     Tcl_CmdDeleteProc *deleteProc;
  1401. /* If not NULL, gives a procedure to call
  1402.  * when this command is deleted. */
  1403. {
  1404.     Interp *iPtr = (Interp *) interp;
  1405.     ImportRef *oldRefPtr = NULL;
  1406.     Namespace *nsPtr, *dummy1, *dummy2;
  1407.     Command *cmdPtr, *refCmdPtr;
  1408.     Tcl_HashEntry *hPtr;
  1409.     CONST char *tail;
  1410.     int new;
  1411.     ImportedCmdData *dataPtr;
  1412.     if (iPtr->flags & DELETED) {
  1413. /*
  1414.  * The interpreter is being deleted.  Don't create any new
  1415.  * commands; it's not safe to muck with the interpreter anymore.
  1416.  */
  1417. return (Tcl_Command) NULL;
  1418.     }
  1419.     /*
  1420.      * Determine where the command should reside. If its name contains 
  1421.      * namespace qualifiers, we put it in the specified namespace; 
  1422.      * otherwise, we always put it in the global namespace.
  1423.      */
  1424.     if (strstr(cmdName, "::") != NULL) {
  1425.        TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
  1426.            CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
  1427.        if ((nsPtr == NULL) || (tail == NULL)) {
  1428.     return (Tcl_Command) NULL;
  1429. }
  1430.     } else {
  1431. nsPtr = iPtr->globalNsPtr;
  1432. tail = cmdName;
  1433.     }
  1434.     
  1435.     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
  1436.     if (!new) {
  1437. /*
  1438.  * Command already exists. Delete the old one.
  1439.  * Be careful to preserve any existing import links so we can
  1440.  * restore them down below.  That way, you can redefine a
  1441.  * command and its import status will remain intact.
  1442.  */
  1443. cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
  1444. oldRefPtr = cmdPtr->importRefPtr;
  1445. cmdPtr->importRefPtr = NULL;
  1446. Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
  1447. hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
  1448. if (!new) {
  1449.     /*
  1450.      * If the deletion callback recreated the command, just throw
  1451.              * away the new command (if we try to delete it again, we
  1452.              * could get stuck in an infinite loop).
  1453.      */
  1454.      ckfree((char*) Tcl_GetHashValue(hPtr));
  1455. }
  1456.     }
  1457.     cmdPtr = (Command *) ckalloc(sizeof(Command));
  1458.     Tcl_SetHashValue(hPtr, cmdPtr);
  1459.     cmdPtr->hPtr = hPtr;
  1460.     cmdPtr->nsPtr = nsPtr;
  1461.     cmdPtr->refCount = 1;
  1462.     cmdPtr->cmdEpoch = 0;
  1463.     cmdPtr->compileProc = (CompileProc *) NULL;
  1464.     cmdPtr->objProc = TclInvokeStringCommand;
  1465.     cmdPtr->objClientData = (ClientData) cmdPtr;
  1466.     cmdPtr->proc = proc;
  1467.     cmdPtr->clientData = clientData;
  1468.     cmdPtr->deleteProc = deleteProc;
  1469.     cmdPtr->deleteData = clientData;
  1470.     cmdPtr->flags = 0;
  1471.     cmdPtr->importRefPtr = NULL;
  1472.     cmdPtr->tracePtr = NULL;
  1473.     /*
  1474.      * Plug in any existing import references found above.  Be sure
  1475.      * to update all of these references to point to the new command.
  1476.      */
  1477.     if (oldRefPtr != NULL) {
  1478. cmdPtr->importRefPtr = oldRefPtr;
  1479. while (oldRefPtr != NULL) {
  1480.     refCmdPtr = oldRefPtr->importedCmdPtr;
  1481.     dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
  1482.     dataPtr->realCmdPtr = cmdPtr;
  1483.     oldRefPtr = oldRefPtr->nextPtr;
  1484. }
  1485.     }
  1486.     /*
  1487.      * We just created a command, so in its namespace and all of its parent
  1488.      * namespaces, it may shadow global commands with the same name. If any
  1489.      * shadowed commands are found, invalidate all cached command references
  1490.      * in the affected namespaces.
  1491.      */
  1492.     
  1493.     TclResetShadowedCmdRefs(interp, cmdPtr);
  1494.     return (Tcl_Command) cmdPtr;
  1495. }
  1496. /*
  1497.  *----------------------------------------------------------------------
  1498.  *
  1499.  * Tcl_CreateObjCommand --
  1500.  *
  1501.  * Define a new object-based command in a command table.
  1502.  *
  1503.  * Results:
  1504.  * The return value is a token for the command, which can
  1505.  * be used in future calls to Tcl_GetCommandName.
  1506.  *
  1507.  * Side effects:
  1508.  * If no command named "cmdName" already exists for interp, one is
  1509.  * created. Otherwise, if a command does exist, then if the
  1510.  * object-based Tcl_ObjCmdProc is TclInvokeStringCommand, we assume
  1511.  * Tcl_CreateCommand was called previously for the same command and
  1512.  * just set its Tcl_ObjCmdProc to the argument "proc"; otherwise, we
  1513.  * delete the old command.
  1514.  *
  1515.  * In the future, during bytecode evaluation when "cmdName" is seen as
  1516.  * the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
  1517.  * Tcl_ObjCmdProc proc will be called. When the command is deleted from
  1518.  * the table, deleteProc will be called. See the manual entry for
  1519.  * details on the calling sequence.
  1520.  *
  1521.  *----------------------------------------------------------------------
  1522.  */
  1523. Tcl_Command
  1524. Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
  1525.     Tcl_Interp *interp; /* Token for command interpreter (returned
  1526.  * by previous call to Tcl_CreateInterp). */
  1527.     CONST char *cmdName; /* Name of command. If it contains namespace
  1528.  * qualifiers, the new command is put in the
  1529.  * specified namespace; otherwise it is put
  1530.  * in the global namespace. */
  1531.     Tcl_ObjCmdProc *proc; /* Object-based procedure to associate with
  1532.  * name. */
  1533.     ClientData clientData; /* Arbitrary value to pass to object
  1534.       * procedure. */
  1535.     Tcl_CmdDeleteProc *deleteProc;
  1536. /* If not NULL, gives a procedure to call
  1537.  * when this command is deleted. */
  1538. {
  1539.     Interp *iPtr = (Interp *) interp;
  1540.     ImportRef *oldRefPtr = NULL;
  1541.     Namespace *nsPtr, *dummy1, *dummy2;
  1542.     Command *cmdPtr, *refCmdPtr;
  1543.     Tcl_HashEntry *hPtr;
  1544.     CONST char *tail;
  1545.     int new;
  1546.     ImportedCmdData *dataPtr;
  1547.     if (iPtr->flags & DELETED) {
  1548. /*
  1549.  * The interpreter is being deleted.  Don't create any new
  1550.  * commands;  it's not safe to muck with the interpreter anymore.
  1551.  */
  1552. return (Tcl_Command) NULL;
  1553.     }
  1554.     /*
  1555.      * Determine where the command should reside. If its name contains 
  1556.      * namespace qualifiers, we put it in the specified namespace; 
  1557.      * otherwise, we always put it in the global namespace.
  1558.      */
  1559.     if (strstr(cmdName, "::") != NULL) {
  1560.        TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
  1561.            CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
  1562.        if ((nsPtr == NULL) || (tail == NULL)) {
  1563.     return (Tcl_Command) NULL;
  1564. }
  1565.     } else {
  1566. nsPtr = iPtr->globalNsPtr;
  1567. tail = cmdName;
  1568.     }
  1569.     hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
  1570.     if (!new) {
  1571. cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
  1572. /*
  1573.  * Command already exists. If its object-based Tcl_ObjCmdProc is
  1574.  * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
  1575.  * argument "proc". Otherwise, we delete the old command. 
  1576.  */
  1577. if (cmdPtr->objProc == TclInvokeStringCommand) {
  1578.     cmdPtr->objProc = proc;
  1579.     cmdPtr->objClientData = clientData;
  1580.             cmdPtr->deleteProc = deleteProc;
  1581.             cmdPtr->deleteData = clientData;
  1582.     return (Tcl_Command) cmdPtr;
  1583. }
  1584. /*
  1585.  * Otherwise, we delete the old command.  Be careful to preserve
  1586.  * any existing import links so we can restore them down below.
  1587.  * That way, you can redefine a command and its import status
  1588.  * will remain intact.
  1589.  */
  1590. oldRefPtr = cmdPtr->importRefPtr;
  1591. cmdPtr->importRefPtr = NULL;
  1592. Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
  1593. hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
  1594. if (!new) {
  1595.     /*
  1596.      * If the deletion callback recreated the command, just throw
  1597.      * away the new command (if we try to delete it again, we
  1598.      * could get stuck in an infinite loop).
  1599.      */
  1600.      ckfree((char *) Tcl_GetHashValue(hPtr));
  1601. }
  1602.     }
  1603.     cmdPtr = (Command *) ckalloc(sizeof(Command));
  1604.     Tcl_SetHashValue(hPtr, cmdPtr);
  1605.     cmdPtr->hPtr = hPtr;
  1606.     cmdPtr->nsPtr = nsPtr;
  1607.     cmdPtr->refCount = 1;
  1608.     cmdPtr->cmdEpoch = 0;
  1609.     cmdPtr->compileProc = (CompileProc *) NULL;
  1610.     cmdPtr->objProc = proc;
  1611.     cmdPtr->objClientData = clientData;
  1612.     cmdPtr->proc = TclInvokeObjectCommand;
  1613.     cmdPtr->clientData = (ClientData) cmdPtr;
  1614.     cmdPtr->deleteProc = deleteProc;
  1615.     cmdPtr->deleteData = clientData;
  1616.     cmdPtr->flags = 0;
  1617.     cmdPtr->importRefPtr = NULL;
  1618.     cmdPtr->tracePtr = NULL;
  1619.     /*
  1620.      * Plug in any existing import references found above.  Be sure
  1621.      * to update all of these references to point to the new command.
  1622.      */
  1623.     if (oldRefPtr != NULL) {
  1624. cmdPtr->importRefPtr = oldRefPtr;
  1625. while (oldRefPtr != NULL) {
  1626.     refCmdPtr = oldRefPtr->importedCmdPtr;
  1627.     dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
  1628.     dataPtr->realCmdPtr = cmdPtr;
  1629.     oldRefPtr = oldRefPtr->nextPtr;
  1630. }
  1631.     }
  1632.     
  1633.     /*
  1634.      * We just created a command, so in its namespace and all of its parent
  1635.      * namespaces, it may shadow global commands with the same name. If any
  1636.      * shadowed commands are found, invalidate all cached command references
  1637.      * in the affected namespaces.
  1638.      */
  1639.     
  1640.     TclResetShadowedCmdRefs(interp, cmdPtr);
  1641.     return (Tcl_Command) cmdPtr;
  1642. }
  1643. /*
  1644.  *----------------------------------------------------------------------
  1645.  *
  1646.  * TclInvokeStringCommand --
  1647.  *
  1648.  * "Wrapper" Tcl_ObjCmdProc used to call an existing string-based
  1649.  * Tcl_CmdProc if no object-based procedure exists for a command. A
  1650.  * pointer to this procedure is stored as the Tcl_ObjCmdProc in a
  1651.  * Command structure. It simply turns around and calls the string
  1652.  * Tcl_CmdProc in the Command structure.
  1653.  *
  1654.  * Results:
  1655.  * A standard Tcl object result value.
  1656.  *
  1657.  * Side effects:
  1658.  * Besides those side effects of the called Tcl_CmdProc,
  1659.  * TclInvokeStringCommand allocates and frees storage.
  1660.  *
  1661.  *----------------------------------------------------------------------
  1662.  */
  1663. int
  1664. TclInvokeStringCommand(clientData, interp, objc, objv)
  1665.     ClientData clientData; /* Points to command's Command structure. */
  1666.     Tcl_Interp *interp; /* Current interpreter. */
  1667.     register int objc; /* Number of arguments. */
  1668.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1669. {
  1670.     register Command *cmdPtr = (Command *) clientData;
  1671.     register int i;
  1672.     int result;
  1673.     /*
  1674.      * This procedure generates an argv array for the string arguments. It
  1675.      * starts out with stack-allocated space but uses dynamically-allocated
  1676.      * storage if needed.
  1677.      */
  1678. #define NUM_ARGS 20
  1679.     CONST char *(argStorage[NUM_ARGS]);
  1680.     CONST char **argv = argStorage;
  1681.     /*
  1682.      * Create the string argument array "argv". Make sure argv is large
  1683.      * enough to hold the objc arguments plus 1 extra for the zero
  1684.      * end-of-argv word.
  1685.      */
  1686.     if ((objc + 1) > NUM_ARGS) {
  1687. argv = (CONST char **) ckalloc((unsigned)(objc + 1) * sizeof(char *));
  1688.     }
  1689.     for (i = 0;  i < objc;  i++) {
  1690. argv[i] = Tcl_GetString(objv[i]);
  1691.     }
  1692.     argv[objc] = 0;
  1693.     /*
  1694.      * Invoke the command's string-based Tcl_CmdProc.
  1695.      */
  1696.     result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv);
  1697.     /*
  1698.      * Free the argv array if malloc'ed storage was used.
  1699.      */
  1700.     if (argv != argStorage) {
  1701. ckfree((char *) argv);
  1702.     }
  1703.     return result;
  1704. #undef NUM_ARGS
  1705. }
  1706. /*
  1707.  *----------------------------------------------------------------------
  1708.  *
  1709.  * TclInvokeObjectCommand --
  1710.  *
  1711.  * "Wrapper" Tcl_CmdProc used to call an existing object-based
  1712.  * Tcl_ObjCmdProc if no string-based procedure exists for a command.
  1713.  * A pointer to this procedure is stored as the Tcl_CmdProc in a
  1714.  * Command structure. It simply turns around and calls the object
  1715.  * Tcl_ObjCmdProc in the Command structure.
  1716.  *
  1717.  * Results:
  1718.  * A standard Tcl string result value.
  1719.  *
  1720.  * Side effects:
  1721.  * Besides those side effects of the called Tcl_CmdProc,
  1722.  * TclInvokeStringCommand allocates and frees storage.
  1723.  *
  1724.  *----------------------------------------------------------------------
  1725.  */
  1726. int
  1727. TclInvokeObjectCommand(clientData, interp, argc, argv)
  1728.     ClientData clientData; /* Points to command's Command structure. */
  1729.     Tcl_Interp *interp; /* Current interpreter. */
  1730.     int argc; /* Number of arguments. */
  1731.     register CONST char **argv; /* Argument strings. */
  1732. {
  1733.     Command *cmdPtr = (Command *) clientData;
  1734.     register Tcl_Obj *objPtr;
  1735.     register int i;
  1736.     int length, result;
  1737.     /*
  1738.      * This procedure generates an objv array for object arguments that hold
  1739.      * the argv strings. It starts out with stack-allocated space but uses
  1740.      * dynamically-allocated storage if needed.
  1741.      */
  1742. #define NUM_ARGS 20
  1743.     Tcl_Obj *(argStorage[NUM_ARGS]);
  1744.     register Tcl_Obj **objv = argStorage;
  1745.     /*
  1746.      * Create the object argument array "objv". Make sure objv is large
  1747.      * enough to hold the objc arguments plus 1 extra for the zero
  1748.      * end-of-objv word.
  1749.      */
  1750.     if (argc > NUM_ARGS) {
  1751. objv = (Tcl_Obj **)
  1752.     ckalloc((unsigned)(argc * sizeof(Tcl_Obj *)));
  1753.     }
  1754.     for (i = 0;  i < argc;  i++) {
  1755. length = strlen(argv[i]);
  1756. TclNewObj(objPtr);
  1757. TclInitStringRep(objPtr, argv[i], length);
  1758. Tcl_IncrRefCount(objPtr);
  1759. objv[i] = objPtr;
  1760.     }
  1761.     /*
  1762.      * Invoke the command's object-based Tcl_ObjCmdProc.
  1763.      */
  1764.     result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);
  1765.     /*
  1766.      * Move the interpreter's object result to the string result, 
  1767.      * then reset the object result.
  1768.      */
  1769.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  1770.     TCL_VOLATILE);
  1771.     
  1772.     /*
  1773.      * Decrement the ref counts for the argument objects created above,
  1774.      * then free the objv array if malloc'ed storage was used.
  1775.      */
  1776.     for (i = 0;  i < argc;  i++) {
  1777. objPtr = objv[i];
  1778. Tcl_DecrRefCount(objPtr);
  1779.     }
  1780.     if (objv != argStorage) {
  1781. ckfree((char *) objv);
  1782.     }
  1783.     return result;
  1784. #undef NUM_ARGS
  1785. }
  1786. /*
  1787.  *----------------------------------------------------------------------
  1788.  *
  1789.  * TclRenameCommand --
  1790.  *
  1791.  *      Called to give an existing Tcl command a different name. Both the
  1792.  *      old command name and the new command name can have "::" namespace
  1793.  *      qualifiers. If the new command has a different namespace context,
  1794.  *      the command will be moved to that namespace and will execute in
  1795.  * the context of that new namespace.
  1796.  *
  1797.  *      If the new command name is NULL or the null string, the command is
  1798.  *      deleted.
  1799.  *
  1800.  * Results:
  1801.  *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
  1802.  *
  1803.  * Side effects:
  1804.  *      If anything goes wrong, an error message is returned in the
  1805.  *      interpreter's result object.
  1806.  *
  1807.  *----------------------------------------------------------------------
  1808.  */
  1809. int
  1810. TclRenameCommand(interp, oldName, newName)
  1811.     Tcl_Interp *interp;                 /* Current interpreter. */
  1812.     char *oldName;                      /* Existing command name. */
  1813.     char *newName;                      /* New command name. */
  1814. {
  1815.     Interp *iPtr = (Interp *) interp;
  1816.     CONST char *newTail;
  1817.     Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2;
  1818.     Tcl_Command cmd;
  1819.     Command *cmdPtr;
  1820.     Tcl_HashEntry *hPtr, *oldHPtr;
  1821.     int new, result;
  1822.     Tcl_Obj* oldFullName;
  1823.     Tcl_DString newFullName;
  1824.     /*
  1825.      * Find the existing command. An error is returned if cmdName can't
  1826.      * be found.
  1827.      */
  1828.     cmd = Tcl_FindCommand(interp, oldName, (Tcl_Namespace *) NULL,
  1829. /*flags*/ 0);
  1830.     cmdPtr = (Command *) cmd;
  1831.     if (cmdPtr == NULL) {
  1832. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't ",
  1833.                 ((newName == NULL)||(*newName == ''))? "delete":"rename",
  1834.                 " "", oldName, "": command doesn't exist", (char *) NULL);
  1835. return TCL_ERROR;
  1836.     }
  1837.     cmdNsPtr = cmdPtr->nsPtr;
  1838.     oldFullName = Tcl_NewObj();
  1839.     Tcl_IncrRefCount( oldFullName );
  1840.     Tcl_GetCommandFullName( interp, cmd, oldFullName );
  1841.     /*
  1842.      * If the new command name is NULL or empty, delete the command. Do this
  1843.      * with Tcl_DeleteCommandFromToken, since we already have the command.
  1844.      */
  1845.     
  1846.     if ((newName == NULL) || (*newName == '')) {
  1847. Tcl_DeleteCommandFromToken(interp, cmd);
  1848. result = TCL_OK;
  1849. goto done;
  1850.     }
  1851.     /*
  1852.      * Make sure that the destination command does not already exist.
  1853.      * The rename operation is like creating a command, so we should
  1854.      * automatically create the containing namespaces just like
  1855.      * Tcl_CreateCommand would.
  1856.      */
  1857.     TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL,
  1858.        CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
  1859.     if ((newNsPtr == NULL) || (newTail == NULL)) {
  1860. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1861.  "can't rename to "", newName, "": bad command name",
  1862.            (char *) NULL);
  1863. result = TCL_ERROR;
  1864. goto done;
  1865.     }
  1866.     if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) {
  1867. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1868.  "can't rename to "", newName,
  1869.  "": command already exists", (char *) NULL);
  1870. result = TCL_ERROR;
  1871. goto done;
  1872.     }
  1873.     /*
  1874.      * Warning: any changes done in the code here are likely
  1875.      * to be needed in Tcl_HideCommand() code too.
  1876.      * (until the common parts are extracted out)     --dl
  1877.      */
  1878.     /*
  1879.      * Put the command in the new namespace so we can check for an alias
  1880.      * loop. Since we are adding a new command to a namespace, we must
  1881.      * handle any shadowing of the global commands that this might create.
  1882.      */
  1883.     
  1884.     oldHPtr = cmdPtr->hPtr;
  1885.     hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &new);
  1886.     Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
  1887.     cmdPtr->hPtr = hPtr;
  1888.     cmdPtr->nsPtr = newNsPtr;
  1889.     TclResetShadowedCmdRefs(interp, cmdPtr);
  1890.     /*
  1891.      * Now check for an alias loop. If we detect one, put everything back
  1892.      * the way it was and report the error.
  1893.      */
  1894.     result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr);
  1895.     if (result != TCL_OK) {
  1896.         Tcl_DeleteHashEntry(cmdPtr->hPtr);
  1897.         cmdPtr->hPtr = oldHPtr;
  1898.         cmdPtr->nsPtr = cmdNsPtr;
  1899. goto done;
  1900.     }
  1901.     /*
  1902.      * Script for rename traces can delete the command "oldName".
  1903.      * Therefore increment the reference count for cmdPtr so that
  1904.      * it's Command structure is freed only towards the end of this
  1905.      * function by calling TclCleanupCommand.
  1906.      *
  1907.      * The trace procedure needs to get a fully qualified name for
  1908.      * old and new commands [Tcl bug #651271], or else there's no way
  1909.      * for the trace procedure to get the namespace from which the old
  1910.      * command is being renamed!
  1911.      */
  1912.     Tcl_DStringInit( &newFullName );
  1913.     Tcl_DStringAppend( &newFullName, newNsPtr->fullName, -1 );
  1914.     if ( newNsPtr != iPtr->globalNsPtr ) {
  1915. Tcl_DStringAppend( &newFullName, "::", 2 );
  1916.     }
  1917.     Tcl_DStringAppend( &newFullName, newTail, -1 );
  1918.     cmdPtr->refCount++;
  1919.     CallCommandTraces( iPtr, cmdPtr,
  1920.        Tcl_GetString( oldFullName ),
  1921.        Tcl_DStringValue( &newFullName ),
  1922.        TCL_TRACE_RENAME);
  1923.     Tcl_DStringFree( &newFullName );
  1924.     /*
  1925.      * The new command name is okay, so remove the command from its
  1926.      * current namespace. This is like deleting the command, so bump
  1927.      * the cmdEpoch to invalidate any cached references to the command.
  1928.      */
  1929.     
  1930.     Tcl_DeleteHashEntry(oldHPtr);
  1931.     cmdPtr->cmdEpoch++;
  1932.     /*
  1933.      * If the command being renamed has a compile procedure, increment the
  1934.      * interpreter's compileEpoch to invalidate its compiled code. This
  1935.      * makes sure that we don't later try to execute old code compiled for
  1936.      * the now-renamed command.
  1937.      */
  1938.     if (cmdPtr->compileProc != NULL) {
  1939. iPtr->compileEpoch++;
  1940.     }
  1941.     /*
  1942.      * Now free the Command structure, if the "oldName" command has
  1943.      * been deleted by invocation of rename traces.
  1944.      */
  1945.     TclCleanupCommand(cmdPtr);
  1946.     result = TCL_OK;
  1947.     done:
  1948.     TclDecrRefCount( oldFullName );
  1949.     return result;
  1950. }
  1951. /*
  1952.  *----------------------------------------------------------------------
  1953.  *
  1954.  * Tcl_SetCommandInfo --
  1955.  *
  1956.  * Modifies various information about a Tcl command. Note that
  1957.  * this procedure will not change a command's namespace; use
  1958.  * Tcl_RenameCommand to do that. Also, the isNativeObjectProc
  1959.  * member of *infoPtr is ignored.
  1960.  *
  1961.  * Results:
  1962.  * If cmdName exists in interp, then the information at *infoPtr
  1963.  * is stored with the command in place of the current information
  1964.  * and 1 is returned. If the command doesn't exist then 0 is
  1965.  * returned. 
  1966.  *
  1967.  * Side effects:
  1968.  * None.
  1969.  *
  1970.  *----------------------------------------------------------------------
  1971.  */
  1972. int
  1973. Tcl_SetCommandInfo(interp, cmdName, infoPtr)
  1974.     Tcl_Interp *interp; /* Interpreter in which to look
  1975.  * for command. */
  1976.     CONST char *cmdName; /* Name of desired command. */
  1977.     CONST Tcl_CmdInfo *infoPtr; /* Where to find information
  1978.  * to store in the command. */
  1979. {
  1980.     Tcl_Command cmd;
  1981.     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
  1982.             /*flags*/ 0);
  1983.     return Tcl_SetCommandInfoFromToken( cmd, infoPtr );
  1984. }
  1985. /*
  1986.  *----------------------------------------------------------------------
  1987.  *
  1988.  * Tcl_SetCommandInfoFromToken --
  1989.  *
  1990.  * Modifies various information about a Tcl command. Note that
  1991.  * this procedure will not change a command's namespace; use
  1992.  * Tcl_RenameCommand to do that. Also, the isNativeObjectProc
  1993.  * member of *infoPtr is ignored.
  1994.  *
  1995.  * Results:
  1996.  * If cmdName exists in interp, then the information at *infoPtr
  1997.  * is stored with the command in place of the current information
  1998.  * and 1 is returned. If the command doesn't exist then 0 is
  1999.  * returned. 
  2000.  *
  2001.  * Side effects:
  2002.  * None.
  2003.  *
  2004.  *----------------------------------------------------------------------
  2005.  */
  2006. int
  2007. Tcl_SetCommandInfoFromToken( cmd, infoPtr )
  2008.     Tcl_Command cmd;
  2009.     CONST Tcl_CmdInfo* infoPtr;
  2010. {
  2011.     Command* cmdPtr; /* Internal representation of the command */
  2012.     if (cmd == (Tcl_Command) NULL) {
  2013. return 0;
  2014.     }
  2015.     /*
  2016.      * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
  2017.      */
  2018.     
  2019.     cmdPtr = (Command *) cmd;
  2020.     cmdPtr->proc = infoPtr->proc;
  2021.     cmdPtr->clientData = infoPtr->clientData;
  2022.     if (infoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
  2023. cmdPtr->objProc = TclInvokeStringCommand;
  2024. cmdPtr->objClientData = (ClientData) cmdPtr;
  2025.     } else {
  2026. cmdPtr->objProc = infoPtr->objProc;
  2027. cmdPtr->objClientData = infoPtr->objClientData;
  2028.     }
  2029.     cmdPtr->deleteProc = infoPtr->deleteProc;
  2030.     cmdPtr->deleteData = infoPtr->deleteData;
  2031.     return 1;
  2032. }
  2033. /*
  2034.  *----------------------------------------------------------------------
  2035.  *
  2036.  * Tcl_GetCommandInfo --
  2037.  *
  2038.  * Returns various information about a Tcl command.
  2039.  *
  2040.  * Results:
  2041.  * If cmdName exists in interp, then *infoPtr is modified to
  2042.  * hold information about cmdName and 1 is returned.  If the
  2043.  * command doesn't exist then 0 is returned and *infoPtr isn't
  2044.  * modified.
  2045.  *
  2046.  * Side effects:
  2047.  * None.
  2048.  *
  2049.  *----------------------------------------------------------------------
  2050.  */
  2051. int
  2052. Tcl_GetCommandInfo(interp, cmdName, infoPtr)
  2053.     Tcl_Interp *interp; /* Interpreter in which to look
  2054.  * for command. */
  2055.     CONST char *cmdName; /* Name of desired command. */
  2056.     Tcl_CmdInfo *infoPtr; /* Where to store information about
  2057.  * command. */
  2058. {
  2059.     Tcl_Command cmd;
  2060.     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
  2061.             /*flags*/ 0);
  2062.     return Tcl_GetCommandInfoFromToken( cmd, infoPtr );
  2063. }
  2064. /*
  2065.  *----------------------------------------------------------------------
  2066.  *
  2067.  * Tcl_GetCommandInfoFromToken --
  2068.  *
  2069.  * Returns various information about a Tcl command.
  2070.  *
  2071.  * Results:
  2072.  * Copies information from the command identified by 'cmd' into
  2073.  * a caller-supplied structure and returns 1.  If the 'cmd' is
  2074.  * NULL, leaves the structure untouched and returns 0.
  2075.  *
  2076.  * Side effects:
  2077.  * None.
  2078.  *
  2079.  *----------------------------------------------------------------------
  2080.  */
  2081. int
  2082. Tcl_GetCommandInfoFromToken( cmd, infoPtr )
  2083.     Tcl_Command cmd;
  2084.     Tcl_CmdInfo* infoPtr;
  2085. {
  2086.     Command* cmdPtr; /* Internal representation of the command */
  2087.     if ( cmd == (Tcl_Command) NULL ) {
  2088. return 0;
  2089.     }
  2090.     /*
  2091.      * Set isNativeObjectProc 1 if objProc was registered by a call to
  2092.      * Tcl_CreateObjCommand. Otherwise set it to 0.
  2093.      */
  2094.     cmdPtr = (Command *) cmd;
  2095.     infoPtr->isNativeObjectProc =
  2096.     (cmdPtr->objProc != TclInvokeStringCommand);
  2097.     infoPtr->objProc = cmdPtr->objProc;
  2098.     infoPtr->objClientData = cmdPtr->objClientData;
  2099.     infoPtr->proc = cmdPtr->proc;
  2100.     infoPtr->clientData = cmdPtr->clientData;
  2101.     infoPtr->deleteProc = cmdPtr->deleteProc;
  2102.     infoPtr->deleteData = cmdPtr->deleteData;
  2103.     infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
  2104.     return 1;
  2105. }
  2106. /*
  2107.  *----------------------------------------------------------------------
  2108.  *
  2109.  * Tcl_GetCommandName --
  2110.  *
  2111.  * Given a token returned by Tcl_CreateCommand, this procedure
  2112.  * returns the current name of the command (which may have changed
  2113.  * due to renaming).
  2114.  *
  2115.  * Results:
  2116.  * The return value is the name of the given command.
  2117.  *
  2118.  * Side effects:
  2119.  * None.
  2120.  *
  2121.  *----------------------------------------------------------------------
  2122.  */
  2123. CONST char *
  2124. Tcl_GetCommandName(interp, command)
  2125.     Tcl_Interp *interp; /* Interpreter containing the command. */
  2126.     Tcl_Command command; /* Token for command returned by a previous
  2127.  * call to Tcl_CreateCommand. The command
  2128.  * must not have been deleted. */
  2129. {
  2130.     Command *cmdPtr = (Command *) command;
  2131.     if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
  2132. /*
  2133.  * This should only happen if command was "created" after the
  2134.  * interpreter began to be deleted, so there isn't really any
  2135.  * command. Just return an empty string.
  2136.  */
  2137. return "";
  2138.     }
  2139.     return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
  2140. }
  2141. /*
  2142.  *----------------------------------------------------------------------
  2143.  *
  2144.  * Tcl_GetCommandFullName --
  2145.  *
  2146.  * Given a token returned by, e.g., Tcl_CreateCommand or
  2147.  * Tcl_FindCommand, this procedure appends to an object the command's
  2148.  * full name, qualified by a sequence of parent namespace names. The
  2149.  * command's fully-qualified name may have changed due to renaming.
  2150.  *
  2151.  * Results:
  2152.  * None.
  2153.  *
  2154.  * Side effects:
  2155.  * The command's fully-qualified name is appended to the string
  2156.  * representation of objPtr. 
  2157.  *
  2158.  *----------------------------------------------------------------------
  2159.  */
  2160. void
  2161. Tcl_GetCommandFullName(interp, command, objPtr)
  2162.     Tcl_Interp *interp; /* Interpreter containing the command. */
  2163.     Tcl_Command command; /* Token for command returned by a previous
  2164.  * call to Tcl_CreateCommand. The command
  2165.  * must not have been deleted. */
  2166.     Tcl_Obj *objPtr; /* Points to the object onto which the
  2167.  * command's full name is appended. */
  2168. {
  2169.     Interp *iPtr = (Interp *) interp;
  2170.     register Command *cmdPtr = (Command *) command;
  2171.     char *name;
  2172.     /*
  2173.      * Add the full name of the containing namespace, followed by the "::"
  2174.      * separator, and the command name.
  2175.      */
  2176.     if (cmdPtr != NULL) {
  2177. if (cmdPtr->nsPtr != NULL) {
  2178.     Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1);
  2179.     if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
  2180. Tcl_AppendToObj(objPtr, "::", 2);
  2181.     }
  2182. }
  2183. if (cmdPtr->hPtr != NULL) {
  2184.     name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
  2185.     Tcl_AppendToObj(objPtr, name, -1);
  2186.     }
  2187. }
  2188. /*
  2189.  *----------------------------------------------------------------------
  2190.  *
  2191.  * Tcl_DeleteCommand --
  2192.  *
  2193.  * Remove the given command from the given interpreter.
  2194.  *
  2195.  * Results:
  2196.  * 0 is returned if the command was deleted successfully.
  2197.  * -1 is returned if there didn't exist a command by that name.
  2198.  *
  2199.  * Side effects:
  2200.  * cmdName will no longer be recognized as a valid command for
  2201.  * interp.
  2202.  *
  2203.  *----------------------------------------------------------------------
  2204.  */
  2205. int
  2206. Tcl_DeleteCommand(interp, cmdName)
  2207.     Tcl_Interp *interp; /* Token for command interpreter (returned
  2208.  * by a previous Tcl_CreateInterp call). */
  2209.     CONST char *cmdName; /* Name of command to remove. */
  2210. {
  2211.     Tcl_Command cmd;
  2212.     /*
  2213.      *  Find the desired command and delete it.
  2214.      */
  2215.     cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
  2216.             /*flags*/ 0);
  2217.     if (cmd == (Tcl_Command) NULL) {
  2218. return -1;
  2219.     }
  2220.     return Tcl_DeleteCommandFromToken(interp, cmd);
  2221. }
  2222. /*
  2223.  *----------------------------------------------------------------------
  2224.  *
  2225.  * Tcl_DeleteCommandFromToken --
  2226.  *
  2227.  * Removes the given command from the given interpreter. This procedure
  2228.  * resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead
  2229.  * of a command name for efficiency.
  2230.  *
  2231.  * Results:
  2232.  * 0 is returned if the command was deleted successfully.
  2233.  * -1 is returned if there didn't exist a command by that name.
  2234.  *
  2235.  * Side effects:
  2236.  * The command specified by "cmd" will no longer be recognized as a
  2237.  * valid command for "interp".
  2238.  *
  2239.  *----------------------------------------------------------------------
  2240.  */
  2241. int
  2242. Tcl_DeleteCommandFromToken(interp, cmd)
  2243.     Tcl_Interp *interp; /* Token for command interpreter returned by
  2244.  * a previous call to Tcl_CreateInterp. */
  2245.     Tcl_Command cmd;            /* Token for command to delete. */
  2246. {
  2247.     Interp *iPtr = (Interp *) interp;
  2248.     Command *cmdPtr = (Command *) cmd;
  2249.     ImportRef *refPtr, *nextRefPtr;
  2250.     Tcl_Command importCmd;
  2251.     /*
  2252.      * The code here is tricky.  We can't delete the hash table entry
  2253.      * before invoking the deletion callback because there are cases
  2254.      * where the deletion callback needs to invoke the command (e.g.
  2255.      * object systems such as OTcl). However, this means that the
  2256.      * callback could try to delete or rename the command. The deleted
  2257.      * flag allows us to detect these cases and skip nested deletes.
  2258.      */
  2259.     if (cmdPtr->flags & CMD_IS_DELETED) {
  2260. /*
  2261.  * Another deletion is already in progress.  Remove the hash
  2262.  * table entry now, but don't invoke a callback or free the
  2263.  * command structure.
  2264.  */
  2265.         Tcl_DeleteHashEntry(cmdPtr->hPtr);
  2266. cmdPtr->hPtr = NULL;
  2267. return 0;
  2268.     }
  2269.     /* 
  2270.      * We must delete this command, even though both traces and
  2271.      * delete procs may try to avoid this (renaming the command etc).
  2272.      * Also traces and delete procs may try to delete the command
  2273.      * themsevles.  This flag declares that a delete is in progress
  2274.      * and that recursive deletes should be ignored.
  2275.      */
  2276.     cmdPtr->flags |= CMD_IS_DELETED;
  2277.     /*
  2278.      * Bump the command epoch counter. This will invalidate all cached
  2279.      * references that point to this command.
  2280.      */
  2281.     
  2282.     cmdPtr->cmdEpoch++;
  2283.     /*
  2284.      * Call trace procedures for the command being deleted. Then delete
  2285.      * its traces. 
  2286.      */
  2287.     if (cmdPtr->tracePtr != NULL) {
  2288. CommandTrace *tracePtr;
  2289. CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);
  2290. /* Now delete these traces */
  2291. tracePtr = cmdPtr->tracePtr;
  2292. while (tracePtr != NULL) {
  2293.     CommandTrace *nextPtr = tracePtr->nextPtr;
  2294.     if ((--tracePtr->refCount) <= 0) {
  2295. ckfree((char*)tracePtr);
  2296.     }
  2297.     tracePtr = nextPtr;
  2298. }
  2299. cmdPtr->tracePtr = NULL;
  2300.     }
  2301.     
  2302.     /*
  2303.      * If the command being deleted has a compile procedure, increment the
  2304.      * interpreter's compileEpoch to invalidate its compiled code. This
  2305.      * makes sure that we don't later try to execute old code compiled with
  2306.      * command-specific (i.e., inline) bytecodes for the now-deleted
  2307.      * command. This field is checked in Tcl_EvalObj and ObjInterpProc, and
  2308.      * code whose compilation epoch doesn't match is recompiled.
  2309.      */
  2310.     if (cmdPtr->compileProc != NULL) {
  2311.         iPtr->compileEpoch++;
  2312.     }
  2313.     if (cmdPtr->deleteProc != NULL) {
  2314. /*
  2315.  * Delete the command's client data. If this was an imported command
  2316.  * created when a command was imported into a namespace, this client
  2317.  * data will be a pointer to a ImportedCmdData structure describing
  2318.  * the "real" command that this imported command refers to.
  2319.  */
  2320. /*
  2321.  * If you are getting a crash during the call to deleteProc and
  2322.  * cmdPtr->deleteProc is a pointer to the function free(), the
  2323.  * most likely cause is that your extension allocated memory
  2324.  * for the clientData argument to Tcl_CreateObjCommand() with
  2325.  * the ckalloc() macro and you are now trying to deallocate
  2326.  * this memory with free() instead of ckfree(). You should
  2327.  * pass a pointer to your own method that calls ckfree().
  2328.  */
  2329. (*cmdPtr->deleteProc)(cmdPtr->deleteData);
  2330.     }
  2331.     /*
  2332.      * If this command was imported into other namespaces, then imported
  2333.      * commands were created that refer back to this command. Delete these
  2334.      * imported commands now.
  2335.      */
  2336.     for (refPtr = cmdPtr->importRefPtr;  refPtr != NULL;
  2337.             refPtr = nextRefPtr) {
  2338. nextRefPtr = refPtr->nextPtr;
  2339. importCmd = (Tcl_Command) refPtr->importedCmdPtr;
  2340.         Tcl_DeleteCommandFromToken(interp, importCmd);
  2341.     }
  2342.     /*
  2343.      * Don't use hPtr to delete the hash entry here, because it's
  2344.      * possible that the deletion callback renamed the command.
  2345.      * Instead, use cmdPtr->hptr, and make sure that no-one else
  2346.      * has already deleted the hash entry.
  2347.      */
  2348.     if (cmdPtr->hPtr != NULL) {
  2349. Tcl_DeleteHashEntry(cmdPtr->hPtr);
  2350.     }
  2351.     /*
  2352.      * Mark the Command structure as no longer valid. This allows
  2353.      * TclExecuteByteCode to recognize when a Command has logically been
  2354.      * deleted and a pointer to this Command structure cached in a CmdName
  2355.      * object is invalid. TclExecuteByteCode will look up the command again
  2356.      * in the interpreter's command hashtable.
  2357.      */
  2358.     cmdPtr->objProc = NULL;
  2359.     /*
  2360.      * Now free the Command structure, unless there is another reference to
  2361.      * it from a CmdName Tcl object in some ByteCode code sequence. In that
  2362.      * case, delay the cleanup until all references are either discarded
  2363.      * (when a ByteCode is freed) or replaced by a new reference (when a
  2364.      * cached CmdName Command reference is found to be invalid and
  2365.      * TclExecuteByteCode looks up the command in the command hashtable).
  2366.      */
  2367.     
  2368.     TclCleanupCommand(cmdPtr);
  2369.     return 0;
  2370. }
  2371. static char *
  2372. CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
  2373.     Interp *iPtr; /* Interpreter containing command. */
  2374.     Command *cmdPtr; /* Command whose traces are to be
  2375.  * invoked. */
  2376.     CONST char *oldName;        /* Command's old name, or NULL if we
  2377.                                  * must get the name from cmdPtr */
  2378.     CONST char *newName;        /* Command's new name, or NULL if
  2379.                                  * the command is not being renamed */
  2380.     int flags; /* Flags indicating the type of traces
  2381.  * to trigger, either TCL_TRACE_DELETE
  2382.  * or TCL_TRACE_RENAME. */
  2383. {
  2384.     register CommandTrace *tracePtr;
  2385.     ActiveCommandTrace active;
  2386.     char *result;
  2387.     Tcl_Obj *oldNamePtr = NULL;
  2388.     int mask = (TCL_TRACE_DELETE | TCL_TRACE_RENAME); /* Safety */
  2389.     flags &= mask;
  2390.     if (cmdPtr->flags & CMD_TRACE_ACTIVE) {
  2391. /* 
  2392.  * While a rename trace is active, we will not process any more
  2393.  * rename traces; while a delete trace is active we will never
  2394.  * reach here -- because Tcl_DeleteCommandFromToken checks for the
  2395.  * condition (cmdPtr->flags & CMD_IS_DELETED) and returns immediately
  2396.  * when a command deletion is in progress.  For all other traces,
  2397.  * delete traces will not be invoked but a call to TraceCommandProc
  2398.  * will ensure that tracePtr->clientData is freed whenever the
  2399.  * command "oldName" is deleted.
  2400.  */
  2401. if (cmdPtr->flags & TCL_TRACE_RENAME) {
  2402.     flags &= ~TCL_TRACE_RENAME;
  2403. }
  2404. if (flags == 0) {
  2405.     return NULL;
  2406. }
  2407.     }
  2408.     cmdPtr->flags |= CMD_TRACE_ACTIVE;
  2409.     cmdPtr->refCount++;
  2410.     
  2411.     result = NULL;
  2412.     active.nextPtr = iPtr->activeCmdTracePtr;
  2413.     active.reverseScan = 0;
  2414.     iPtr->activeCmdTracePtr = &active;
  2415.     if (flags & TCL_TRACE_DELETE) {
  2416. flags |= TCL_TRACE_DESTROYED;
  2417.     }
  2418.     active.cmdPtr = cmdPtr;
  2419.     
  2420.     Tcl_Preserve((ClientData) iPtr);
  2421.     
  2422.     for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL;
  2423.  tracePtr = active.nextTracePtr) {
  2424. int traceFlags = (tracePtr->flags & mask);
  2425. active.nextTracePtr = tracePtr->nextPtr;
  2426. if (!(traceFlags & flags)) {
  2427.     continue;
  2428. }
  2429. cmdPtr->flags |= traceFlags;
  2430. if (oldName == NULL) {
  2431.     TclNewObj(oldNamePtr);
  2432.     Tcl_IncrRefCount(oldNamePtr);
  2433.     Tcl_GetCommandFullName((Tcl_Interp *) iPtr, 
  2434.             (Tcl_Command) cmdPtr, oldNamePtr);
  2435.     oldName = TclGetString(oldNamePtr);
  2436. }
  2437. tracePtr->refCount++;
  2438. (*tracePtr->traceProc)(tracePtr->clientData,
  2439. (Tcl_Interp *) iPtr, oldName, newName, flags);
  2440. cmdPtr->flags &= ~traceFlags;
  2441. if ((--tracePtr->refCount) <= 0) {
  2442.     ckfree((char*)tracePtr);
  2443. }
  2444.     }
  2445.     /*
  2446.      * If a new object was created to hold the full oldName,
  2447.      * free it now.
  2448.      */
  2449.     if (oldNamePtr != NULL) {
  2450. TclDecrRefCount(oldNamePtr);
  2451.     }
  2452.     /*
  2453.      * Restore the variable's flags, remove the record of our active
  2454.      * traces, and then return.
  2455.      */
  2456.     cmdPtr->flags &= ~CMD_TRACE_ACTIVE;
  2457.     cmdPtr->refCount--;
  2458.     iPtr->activeCmdTracePtr = active.nextPtr;
  2459.     Tcl_Release((ClientData) iPtr);
  2460.     return result;
  2461. }
  2462. /*
  2463.  *----------------------------------------------------------------------
  2464.  *
  2465.  * TclCleanupCommand --
  2466.  *
  2467.  * This procedure frees up a Command structure unless it is still
  2468.  * referenced from an interpreter's command hashtable or from a CmdName
  2469.  * Tcl object representing the name of a command in a ByteCode
  2470.  * instruction sequence. 
  2471.  *
  2472.  * Results:
  2473.  * None.
  2474.  *
  2475.  * Side effects:
  2476.  * Memory gets freed unless a reference to the Command structure still
  2477.  * exists. In that case the cleanup is delayed until the command is
  2478.  * deleted or when the last ByteCode referring to it is freed.
  2479.  *
  2480.  *----------------------------------------------------------------------
  2481.  */
  2482. void
  2483. TclCleanupCommand(cmdPtr)
  2484.     register Command *cmdPtr; /* Points to the Command structure to
  2485.  * be freed. */
  2486. {
  2487.     cmdPtr->refCount--;
  2488.     if (cmdPtr->refCount <= 0) {
  2489. ckfree((char *) cmdPtr);
  2490.     }
  2491. }
  2492. /*
  2493.  *----------------------------------------------------------------------
  2494.  *
  2495.  * Tcl_CreateMathFunc --
  2496.  *
  2497.  * Creates a new math function for expressions in a given
  2498.  * interpreter.
  2499.  *
  2500.  * Results:
  2501.  * None.
  2502.  *
  2503.  * Side effects:
  2504.  * The function defined by "name" is created or redefined. If the
  2505.  * function already exists then its definition is replaced; this
  2506.  * includes the builtin functions. Redefining a builtin function forces
  2507.  * all existing code to be invalidated since that code may be compiled
  2508.  * using an instruction specific to the replaced function. In addition,
  2509.  * redefioning a non-builtin function will force existing code to be
  2510.  * invalidated if the number of arguments has changed.
  2511.  *
  2512.  *----------------------------------------------------------------------
  2513.  */
  2514. void
  2515. Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
  2516.     Tcl_Interp *interp; /* Interpreter in which function is
  2517.  * to be available. */
  2518.     CONST char *name; /* Name of function (e.g. "sin"). */
  2519.     int numArgs; /* Nnumber of arguments required by
  2520.  * function. */
  2521.     Tcl_ValueType *argTypes; /* Array of types acceptable for
  2522.  * each argument. */
  2523.     Tcl_MathProc *proc; /* Procedure that implements the
  2524.  * math function. */
  2525.     ClientData clientData; /* Additional value to pass to the
  2526.  * function. */
  2527. {
  2528.     Interp *iPtr = (Interp *) interp;
  2529.     Tcl_HashEntry *hPtr;
  2530.     MathFunc *mathFuncPtr;
  2531.     int new, i;
  2532.     hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
  2533.     if (new) {
  2534. Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
  2535.     }
  2536.     mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
  2537.     if (!new) {
  2538. if (mathFuncPtr->builtinFuncIndex >= 0) {
  2539.     /*
  2540.      * We are redefining a builtin math function. Invalidate the
  2541.              * interpreter's existing code by incrementing its
  2542.              * compileEpoch member. This field is checked in Tcl_EvalObj
  2543.              * and ObjInterpProc, and code whose compilation epoch doesn't
  2544.              * match is recompiled. Newly compiled code will no longer
  2545.              * treat the function as builtin.
  2546.      */
  2547.     iPtr->compileEpoch++;
  2548. } else {
  2549.     /*
  2550.      * A non-builtin function is being redefined. We must invalidate
  2551.              * existing code if the number of arguments has changed. This
  2552.      * is because existing code was compiled assuming that number.
  2553.      */
  2554.     if (numArgs != mathFuncPtr->numArgs) {
  2555. iPtr->compileEpoch++;
  2556.     }
  2557. }
  2558.     }
  2559.     
  2560.     mathFuncPtr->builtinFuncIndex = -1; /* can't be a builtin function */
  2561.     if (numArgs > MAX_MATH_ARGS) {
  2562. numArgs = MAX_MATH_ARGS;
  2563.     }
  2564.     mathFuncPtr->numArgs = numArgs;
  2565.     for (i = 0;  i < numArgs;  i++) {
  2566. mathFuncPtr->argTypes[i] = argTypes[i];
  2567.     }
  2568.     mathFuncPtr->proc = proc;
  2569.     mathFuncPtr->clientData = clientData;
  2570. }
  2571. /*
  2572.  *----------------------------------------------------------------------
  2573.  *
  2574.  * Tcl_GetMathFuncInfo --
  2575.  *
  2576.  * Discovers how a particular math function was created in a given
  2577.  * interpreter.
  2578.  *
  2579.  * Results:
  2580.  * TCL_OK if it succeeds, TCL_ERROR else (leaving an error message
  2581.  * in the interpreter result if that happens.)
  2582.  *
  2583.  * Side effects:
  2584.  * If this function succeeds, the variables pointed to by the
  2585.  * numArgsPtr and argTypePtr arguments will be updated to detail the
  2586.  * arguments allowed by the function.  The variable pointed to by the
  2587.  * procPtr argument will be set to NULL if the function is a builtin
  2588.  * function, and will be set to the address of the C function used to
  2589.  * implement the math function otherwise (in which case the variable
  2590.  * pointed to by the clientDataPtr argument will also be updated.)
  2591.  *
  2592.  *----------------------------------------------------------------------
  2593.  */
  2594. int
  2595. Tcl_GetMathFuncInfo(interp, name, numArgsPtr, argTypesPtr, procPtr,
  2596.     clientDataPtr)
  2597.     Tcl_Interp *interp;
  2598.     CONST char *name;
  2599.     int *numArgsPtr;
  2600.     Tcl_ValueType **argTypesPtr;
  2601.     Tcl_MathProc **procPtr;
  2602.     ClientData *clientDataPtr;
  2603. {
  2604.     Interp *iPtr = (Interp *) interp;
  2605.     Tcl_HashEntry *hPtr;
  2606.     MathFunc *mathFuncPtr;
  2607.     Tcl_ValueType *argTypes;
  2608.     int i,numArgs;
  2609.     hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, name);
  2610.     if (hPtr == NULL) {
  2611.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  2612.                 "math function "", name, "" not known in this interpreter",
  2613. (char *) NULL);
  2614. return TCL_ERROR;
  2615.     }
  2616.     mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
  2617.     *numArgsPtr = numArgs = mathFuncPtr->numArgs;
  2618.     if (numArgs == 0) {
  2619. /* Avoid doing zero-sized allocs... */
  2620. numArgs = 1;
  2621.     }
  2622.     *argTypesPtr = argTypes =
  2623. (Tcl_ValueType *)ckalloc(numArgs * sizeof(Tcl_ValueType));
  2624.     for (i = 0; i < mathFuncPtr->numArgs; i++) {
  2625. argTypes[i] = mathFuncPtr->argTypes[i];
  2626.     }
  2627.     if (mathFuncPtr->builtinFuncIndex == -1) {
  2628. *procPtr = (Tcl_MathProc *) NULL;
  2629.     } else {
  2630. *procPtr = mathFuncPtr->proc;
  2631. *clientDataPtr = mathFuncPtr->clientData;
  2632.     }
  2633.     return TCL_OK;
  2634. }
  2635. /*
  2636.  *----------------------------------------------------------------------
  2637.  *
  2638.  * Tcl_ListMathFuncs --
  2639.  *
  2640.  * Produces a list of all the math functions defined in a given
  2641.  * interpreter.
  2642.  *
  2643.  * Results:
  2644.  * A pointer to a Tcl_Obj structure with a reference count of zero,
  2645.  * or NULL in the case of an error (in which case a suitable error
  2646.  * message will be left in the interpreter result.)
  2647.  *
  2648.  * Side effects:
  2649.  * None.
  2650.  *
  2651.  *----------------------------------------------------------------------
  2652.  */
  2653. Tcl_Obj *
  2654. Tcl_ListMathFuncs(interp, pattern)
  2655.     Tcl_Interp *interp;
  2656.     CONST char *pattern;
  2657. {
  2658.     Interp *iPtr = (Interp *) interp;
  2659.     Tcl_Obj *resultList = Tcl_NewObj();
  2660.     register Tcl_HashEntry *hPtr;
  2661.     Tcl_HashSearch hSearch;
  2662.     CONST char *name;
  2663.     for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &hSearch);
  2664.  hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
  2665.         name = Tcl_GetHashKey(&iPtr->mathFuncTable, hPtr);
  2666. if ((pattern == NULL || Tcl_StringMatch(name, pattern)) &&
  2667.     /* I don't expect this to fail, but... */
  2668.     Tcl_ListObjAppendElement(interp, resultList,
  2669.      Tcl_NewStringObj(name,-1)) != TCL_OK) {
  2670.     Tcl_DecrRefCount(resultList);
  2671.     return NULL;
  2672. }
  2673.     }
  2674.     return resultList;
  2675. }
  2676. /*
  2677.  *----------------------------------------------------------------------
  2678.  *
  2679.  * TclInterpReady --
  2680.  *
  2681.  * Check if an interpreter is ready to eval commands or scripts, 
  2682.  *      i.e., if it was not deleted and if the nesting level is not 
  2683.  *      too high.
  2684.  *
  2685.  * Results:
  2686.  * The return value is TCL_OK if it the interpreter is ready, 
  2687.  *      TCL_ERROR otherwise.
  2688.  *
  2689.  * Side effects:
  2690.  * The interpreters object and string results are cleared.
  2691.  *
  2692.  *----------------------------------------------------------------------
  2693.  */
  2694. int 
  2695. TclInterpReady(interp)
  2696.     Tcl_Interp *interp;
  2697. {
  2698.     register Interp *iPtr = (Interp *) interp;
  2699.     /*
  2700.      * Reset both the interpreter's string and object results and clear 
  2701.      * out any previous error information. 
  2702.      */
  2703.     Tcl_ResetResult(interp);
  2704.     /*
  2705.      * If the interpreter has been deleted, return an error.
  2706.      */
  2707.     
  2708.     if (iPtr->flags & DELETED) {
  2709. Tcl_ResetResult(interp);
  2710. Tcl_AppendToObj(Tcl_GetObjResult(interp),
  2711.         "attempt to call eval in deleted interpreter", -1);
  2712. Tcl_SetErrorCode(interp, "CORE", "IDELETE",
  2713.         "attempt to call eval in deleted interpreter",
  2714. (char *) NULL);
  2715. return TCL_ERROR;
  2716.     }
  2717.     /*
  2718.      * Check depth of nested calls to Tcl_Eval:  if this gets too large,
  2719.      * it's probably because of an infinite loop somewhere.
  2720.      */
  2721.     if (((iPtr->numLevels) > iPtr->maxNestingDepth) 
  2722.     || (TclpCheckStackSpace() == 0)) {
  2723. Tcl_AppendToObj(Tcl_GetObjResult(interp),
  2724. "too many nested evaluations (infinite loop?)", -1); 
  2725. return TCL_ERROR;
  2726.     }
  2727.     return TCL_OK;
  2728. }
  2729. /*
  2730.  *----------------------------------------------------------------------
  2731.  *
  2732.  * TclEvalObjvInternal --
  2733.  *
  2734.  * This procedure evaluates a Tcl command that has already been
  2735.  * parsed into words, with one Tcl_Obj holding each word. The caller
  2736.  *      is responsible for managing the iPtr->numLevels.
  2737.  *
  2738.  * Results:
  2739.  * The return value is a standard Tcl completion code such as
  2740.  * TCL_OK or TCL_ERROR.  A result or error message is left in
  2741.  * interp's result.  If an error occurs, this procedure does
  2742.  * NOT add any information to the errorInfo variable.
  2743.  *
  2744.  * Side effects:
  2745.  * Depends on the command.
  2746.  *
  2747.  *----------------------------------------------------------------------
  2748.  */
  2749. int
  2750. TclEvalObjvInternal(interp, objc, objv, command, length, flags)
  2751.     Tcl_Interp *interp; /* Interpreter in which to evaluate the
  2752.  * command.  Also used for error
  2753.  * reporting. */
  2754.     int objc; /* Number of words in command. */
  2755.     Tcl_Obj *CONST objv[]; /* An array of pointers to objects that are
  2756.  * the words that make up the command. */
  2757.     CONST char *command; /* Points to the beginning of the string
  2758.  * representation of the command; this
  2759.  * is used for traces.  If the string
  2760.  * representation of the command is
  2761.  * unknown, an empty string should be
  2762.  * supplied. If it is NULL, no traces will
  2763.  * be called. */
  2764.     int length; /* Number of bytes in command; if -1, all
  2765.  * characters up to the first null byte are
  2766.  * used. */
  2767.     int flags; /* Collection of OR-ed bits that control
  2768.  * the evaluation of the script.  Only
  2769.  * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are