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

通讯编程

开发平台:

Visual C++

  1.  * currently supported. */
  2. {
  3.     Command *cmdPtr;
  4.     Interp *iPtr = (Interp *) interp;
  5.     Tcl_Obj **newObjv;
  6.     int i;
  7.     CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
  8.  * in case TCL_EVAL_GLOBAL was set. */
  9.     int code = TCL_OK;
  10.     int traceCode = TCL_OK;
  11.     int checkTraces = 1;
  12.     Namespace *savedNsPtr = NULL;
  13.     if (TclInterpReady(interp) == TCL_ERROR) {
  14. return TCL_ERROR;
  15.     }
  16.     if (objc == 0) {
  17. return TCL_OK;
  18.     }
  19.     /*
  20.      * If any execution traces rename or delete the current command,
  21.      * we may need (at most) two passes here.
  22.      */
  23.     savedVarFramePtr = iPtr->varFramePtr;
  24.     while (1) {
  25.     
  26. /* Configure evaluation context to match the requested flags */
  27. if (flags & TCL_EVAL_GLOBAL) {
  28.     iPtr->varFramePtr = NULL;
  29. } else if ((flags & TCL_EVAL_INVOKE) && iPtr->varFramePtr) {
  30.     savedNsPtr = iPtr->varFramePtr->nsPtr;
  31.     iPtr->varFramePtr->nsPtr = iPtr->globalNsPtr;
  32. }
  33.         /*
  34.          * Find the procedure to execute this command. If there isn't one,
  35.          * then see if there is a command "unknown".  If so, create a new
  36.          * word array with "unknown" as the first word and the original
  37.          * command words as arguments.  Then call ourselves recursively
  38.          * to execute it.
  39.          */
  40.         cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
  41.         if (cmdPtr == NULL) {
  42.     newObjv = (Tcl_Obj **) ckalloc((unsigned)
  43. ((objc + 1) * sizeof (Tcl_Obj *)));
  44.     for (i = objc-1; i >= 0; i--) {
  45.         newObjv[i+1] = objv[i];
  46.     }
  47.     newObjv[0] = Tcl_NewStringObj("::unknown", -1);
  48.     Tcl_IncrRefCount(newObjv[0]);
  49.     cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
  50.     if (cmdPtr == NULL) {
  51.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  52.     "invalid command name "", Tcl_GetString(objv[0]), """,
  53.     (char *) NULL);
  54.         code = TCL_ERROR;
  55.     } else {
  56.         iPtr->numLevels++;
  57.         code = TclEvalObjvInternal(interp, objc+1, newObjv,
  58. command, length, 0);
  59.         iPtr->numLevels--;
  60.     }
  61.     Tcl_DecrRefCount(newObjv[0]);
  62.     ckfree((char *) newObjv);
  63.     if (savedNsPtr) {
  64. iPtr->varFramePtr->nsPtr = savedNsPtr;
  65.     }
  66.     goto done;
  67.         }
  68. if (savedNsPtr) {
  69.     iPtr->varFramePtr->nsPtr = savedNsPtr;
  70. }
  71.     
  72.         /*
  73.          * Call trace procedures if needed.
  74.          */
  75.         if ((checkTraces) && (command != NULL)) {
  76.             int cmdEpoch = cmdPtr->cmdEpoch;
  77.     int newEpoch;
  78.     
  79.     cmdPtr->refCount++;
  80.             /* 
  81.              * If the first set of traces modifies/deletes the command or
  82.              * any existing traces, then the set checkTraces to 0 and
  83.              * go through this while loop one more time.
  84.              */
  85.             if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
  86.                 traceCode = TclCheckInterpTraces(interp, command, length,
  87.                                cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
  88.             }
  89.             if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) 
  90.     && (traceCode == TCL_OK)) {
  91.                 traceCode = TclCheckExecutionTraces(interp, command, length,
  92.                                cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
  93.             }
  94.     newEpoch = cmdPtr->cmdEpoch;
  95.     TclCleanupCommand(cmdPtr);
  96.             if (cmdEpoch != newEpoch) {
  97.                 /* The command has been modified in some way */
  98.                 checkTraces = 0;
  99.                 continue;
  100.             }
  101.         }
  102.         break;
  103.     }
  104.     if (TCL_DTRACE_CMD_ARGS_ENABLED()) {
  105. char *a[10];
  106. int i = 0;
  107. while (i < 10) {
  108.     a[i] = i < objc ? TclGetString(objv[i]) : NULL; i++;
  109. }
  110. TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
  111. a[8], a[9]);
  112.     }
  113.     /*
  114.      * Finally, invoke the command's Tcl_ObjCmdProc.
  115.      */
  116.     cmdPtr->refCount++;
  117.     iPtr->cmdCount++;
  118.     if ( code == TCL_OK && traceCode == TCL_OK) {
  119. if (TCL_DTRACE_CMD_ENTRY_ENABLED()) {
  120.     TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1,
  121.     (Tcl_Obj **)(objv + 1));
  122. }
  123. code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
  124. if (TCL_DTRACE_CMD_RETURN_ENABLED()) {
  125.     TCL_DTRACE_CMD_RETURN(TclGetString(objv[0]), code);
  126. }
  127.     }
  128.     if (Tcl_AsyncReady()) {
  129. code = Tcl_AsyncInvoke(interp, code);
  130.     }
  131.     /*
  132.      * Call 'leave' command traces
  133.      */
  134.     if (!(cmdPtr->flags & CMD_IS_DELETED)) {
  135. int saveErrFlags = iPtr->flags 
  136. & (ERR_IN_PROGRESS | ERR_ALREADY_LOGGED | ERROR_CODE_SET);
  137.         if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
  138.             traceCode = TclCheckExecutionTraces (interp, command, length,
  139.                    cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
  140.         }
  141.         if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
  142.             traceCode = TclCheckInterpTraces(interp, command, length,
  143.                    cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
  144.         }
  145. if (traceCode == TCL_OK) {
  146.     iPtr->flags |= saveErrFlags;
  147. }
  148.     }
  149.     TclCleanupCommand(cmdPtr);
  150.     /*
  151.      * If one of the trace invocation resulted in error, then 
  152.      * change the result code accordingly. Note, that the
  153.      * interp->result should already be set correctly by the
  154.      * call to TraceExecutionProc.  
  155.      */
  156.     if (traceCode != TCL_OK) {
  157. code = traceCode;
  158.     }
  159.     
  160.     /*
  161.      * If the interpreter has a non-empty string result, the result
  162.      * object is either empty or stale because some procedure set
  163.      * interp->result directly. If so, move the string result to the
  164.      * result object, then reset the string result.
  165.      */
  166.     
  167.     if (*(iPtr->result) != 0) {
  168. (void) Tcl_GetObjResult(interp);
  169.     }
  170.     if (TCL_DTRACE_CMD_RESULT_ENABLED()) {
  171. Tcl_Obj *r;
  172. r = Tcl_GetObjResult(interp);
  173. TCL_DTRACE_CMD_RESULT(TclGetString(objv[0]), code, TclGetString(r), r);
  174.     }
  175.     done:
  176.     iPtr->varFramePtr = savedVarFramePtr;
  177.     return code;
  178. }
  179. /*
  180.  *----------------------------------------------------------------------
  181.  *
  182.  * Tcl_EvalObjv --
  183.  *
  184.  * This procedure evaluates a Tcl command that has already been
  185.  * parsed into words, with one Tcl_Obj holding each word.
  186.  *
  187.  * Results:
  188.  * The return value is a standard Tcl completion code such as
  189.  * TCL_OK or TCL_ERROR.  A result or error message is left in
  190.  * interp's result.
  191.  *
  192.  * Side effects:
  193.  * Depends on the command.
  194.  *
  195.  *----------------------------------------------------------------------
  196.  */
  197. int
  198. Tcl_EvalObjv(interp, objc, objv, flags)
  199.     Tcl_Interp *interp; /* Interpreter in which to evaluate the
  200.  * command.  Also used for error
  201.  * reporting. */
  202.     int objc; /* Number of words in command. */
  203.     Tcl_Obj *CONST objv[]; /* An array of pointers to objects that are
  204.  * the words that make up the command. */
  205.     int flags; /* Collection of OR-ed bits that control
  206.  * the evaluation of the script.  Only
  207.  * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE
  208.  * are  currently supported. */
  209. {
  210.     Interp *iPtr = (Interp *)interp;
  211.     Trace *tracePtr;
  212.     Tcl_DString cmdBuf;
  213.     char *cmdString = ""; /* A command string is only necessary for
  214.  * command traces or error logs; it will be
  215.  * generated to replace this default value if
  216.  * necessary. */
  217.     int cmdLen = 0; /* a non-zero value indicates that a command
  218.  * string was generated. */
  219.     int code = TCL_OK;
  220.     int i;
  221.     int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
  222.     for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) {
  223. if ((tracePtr->level == 0) || (iPtr->numLevels <= tracePtr->level)) {
  224.     /*
  225.      * The command may be needed for an execution trace.  Generate a
  226.      * command string.
  227.      */
  228.     
  229.     Tcl_DStringInit(&cmdBuf);
  230.     for (i = 0; i < objc; i++) {
  231. Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
  232.     }
  233.     cmdString = Tcl_DStringValue(&cmdBuf);
  234.     cmdLen = Tcl_DStringLength(&cmdBuf);
  235.     break;
  236. }
  237.     }
  238.     iPtr->numLevels++;
  239.     code = TclEvalObjvInternal(interp, objc, objv, cmdString, cmdLen, flags);
  240.     iPtr->numLevels--;
  241.     /*
  242.      * If we are again at the top level, process any unusual 
  243.      * return code returned by the evaluated code. 
  244.      */
  245.     if (iPtr->numLevels == 0) {
  246. if (code == TCL_RETURN) {
  247.     code = TclUpdateReturnInfo(iPtr);
  248. }
  249. if ((code != TCL_OK) && (code != TCL_ERROR) 
  250.     && !allowExceptions) {
  251.     ProcessUnexpectedResult(interp, code);
  252.     code = TCL_ERROR;
  253. }
  254.     }
  255.     
  256.     if ((code == TCL_ERROR) && !(flags & TCL_EVAL_INVOKE)) {
  257. /* 
  258.  * If there was an error, a command string will be needed for the 
  259.  * error log: generate it now if it was not done previously.
  260.  */
  261. if (cmdLen == 0) {
  262.     Tcl_DStringInit(&cmdBuf);
  263.     for (i = 0; i < objc; i++) {
  264. Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
  265.     }
  266.     cmdString = Tcl_DStringValue(&cmdBuf);
  267.     cmdLen = Tcl_DStringLength(&cmdBuf);
  268. }
  269. Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
  270.     }
  271.     if (cmdLen != 0) {
  272. Tcl_DStringFree(&cmdBuf);
  273.     }
  274.     return code;
  275. }
  276. /*
  277.  *----------------------------------------------------------------------
  278.  *
  279.  * Tcl_LogCommandInfo --
  280.  *
  281.  * This procedure is invoked after an error occurs in an interpreter.
  282.  * It adds information to the "errorInfo" variable to describe the
  283.  * command that was being executed when the error occurred.
  284.  *
  285.  * Results:
  286.  * None.
  287.  *
  288.  * Side effects:
  289.  * Information about the command is added to errorInfo and the
  290.  * line number stored internally in the interpreter is set.  If this
  291.  * is the first call to this procedure or Tcl_AddObjErrorInfo since
  292.  * an error occurred, then old information in errorInfo is
  293.  * deleted.
  294.  *
  295.  *----------------------------------------------------------------------
  296.  */
  297. void
  298. Tcl_LogCommandInfo(interp, script, command, length)
  299.     Tcl_Interp *interp; /* Interpreter in which to log information. */
  300.     CONST char *script; /* First character in script containing
  301.  * command (must be <= command). */
  302.     CONST char *command; /* First character in command that
  303.  * generated the error. */
  304.     int length; /* Number of bytes in command (-1 means
  305.  * use all bytes up to first null byte). */
  306. {
  307.     char buffer[200];
  308.     register CONST char *p;
  309.     char *ellipsis = "";
  310.     Interp *iPtr = (Interp *) interp;
  311.     if (iPtr->flags & ERR_ALREADY_LOGGED) {
  312. /*
  313.  * Someone else has already logged error information for this
  314.  * command; we shouldn't add anything more.
  315.  */
  316. return;
  317.     }
  318.     /*
  319.      * Compute the line number where the error occurred.
  320.      */
  321.     iPtr->errorLine = 1;
  322.     for (p = script; p != command; p++) {
  323. if (*p == 'n') {
  324.     iPtr->errorLine++;
  325. }
  326.     }
  327.     /*
  328.      * Create an error message to add to errorInfo, including up to a
  329.      * maximum number of characters of the command.
  330.      */
  331.     if (length < 0) {
  332. length = strlen(command);
  333.     }
  334.     if (length > 150) {
  335. length = 150;
  336. ellipsis = "...";
  337.     }
  338.     while ( (command[length] & 0xC0) == 0x80 ) {
  339. /*
  340.  * Back up truncation point so that we don't truncate in the
  341.  * middle of a multi-byte character (in UTF-8)
  342.  */
  343. length--;
  344. ellipsis = "...";
  345.     }
  346.     if (!(iPtr->flags & ERR_IN_PROGRESS)) {
  347. sprintf(buffer, "n    while executingn"%.*s%s"",
  348. length, command, ellipsis);
  349.     } else {
  350. sprintf(buffer, "n    invoked from withinn"%.*s%s"",
  351. length, command, ellipsis);
  352.     }
  353.     Tcl_AddObjErrorInfo(interp, buffer, -1);
  354.     iPtr->flags &= ~ERR_ALREADY_LOGGED;
  355. }
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * Tcl_EvalTokensStandard, EvalTokensStandard --
  360.  *
  361.  * Given an array of tokens parsed from a Tcl command (e.g., the
  362.  * tokens that make up a word or the index for an array variable)
  363.  * this procedure evaluates the tokens and concatenates their
  364.  * values to form a single result value.
  365.  * 
  366.  * Results:
  367.  * The return value is a standard Tcl completion code such as
  368.  * TCL_OK or TCL_ERROR.  A result or error message is left in
  369.  * interp's result.
  370.  *
  371.  * Side effects:
  372.  * Depends on the array of tokens being evaled.
  373.  *
  374.  * TIP #280 : Keep public API, internally extended API.
  375.  *----------------------------------------------------------------------
  376.  */
  377. int
  378. Tcl_EvalTokensStandard(interp, tokenPtr, count)
  379.     Tcl_Interp *interp; /* Interpreter in which to lookup
  380.  * variables, execute nested commands,
  381.  * and report errors. */
  382.     Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
  383.  * to evaluate and concatenate. */
  384.     int count; /* Number of tokens to consider at tokenPtr.
  385.  * Must be at least 1. */
  386. {
  387. #ifdef TCL_TIP280
  388.   return EvalTokensStandard (interp, tokenPtr, count, 1);
  389. }
  390. static int
  391. EvalTokensStandard(interp, tokenPtr, count, line)
  392.     Tcl_Interp *interp; /* Interpreter in which to lookup
  393.  * variables, execute nested commands,
  394.  * and report errors. */
  395.     Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
  396.  * to evaluate and concatenate. */
  397.     int count; /* Number of tokens to consider at tokenPtr.
  398.  * Must be at least 1. */
  399.     int line;                   /* The line the script starts on. */
  400. {
  401. #endif
  402.     Tcl_Obj *resultPtr, *indexPtr, *valuePtr;
  403.     char buffer[TCL_UTF_MAX];
  404. #ifdef TCL_MEM_DEBUG
  405. #   define  MAX_VAR_CHARS 5
  406. #else
  407. #   define  MAX_VAR_CHARS 30
  408. #endif
  409.     char nameBuffer[MAX_VAR_CHARS+1];
  410.     char *varName, *index;
  411.     CONST char *p = NULL; /* Initialized to avoid compiler warning. */
  412.     int length, code;
  413.     /*
  414.      * The only tricky thing about this procedure is that it attempts to
  415.      * avoid object creation and string copying whenever possible.  For
  416.      * example, if the value is just a nested command, then use the
  417.      * command's result object directly.
  418.      */
  419.     code = TCL_OK;
  420.     resultPtr = NULL;
  421.     Tcl_ResetResult(interp);
  422.     for ( ; count > 0; count--, tokenPtr++) {
  423. valuePtr = NULL;
  424. /*
  425.  * The switch statement below computes the next value to be
  426.  * concat to the result, as either a range of text or an
  427.  * object.
  428.  */
  429. switch (tokenPtr->type) {
  430.     case TCL_TOKEN_TEXT:
  431. p = tokenPtr->start;
  432. length = tokenPtr->size;
  433. break;
  434.     case TCL_TOKEN_BS:
  435. length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL,
  436. buffer);
  437. p = buffer;
  438. break;
  439.     case TCL_TOKEN_COMMAND: {
  440. Interp *iPtr = (Interp *) interp;
  441. iPtr->numLevels++;
  442. code = TclInterpReady(interp);
  443. if (code == TCL_OK) {
  444. #ifndef TCL_TIP280
  445.     code = Tcl_EvalEx(interp,
  446.     tokenPtr->start+1, tokenPtr->size-2, 0);
  447. #else
  448.     /* TIP #280: Transfer line information to nested command */
  449.     code = EvalEx(interp,
  450.     tokenPtr->start+1, tokenPtr->size-2, 0, line);
  451. #endif
  452. }
  453. iPtr->numLevels--;
  454. if (code != TCL_OK) {
  455.     goto done;
  456. }
  457. valuePtr = Tcl_GetObjResult(interp);
  458. break;
  459.     }
  460.     case TCL_TOKEN_VARIABLE:
  461. if (tokenPtr->numComponents == 1) {
  462.     indexPtr = NULL;
  463.     index = NULL;
  464. } else {
  465. #ifndef TCL_TIP280
  466.     code = Tcl_EvalTokensStandard(interp, tokenPtr+2,
  467.     tokenPtr->numComponents - 1);
  468. #else
  469.     /* TIP #280: Transfer line information to nested command */
  470.     code = EvalTokensStandard(interp, tokenPtr+2,
  471.     tokenPtr->numComponents - 1, line);
  472. #endif
  473.     if (code != TCL_OK) {
  474. goto done;
  475.     }
  476.     indexPtr = Tcl_GetObjResult(interp);
  477.     Tcl_IncrRefCount(indexPtr);
  478.     index = Tcl_GetString(indexPtr);
  479. }
  480. /*
  481.  * We have to make a copy of the variable name in order
  482.  * to have a null-terminated string.  We can't make a
  483.  * temporary modification to the script to null-terminate
  484.  * the name, because a trace callback might potentially
  485.  * reuse the script and be affected by the null character.
  486.  */
  487. if (tokenPtr[1].size <= MAX_VAR_CHARS) {
  488.     varName = nameBuffer;
  489. } else {
  490.     varName = ckalloc((unsigned) (tokenPtr[1].size + 1));
  491. }
  492. strncpy(varName, tokenPtr[1].start, (size_t) tokenPtr[1].size);
  493. varName[tokenPtr[1].size] = 0;
  494. valuePtr = Tcl_GetVar2Ex(interp, varName, index,
  495. TCL_LEAVE_ERR_MSG);
  496. if (varName != nameBuffer) {
  497.     ckfree(varName);
  498. }
  499. if (indexPtr != NULL) {
  500.     Tcl_DecrRefCount(indexPtr);
  501. }
  502. if (valuePtr == NULL) {
  503.     code = TCL_ERROR;
  504.     goto done;
  505. }
  506. count -= tokenPtr->numComponents;
  507. tokenPtr += tokenPtr->numComponents;
  508. break;
  509.     default:
  510. panic("unexpected token type in Tcl_EvalTokensStandard");
  511. }
  512. /*
  513.  * If valuePtr isn't NULL, the next piece of text comes from that
  514.  * object; otherwise, take length bytes starting at p.
  515.  */
  516. if (resultPtr == NULL) {
  517.     if (valuePtr != NULL) {
  518. resultPtr = valuePtr;
  519.     } else {
  520. resultPtr = Tcl_NewStringObj(p, length);
  521.     }
  522.     Tcl_IncrRefCount(resultPtr);
  523. } else {
  524.     if (Tcl_IsShared(resultPtr)) {
  525. Tcl_DecrRefCount(resultPtr);
  526. resultPtr = Tcl_DuplicateObj(resultPtr);
  527. Tcl_IncrRefCount(resultPtr);
  528.     }
  529.     if (valuePtr != NULL) {
  530. p = Tcl_GetStringFromObj(valuePtr, &length);
  531.     }
  532.     Tcl_AppendToObj(resultPtr, p, length);
  533. }
  534.     }
  535.     if (resultPtr != NULL) {
  536. Tcl_SetObjResult(interp, resultPtr);
  537.     } else {
  538. code = TCL_ERROR;
  539.     }
  540.     done:
  541.     if (resultPtr != NULL) {
  542. Tcl_DecrRefCount(resultPtr);
  543.     }
  544.     return code;
  545. }
  546. /*
  547.  *----------------------------------------------------------------------
  548.  *
  549.  * Tcl_EvalTokens --
  550.  *
  551.  * Given an array of tokens parsed from a Tcl command (e.g., the
  552.  * tokens that make up a word or the index for an array variable)
  553.  * this procedure evaluates the tokens and concatenates their
  554.  * values to form a single result value.
  555.  *
  556.  * Results:
  557.  * The return value is a pointer to a newly allocated Tcl_Obj
  558.  * containing the value of the array of tokens.  The reference
  559.  * count of the returned object has been incremented.  If an error
  560.  * occurs in evaluating the tokens then a NULL value is returned
  561.  * and an error message is left in interp's result.
  562.  *
  563.  * Side effects:
  564.  * A new object is allocated to hold the result.
  565.  *
  566.  *----------------------------------------------------------------------
  567.  *
  568.  * This uses a non-standard return convention; its use is now deprecated.
  569.  * It is a wrapper for the new function Tcl_EvalTokensStandard, and is not 
  570.  * used in the core any longer. It is only kept for backward compatibility.
  571.  */
  572. Tcl_Obj *
  573. Tcl_EvalTokens(interp, tokenPtr, count)
  574.     Tcl_Interp *interp; /* Interpreter in which to lookup
  575.  * variables, execute nested commands,
  576.  * and report errors. */
  577.     Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
  578.  * to evaluate and concatenate. */
  579.     int count; /* Number of tokens to consider at tokenPtr.
  580.  * Must be at least 1. */
  581. {
  582.     int code;
  583.     Tcl_Obj *resPtr;
  584.     
  585.     code = Tcl_EvalTokensStandard(interp, tokenPtr, count);
  586.     if (code == TCL_OK) {
  587. resPtr = Tcl_GetObjResult(interp);
  588. Tcl_IncrRefCount(resPtr);
  589. Tcl_ResetResult(interp);
  590. return resPtr;
  591.     } else {
  592. return NULL;
  593.     }
  594. }
  595. /*
  596.  *----------------------------------------------------------------------
  597.  *
  598.  * Tcl_EvalEx, EvalEx --
  599.  *
  600.  * This procedure evaluates a Tcl script without using the compiler
  601.  * or byte-code interpreter.  It just parses the script, creates
  602.  * values for each word of each command, then calls EvalObjv
  603.  * to execute each command.
  604.  *
  605.  * Results:
  606.  * The return value is a standard Tcl completion code such as
  607.  * TCL_OK or TCL_ERROR.  A result or error message is left in
  608.  * interp's result.
  609.  *
  610.  * Side effects:
  611.  * Depends on the script.
  612.  *
  613.  * TIP #280 : Keep public API, internally extended API.
  614.  *----------------------------------------------------------------------
  615.  */
  616. int
  617. Tcl_EvalEx(interp, script, numBytes, flags)
  618.     Tcl_Interp *interp; /* Interpreter in which to evaluate the
  619.  * script.  Also used for error reporting. */
  620.     CONST char *script; /* First character of script to evaluate. */
  621.     int numBytes; /* Number of bytes in script.  If < 0, the
  622.  * script consists of all bytes up to the
  623.  * first null character. */
  624.     int flags; /* Collection of OR-ed bits that control
  625.  * the evaluation of the script.  Only
  626.  * TCL_EVAL_GLOBAL is currently
  627.  * supported. */
  628. {
  629. #ifdef TCL_TIP280
  630.   return EvalEx (interp, script, numBytes, flags, 1);
  631. }
  632. static int
  633. EvalEx(interp, script, numBytes, flags, line)
  634.     Tcl_Interp *interp; /* Interpreter in which to evaluate the
  635.  * script.  Also used for error reporting. */
  636.     CONST char *script; /* First character of script to evaluate. */
  637.     int numBytes; /* Number of bytes in script.  If < 0, the
  638.  * script consists of all bytes up to the
  639.  * first null character. */
  640.     int flags; /* Collection of OR-ed bits that control
  641.  * the evaluation of the script.  Only
  642.  * TCL_EVAL_GLOBAL is currently
  643.  * supported. */
  644.     int line;                   /* The line the script starts on. */
  645. {
  646. #endif
  647.     Interp *iPtr = (Interp *) interp;
  648.     CONST char *p, *next;
  649.     Tcl_Parse parse;
  650. #define NUM_STATIC_OBJS 20
  651.     Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv;
  652.     Tcl_Token *tokenPtr;
  653.     int code = TCL_OK;
  654.     int i, commandLength, bytesLeft, nested;
  655.     CallFrame *savedVarFramePtr;   /* Saves old copy of iPtr->varFramePtr
  656.     * in case TCL_EVAL_GLOBAL was set. */
  657.     int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
  658.     
  659.     /*
  660.      * The variables below keep track of how much state has been
  661.      * allocated while evaluating the script, so that it can be freed
  662.      * properly if an error occurs.
  663.      */
  664.     int gotParse = 0, objectsUsed = 0;
  665. #ifdef TCL_TIP280
  666.     /* TIP #280 Structures for tracking of command locations. */
  667.     CmdFrame eeFrame;
  668. #endif
  669.     if (numBytes < 0) {
  670. numBytes = strlen(script);
  671.     }
  672.     Tcl_ResetResult(interp);
  673.     savedVarFramePtr = iPtr->varFramePtr;
  674.     if (flags & TCL_EVAL_GLOBAL) {
  675. iPtr->varFramePtr = NULL;
  676.     }
  677.     /*
  678.      * Each iteration through the following loop parses the next
  679.      * command from the script and then executes it.
  680.      */
  681.     objv = staticObjArray;
  682.     p = script;
  683.     bytesLeft = numBytes;
  684.     if (iPtr->evalFlags & TCL_BRACKET_TERM) {
  685. nested = 1;
  686.     } else {
  687. nested = 0;
  688.     }
  689. #ifdef TCL_TIP280
  690.     /* TIP #280 Initialize tracking. Do not push on the frame stack yet. */
  691.     /*
  692.      * We may cont. counting based on a specific context (CTX), or open a new
  693.      * context, either for a sourced script, or 'eval'. For sourced files we
  694.      * always have a path object, even if nothing was specified in the interp
  695.      * itself. That makes code using it simpler as NULL checks can be left
  696.      * out. Sourced file without path in the 'scriptFile' is possible during
  697.      * Tcl initialization.
  698.      */
  699.     if (iPtr->evalFlags & TCL_EVAL_CTX) {
  700.         /* Path information comes out of the context. */
  701.         eeFrame.type           = TCL_LOCATION_SOURCE;
  702. eeFrame.data.eval.path = iPtr->invokeCmdFramePtr->data.eval.path;
  703. Tcl_IncrRefCount (eeFrame.data.eval.path);
  704.     } else if (iPtr->evalFlags & TCL_EVAL_FILE) {
  705. /* Set up for a sourced file */
  706.         eeFrame.type = TCL_LOCATION_SOURCE;
  707. if (iPtr->scriptFile) {
  708.     /* Normalization here, to have the correct pwd. Should have
  709.      * negligible impact on performance, as the norm should have been
  710.      * done already by the 'source' invoking us, and it caches the
  711.      * result
  712.      */
  713.     Tcl_Obj* norm = Tcl_FSGetNormalizedPath (interp, iPtr->scriptFile);
  714.     if (!norm) {
  715. /* Error message in the interp result */
  716. return TCL_ERROR;
  717.     }
  718.     eeFrame.data.eval.path = norm;
  719.     Tcl_IncrRefCount (eeFrame.data.eval.path);
  720. } else {
  721.     eeFrame.data.eval.path = Tcl_NewStringObj ("",-1);
  722. }
  723.     } else {
  724. /* Set up for plain eval */
  725.         eeFrame.type           = TCL_LOCATION_EVAL;
  726. eeFrame.data.eval.path = NULL;
  727.     }
  728.     eeFrame.level     = (iPtr->cmdFramePtr == NULL
  729.  ? 1
  730.  : iPtr->cmdFramePtr->level + 1);
  731.     eeFrame.framePtr  = iPtr->framePtr;
  732.     eeFrame.nextPtr   = iPtr->cmdFramePtr;
  733.     eeFrame.nline     = 0;
  734.     eeFrame.line      = NULL;
  735. #endif
  736.     iPtr->evalFlags = 0;
  737.     do {
  738. if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse)
  739.         != TCL_OK) {
  740.     code = TCL_ERROR;
  741.     goto error;
  742. }
  743. gotParse = 1; 
  744. if (nested && parse.term == (script + numBytes)) {
  745.     /*
  746.      * A nested script can only terminate in ']'. If
  747.      * the parsing got terminated at the end of the script,
  748.      * there was no closing ']'.  Report the syntax error.
  749.      */
  750.     code = TCL_ERROR;
  751.     goto error;
  752. }
  753. #ifdef TCL_TIP280
  754. /*
  755.  * TIP #280 Track lines. The parser may have skipped text till it
  756.  * found the command we are now at. We have count the lines in this
  757.  * block.
  758.  */
  759. TclAdvanceLines (&line, p, parse.commandStart);
  760. #endif
  761. if (parse.numWords > 0) {
  762. #ifdef TCL_TIP280
  763.     /*
  764.      * TIP #280. Track lines within the words of the current
  765.      * command.
  766.      */
  767.     int         wordLine  = line;
  768.     CONST char* wordStart = parse.commandStart;
  769. #endif
  770.     /*
  771.      * Generate an array of objects for the words of the command.
  772.      */
  773.     
  774.     if (parse.numWords <= NUM_STATIC_OBJS) {
  775. objv = staticObjArray;
  776.     } else {
  777. objv = (Tcl_Obj **) ckalloc((unsigned)
  778.     (parse.numWords * sizeof (Tcl_Obj *)));
  779.     }
  780. #ifdef TCL_TIP280
  781.     eeFrame.nline = parse.numWords;
  782.     eeFrame.line  = (int*) ckalloc((unsigned)
  783.   (parse.numWords * sizeof (int)));
  784. #endif
  785.     for (objectsUsed = 0, tokenPtr = parse.tokenPtr;
  786.  objectsUsed < parse.numWords;
  787.  objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) {
  788. #ifndef TCL_TIP280
  789. code = Tcl_EvalTokensStandard(interp, tokenPtr+1, 
  790.             tokenPtr->numComponents);
  791. #else
  792.         /*
  793.  * TIP #280. Track lines to current word. Save the
  794.  * information on a per-word basis, signaling dynamic words as
  795.  * needed. Make the information available to the recursively
  796.  * called evaluator as well, including the type of context
  797.  * (source vs. eval).
  798.  */
  799. TclAdvanceLines (&wordLine, wordStart, tokenPtr->start);
  800. wordStart = tokenPtr->start;
  801.                 eeFrame.line [objectsUsed] = (TclWordKnownAtCompileTime (tokenPtr)
  802.       ? wordLine
  803.       : -1);
  804.         if (eeFrame.type == TCL_LOCATION_SOURCE) {
  805.     iPtr->evalFlags |= TCL_EVAL_FILE;
  806. }
  807. code = EvalTokensStandard(interp, tokenPtr+1, 
  808.             tokenPtr->numComponents, wordLine);
  809. iPtr->evalFlags = 0;
  810. #endif
  811. if (code == TCL_OK) {
  812.     objv[objectsUsed] = Tcl_GetObjResult(interp);
  813.     Tcl_IncrRefCount(objv[objectsUsed]);
  814. } else {
  815.     goto error;
  816. }
  817.     }
  818.     
  819.     /*
  820.      * Execute the command and free the objects for its words.
  821.      *
  822.      * TIP #280: Remember the command itself for 'info frame'. We
  823.      * shorten the visible command by one char to exclude the
  824.      * termination character, if necessary. Here is where we put our
  825.      * frame on the stack of frames too. _After_ the nested commands
  826.      * have been executed.
  827.      */
  828. #ifdef TCL_TIP280
  829.     eeFrame.cmd.str.cmd = parse.commandStart;
  830.     eeFrame.cmd.str.len = parse.commandSize;
  831.     if (parse.term == parse.commandStart + parse.commandSize - 1) {
  832. eeFrame.cmd.str.len --;
  833.     }
  834.     iPtr->cmdFramePtr = &eeFrame;
  835. #endif
  836.     iPtr->numLevels++;    
  837.     code = TclEvalObjvInternal(interp, objectsUsed, objv, 
  838.             parse.commandStart, parse.commandSize, 0);
  839.     iPtr->numLevels--;
  840. #ifdef TCL_TIP280
  841.     iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
  842.     ckfree ((char*) eeFrame.line);
  843.     eeFrame.line  = NULL;
  844.     eeFrame.nline = 0;
  845. #endif
  846.     if (code != TCL_OK) {
  847. goto error;
  848.     }
  849.     for (i = 0; i < objectsUsed; i++) {
  850. Tcl_DecrRefCount(objv[i]);
  851.     }
  852.     objectsUsed = 0;
  853.     if (objv != staticObjArray) {
  854. ckfree((char *) objv);
  855. objv = staticObjArray;
  856.     }
  857. }
  858. /*
  859.  * Advance to the next command in the script.
  860.  *
  861.  * TIP #280 Track Lines. Now we track how many lines were in the
  862.  * executed command.
  863.  */
  864. next = parse.commandStart + parse.commandSize;
  865. bytesLeft -= next - p;
  866. p = next;
  867. #ifdef TCL_TIP280
  868. TclAdvanceLines (&line, parse.commandStart, p);
  869. #endif
  870. Tcl_FreeParse(&parse);
  871. gotParse = 0;
  872. if (nested && (*parse.term == ']')) {
  873.     /*
  874.      * We get here in the special case where the TCL_BRACKET_TERM
  875.      * flag was set in the interpreter and the latest parsed command
  876.      * was terminated by the matching close-bracket we seek.
  877.      * Return immediately.
  878.      */
  879.     iPtr->termOffset = (p - 1) - script;
  880.     iPtr->varFramePtr = savedVarFramePtr;
  881. #ifndef TCL_TIP280
  882.     return TCL_OK;
  883. #else
  884.     code = TCL_OK;
  885.     goto cleanup_return;
  886. #endif
  887. }
  888.     } while (bytesLeft > 0);
  889.     if (nested) {
  890. /*
  891.  * This nested script did not terminate in ']', it is an error.
  892.  */
  893. code = TCL_ERROR;
  894. goto error;
  895.     }
  896.     
  897.     iPtr->termOffset = p - script;
  898.     iPtr->varFramePtr = savedVarFramePtr;
  899. #ifndef TCL_TIP280
  900.     return TCL_OK;
  901. #else
  902.     code = TCL_OK;
  903.     goto cleanup_return;
  904. #endif
  905.     error:
  906.     /*
  907.      * Generate various pieces of error information, such as the line
  908.      * number where the error occurred and information to add to the
  909.      * errorInfo variable.  Then free resources that had been allocated
  910.      * to the command.
  911.      */
  912.     if (iPtr->numLevels == 0) {
  913. if (code == TCL_RETURN) {
  914.     code = TclUpdateReturnInfo(iPtr);
  915. }
  916. if ((code != TCL_OK) && (code != TCL_ERROR) 
  917. && !allowExceptions) {
  918.     ProcessUnexpectedResult(interp, code);
  919.     code = TCL_ERROR;
  920. }
  921.     }
  922.     if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { 
  923. commandLength = parse.commandSize;
  924. if (parse.term == parse.commandStart + commandLength - 1) {
  925.     /*
  926.      * The terminator character (such as ; or ]) of the command where
  927.      * the error occurred is the last character in the parsed command.
  928.      * Reduce the length by one so that the error message doesn't
  929.      * include the terminator character.
  930.      */
  931.     
  932.     commandLength -= 1;
  933. }
  934. Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength);
  935.     }
  936.     
  937.     for (i = 0; i < objectsUsed; i++) {
  938. Tcl_DecrRefCount(objv[i]);
  939.     }
  940.     if (gotParse) {
  941. Tcl_FreeParse(&parse);
  942.     }
  943.     if (objv != staticObjArray) {
  944. ckfree((char *) objv);
  945.     }
  946.     iPtr->varFramePtr = savedVarFramePtr;
  947.     /*
  948.      * All that's left to do before returning is to set iPtr->termOffset
  949.      * to point past the end of the script we just evaluated.
  950.      */
  951.     next = parse.commandStart + parse.commandSize;
  952.     bytesLeft -= next - p;
  953.     p = next;
  954.     if (!nested) {
  955. iPtr->termOffset = p - script;
  956. #ifndef TCL_TIP280
  957. return code;
  958. #else
  959. goto cleanup_return;
  960. #endif
  961.     }
  962.     /*
  963.      * When we are nested (the TCL_BRACKET_TERM flag was set in the
  964.      * interpreter), we must find the matching close-bracket to
  965.      * end the script we are evaluating.
  966.      *
  967.      * When our return code is TCL_CONTINUE or TCL_RETURN, we want
  968.      * to correctly set iPtr->termOffset to point to that matching
  969.      * close-bracket so our caller can move to the part of the
  970.      * string beyond the script we were asked to evaluate.
  971.      * So we try to parse past the rest of the commands.
  972.      */
  973.     next = NULL;
  974.     while (bytesLeft && (*parse.term != ']')) {
  975. if (TCL_OK != Tcl_ParseCommand(NULL, p, bytesLeft, 1, &parse)) {
  976.     /*
  977.      * Syntax error.  Set the termOffset to the beginning of
  978.      * the last command parsed.
  979.      */
  980.     if (next == NULL) {
  981.         iPtr->termOffset = (parse.commandStart - 1) - script;
  982.     } else {
  983.         iPtr->termOffset = (next - 1) - script;
  984.     }
  985. #ifndef TCL_TIP280
  986.     return code;
  987. #else
  988.     goto cleanup_return;
  989. #endif
  990. }
  991. next = parse.commandStart + parse.commandSize;
  992. bytesLeft -= next - p;
  993. p = next;
  994. next = parse.commandStart;
  995. Tcl_FreeParse(&parse);
  996.     }
  997.     if (bytesLeft) {
  998. /* 
  999.  * parse.term points to the close-bracket.
  1000.  */
  1001. iPtr->termOffset = parse.term - script;
  1002.     } else if (parse.term == script + numBytes) {
  1003. /*
  1004.  * There was no close-bracket.  Syntax error.
  1005.  */
  1006. iPtr->termOffset = parse.term - script;
  1007. Tcl_SetObjResult(interp,
  1008. Tcl_NewStringObj("missing close-bracket", -1));
  1009. #ifndef TCL_TIP280
  1010. return TCL_ERROR;
  1011. #else
  1012. code = TCL_ERROR;
  1013. goto cleanup_return;
  1014. #endif
  1015.     } else if (*parse.term != ']') {
  1016. /*
  1017.  * There was no close-bracket.  Syntax error.
  1018.  */
  1019. iPtr->termOffset = (parse.term + 1) - script;
  1020. Tcl_SetObjResult(interp,
  1021. Tcl_NewStringObj("missing close-bracket", -1));
  1022. #ifndef TCL_TIP280
  1023. return TCL_ERROR;
  1024. #else
  1025. code = TCL_ERROR;
  1026. goto cleanup_return;
  1027. #endif
  1028.     } else {
  1029. /* 
  1030.  * parse.term points to the close-bracket.
  1031.  */
  1032. iPtr->termOffset = parse.term - script;
  1033.     }
  1034. #ifdef TCL_TIP280
  1035.  cleanup_return:
  1036.     /* TIP #280. Release the local CmdFrame, and its contents. */
  1037.     if (eeFrame.line != NULL) {
  1038.         ckfree ((char*) eeFrame.line);
  1039.     }
  1040.     if (eeFrame.type == TCL_LOCATION_SOURCE) {
  1041.         Tcl_DecrRefCount (eeFrame.data.eval.path);
  1042.     }
  1043. #endif
  1044.     return code;
  1045. }
  1046. #ifdef TCL_TIP280
  1047. /*
  1048.  *----------------------------------------------------------------------
  1049.  *
  1050.  * TclAdvanceLines --
  1051.  *
  1052.  * This procedure is a helper which counts the number of lines
  1053.  * in a block of text and advances an external counter.
  1054.  *
  1055.  * Results:
  1056.  * None.
  1057.  *
  1058.  * Side effects:
  1059.  * The specified counter is advanced per the number of lines found.
  1060.  *
  1061.  * TIP #280
  1062.  *----------------------------------------------------------------------
  1063.  */
  1064. void
  1065. TclAdvanceLines (line,start,end)
  1066.      int*        line;
  1067.      CONST char* start;
  1068.      CONST char* end;
  1069. {
  1070.     CONST char* p;
  1071.     for (p = start; p < end; p++) {
  1072.         if (*p == 'n') {
  1073.   (*line) ++;
  1074. }
  1075.     }
  1076. }
  1077. #endif
  1078. /*
  1079.  *----------------------------------------------------------------------
  1080.  *
  1081.  * Tcl_Eval --
  1082.  *
  1083.  * Execute a Tcl command in a string.  This procedure executes the
  1084.  * script directly, rather than compiling it to bytecodes.  Before
  1085.  * the arrival of the bytecode compiler in Tcl 8.0 Tcl_Eval was
  1086.  * the main procedure used for executing Tcl commands, but nowadays
  1087.  * it isn't used much.
  1088.  *
  1089.  * Results:
  1090.  * The return value is one of the return codes defined in tcl.h
  1091.  * (such as TCL_OK), and interp's result contains a value
  1092.  * to supplement the return code. The value of the result
  1093.  * will persist only until the next call to Tcl_Eval or Tcl_EvalObj:
  1094.  * you must copy it or lose it!
  1095.  *
  1096.  * Side effects:
  1097.  * Can be almost arbitrary, depending on the commands in the script.
  1098.  *
  1099.  *----------------------------------------------------------------------
  1100.  */
  1101. int
  1102. Tcl_Eval(interp, string)
  1103.     Tcl_Interp *interp; /* Token for command interpreter (returned
  1104.  * by previous call to Tcl_CreateInterp). */
  1105.     CONST char *string; /* Pointer to TCL command to execute. */
  1106. {
  1107.     int code = Tcl_EvalEx(interp, string, -1, 0);
  1108.     /*
  1109.      * For backwards compatibility with old C code that predates the
  1110.      * object system in Tcl 8.0, we have to mirror the object result
  1111.      * back into the string result (some callers may expect it there).
  1112.      */
  1113.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  1114.     TCL_VOLATILE);
  1115.     return code;
  1116. }
  1117. /*
  1118.  *----------------------------------------------------------------------
  1119.  *
  1120.  * Tcl_EvalObj, Tcl_GlobalEvalObj --
  1121.  *
  1122.  * These functions are deprecated but we keep them around for backwards
  1123.  * compatibility reasons.
  1124.  *
  1125.  * Results:
  1126.  * See the functions they call.
  1127.  *
  1128.  * Side effects:
  1129.  * See the functions they call.
  1130.  *
  1131.  *----------------------------------------------------------------------
  1132.  */
  1133. #undef Tcl_EvalObj
  1134. int
  1135. Tcl_EvalObj(interp, objPtr)
  1136.     Tcl_Interp * interp;
  1137.     Tcl_Obj * objPtr;
  1138. {
  1139.     return Tcl_EvalObjEx(interp, objPtr, 0);
  1140. }
  1141. #undef Tcl_GlobalEvalObj
  1142. int
  1143. Tcl_GlobalEvalObj(interp, objPtr)
  1144.     Tcl_Interp * interp;
  1145.     Tcl_Obj * objPtr;
  1146. {
  1147.     return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
  1148. }
  1149. /*
  1150.  *----------------------------------------------------------------------
  1151.  *
  1152.  * Tcl_EvalObjEx, TclEvalObjEx --
  1153.  *
  1154.  * Execute Tcl commands stored in a Tcl object. These commands are
  1155.  * compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT
  1156.  * is specified.
  1157.  *
  1158.  * Results:
  1159.  * The return value is one of the return codes defined in tcl.h
  1160.  * (such as TCL_OK), and the interpreter's result contains a value
  1161.  * to supplement the return code.
  1162.  *
  1163.  * Side effects:
  1164.  * The object is converted, if necessary, to a ByteCode object that
  1165.  * holds the bytecode instructions for the commands. Executing the
  1166.  * commands will almost certainly have side effects that depend
  1167.  * on those commands.
  1168.  *
  1169.  * Just as in Tcl_Eval, interp->termOffset is set to the offset of the
  1170.  * last character executed in the objPtr's string.
  1171.  *
  1172.  * TIP #280 : Keep public API, internally extended API.
  1173.  *----------------------------------------------------------------------
  1174.  */
  1175. int
  1176. Tcl_EvalObjEx(interp, objPtr, flags)
  1177.     Tcl_Interp *interp; /* Token for command interpreter
  1178.  * (returned by a previous call to
  1179.  * Tcl_CreateInterp). */
  1180.     register Tcl_Obj *objPtr; /* Pointer to object containing
  1181.  * commands to execute. */
  1182.     int flags; /* Collection of OR-ed bits that
  1183.  * control the evaluation of the
  1184.  * script.  Supported values are
  1185.  * TCL_EVAL_GLOBAL and
  1186.  * TCL_EVAL_DIRECT. */
  1187. {
  1188. #ifdef TCL_TIP280
  1189.   return TclEvalObjEx (interp, objPtr, flags, NULL, 0);
  1190. }
  1191. int
  1192. TclEvalObjEx(interp, objPtr, flags, invoker, word)
  1193.     Tcl_Interp *interp; /* Token for command interpreter
  1194.  * (returned by a previous call to
  1195.  * Tcl_CreateInterp). */
  1196.     register Tcl_Obj *objPtr; /* Pointer to object containing
  1197.  * commands to execute. */
  1198.     int flags; /* Collection of OR-ed bits that
  1199.  * control the evaluation of the
  1200.  * script.  Supported values are
  1201.  * TCL_EVAL_GLOBAL and
  1202.  * TCL_EVAL_DIRECT. */
  1203.     CONST CmdFrame* invoker; /* Frame of the command doing the eval  */
  1204.     int             word;    /* Index of the word which is in objPtr */
  1205. {
  1206. #endif
  1207.     register Interp *iPtr = (Interp *) interp;
  1208.     char *script;
  1209.     int numSrcBytes;
  1210.     int result;
  1211.     CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
  1212.  * in case TCL_EVAL_GLOBAL was set. */
  1213.     int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
  1214.     Tcl_IncrRefCount(objPtr);
  1215.     if ((iPtr->flags & USE_EVAL_DIRECT) || (flags & TCL_EVAL_DIRECT)) {
  1216. /*
  1217.  * We're not supposed to use the compiler or byte-code interpreter.
  1218.  * Let Tcl_EvalEx evaluate the command directly (and probably
  1219.  * more slowly).
  1220.  *
  1221.  * Pure List Optimization (no string representation).  In this
  1222.  * case, we can safely use Tcl_EvalObjv instead and get an
  1223.  * appreciable improvement in execution speed.  This is because it
  1224.  * allows us to avoid a setFromAny step that would just pack
  1225.  * everything into a string and back out again.
  1226.  *
  1227.  * USE_EVAL_DIRECT is a special flag used for testing purpose only
  1228.  * (ensure we go into the TCL_EVAL_DIRECT path, avoiding opt)
  1229.  */
  1230. if (!(iPtr->flags & USE_EVAL_DIRECT) &&
  1231. (objPtr->typePtr == &tclListType) && /* is a list... */
  1232. (objPtr->bytes == NULL) /* ...without a string rep */) {
  1233.     register List *listRepPtr =
  1234. (List *) objPtr->internalRep.twoPtrValue.ptr1;
  1235.     int i, objc = listRepPtr->elemCount;
  1236. #define TEOE_PREALLOC 10
  1237.     Tcl_Obj *staticObjv[TEOE_PREALLOC], **objv = staticObjv;
  1238. #ifdef TCL_TIP280
  1239.     /* TIP #280 Structures for tracking lines.
  1240.      * As we know that this is dynamic execution we ignore the
  1241.      * invoker, even if known.
  1242.      */
  1243.     int      line;
  1244.     CmdFrame eoFrame;
  1245.     eoFrame.type     = TCL_LOCATION_EVAL_LIST;
  1246.     eoFrame.level    = (iPtr->cmdFramePtr == NULL ?
  1247. 1 :
  1248. iPtr->cmdFramePtr->level + 1);
  1249.     eoFrame.framePtr = iPtr->framePtr;
  1250.     eoFrame.nextPtr  = iPtr->cmdFramePtr;
  1251.     eoFrame.nline    = objc;
  1252.     eoFrame.line     = (int*) ckalloc (objc * sizeof (int));
  1253.     /* NOTE: Getting the string rep of the list to eval to fill the
  1254.      * command information required by 'info frame' implies that
  1255.      * further calls for the same list would not be optimized, as it
  1256.      * would not be 'pure' anymore. It would also be a waste of time
  1257.      * as most of the time this information is not needed at all. What
  1258.      * we do instead is to keep the list obj itself around and have
  1259.      * 'info frame' sort it out.
  1260.      */
  1261.     eoFrame.cmd.listPtr  = objPtr;
  1262.     Tcl_IncrRefCount (eoFrame.cmd.listPtr);
  1263.     eoFrame.data.eval.path = NULL;
  1264. #endif
  1265.     if (objc > TEOE_PREALLOC) {
  1266. objv = (Tcl_Obj **) ckalloc(objc*sizeof(Tcl_Obj *));
  1267.     }
  1268. #undef TEOE_PREALLOC
  1269.     /*
  1270.      * Copy the list elements here, to avoid a segfault if
  1271.      * objPtr loses its List internal rep [Bug 1119369].
  1272.      *
  1273.      * TIP #280 Computes all the line numbers for the
  1274.      * words in the command.
  1275.      */
  1276. #ifdef TCL_TIP280
  1277.     line = 1;
  1278. #endif
  1279.     for (i=0; i < objc; i++) {
  1280. objv[i] = listRepPtr->elements[i];
  1281. Tcl_IncrRefCount(objv[i]);
  1282. #ifdef TCL_TIP280
  1283. eoFrame.line [i] = line;
  1284. {
  1285.     char* w = Tcl_GetString (objv [i]);
  1286.     TclAdvanceLines (&line, w, w+ strlen(w));
  1287. }
  1288. #endif
  1289.     }
  1290. #ifdef TCL_TIP280
  1291.     iPtr->cmdFramePtr = &eoFrame;
  1292. #endif
  1293.     result = Tcl_EvalObjv(interp, objc, objv, flags);
  1294. #ifdef TCL_TIP280
  1295.     iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
  1296.     Tcl_DecrRefCount (eoFrame.cmd.listPtr);
  1297. #endif
  1298.     for (i=0; i < objc; i++) {
  1299. TclDecrRefCount(objv[i]);
  1300.     }
  1301.     if (objv != staticObjv) {
  1302. ckfree((char *) objv);
  1303.     }
  1304. #ifdef TCL_TIP280
  1305.     ckfree ((char*) eoFrame.line);
  1306.     eoFrame.line  = NULL;
  1307.     eoFrame.nline = 0;
  1308. #endif
  1309. } else {
  1310. #ifndef TCL_TIP280
  1311.     script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
  1312.     result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
  1313. #else
  1314.     /*
  1315.      * TIP #280. Propagate context as much as we can. Especially if
  1316.      * the script to evaluate is a single literal it makes sense to
  1317.      * look if our context is one with absolute line numbers we can
  1318.      * then track into the literal itself too.
  1319.      *
  1320.      * See also tclCompile.c, TclInitCompileEnv, for the equivalent
  1321.      * code in the bytecode compiler.
  1322.      */
  1323.     if (invoker == NULL) {
  1324.         /* No context, force opening of our own */
  1325.         script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
  1326. result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
  1327.     } else {
  1328. /* We have an invoker, describing the command asking for the
  1329.  * evaluation of a subordinate script. This script may
  1330.  * originate in a literal word, or from a variable, etc. Using
  1331.  * the line array we now check if we have good line
  1332.  * information for the relevant word. The type of context is
  1333.  * relevant as well. In a non-'source' context we don't have
  1334.  * to try tracking lines.
  1335.  *
  1336.  * First see if the word exists and is a literal. If not we go
  1337.  * through the easy dynamic branch. No need to perform more
  1338.  * complex invokations.
  1339.  */
  1340. if ((invoker->nline <= word) || (invoker->line[word] < 0)) {
  1341.     /* Dynamic script, or dynamic context, force our own
  1342.      * context */
  1343.     script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
  1344.     result = Tcl_EvalEx(interp, script,    numSrcBytes, flags);
  1345. } else {
  1346.     /*  Try to get an absolute context for the evaluation
  1347.      */
  1348.     CmdFrame ctx = *invoker;
  1349.     int pc       = 0;
  1350.     if (invoker->type == TCL_LOCATION_BC) {
  1351. /* Note: Type BC => ctx.data.eval.path    is not used.
  1352.  *                  ctx.data.tebc.codePtr is used instead.
  1353.  */
  1354. TclGetSrcInfoForPc (&ctx);
  1355. pc = 1;
  1356.     }
  1357.     if (ctx.type == TCL_LOCATION_SOURCE) {
  1358. /* Absolute context to reuse. */
  1359. iPtr->invokeCmdFramePtr = &ctx;
  1360. iPtr->evalFlags |= TCL_EVAL_CTX;
  1361. script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
  1362. result = EvalEx(interp, script, numSrcBytes, flags, ctx.line [word]);
  1363. if (pc) {
  1364.     /* Death of SrcInfo reference */
  1365.     Tcl_DecrRefCount (ctx.data.eval.path);
  1366. }
  1367.     } else {
  1368. /* Dynamic context or script, easier to make our own as
  1369.  * well */
  1370. script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
  1371. result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
  1372.     }
  1373. }
  1374.     }
  1375. #endif
  1376. }
  1377.     } else {
  1378. /*
  1379.  * Let the compiler/engine subsystem do the evaluation.
  1380.  *
  1381.  * TIP #280 The invoker provides us with the context for the
  1382.  * script. We transfer this to the byte code compiler.
  1383.  */
  1384. savedVarFramePtr = iPtr->varFramePtr;
  1385. if (flags & TCL_EVAL_GLOBAL) {
  1386.     iPtr->varFramePtr = NULL;
  1387. }
  1388. #ifndef TCL_TIP280
  1389. result = TclCompEvalObj(interp, objPtr);
  1390. #else
  1391. result = TclCompEvalObj(interp, objPtr, invoker, word);
  1392. #endif
  1393. /*
  1394.  * If we are again at the top level, process any unusual 
  1395.  * return code returned by the evaluated code. 
  1396.  */
  1397. if (iPtr->numLevels == 0) {
  1398.     if (result == TCL_RETURN) {
  1399. result = TclUpdateReturnInfo(iPtr);
  1400.     }
  1401.     if ((result != TCL_OK) && (result != TCL_ERROR) 
  1402.         && !allowExceptions) {
  1403. ProcessUnexpectedResult(interp, result);
  1404. result = TCL_ERROR;
  1405. /*
  1406.  * If an error was created here, record information about 
  1407.  * what was being executed when the error occurred. Remove
  1408.  * the extra n added by tclMain.c in the command sent to
  1409.  * Tcl_LogCommandInfo [Bug 833150].
  1410.  */
  1411. if (!(iPtr->flags & ERR_ALREADY_LOGGED)) {
  1412.     script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
  1413.     Tcl_LogCommandInfo(interp, script, script, --numSrcBytes);
  1414.     iPtr->flags &= ~ERR_ALREADY_LOGGED;
  1415. }
  1416.     }
  1417. }
  1418. iPtr->evalFlags = 0;
  1419. iPtr->varFramePtr = savedVarFramePtr; 
  1420.     }
  1421.     TclDecrRefCount(objPtr);
  1422.     return result;
  1423. }
  1424. /*
  1425.  *----------------------------------------------------------------------
  1426.  *
  1427.  * ProcessUnexpectedResult --
  1428.  *
  1429.  * Procedure called by Tcl_EvalObj to set the interpreter's result
  1430.  * value to an appropriate error message when the code it evaluates
  1431.  * returns an unexpected result code (not TCL_OK and not TCL_ERROR) to
  1432.  * the topmost evaluation level.
  1433.  *
  1434.  * Results:
  1435.  * None.
  1436.  *
  1437.  * Side effects:
  1438.  * The interpreter result is set to an error message appropriate to
  1439.  * the result code.
  1440.  *
  1441.  *----------------------------------------------------------------------
  1442.  */
  1443. static void
  1444. ProcessUnexpectedResult(interp, returnCode)
  1445.     Tcl_Interp *interp; /* The interpreter in which the unexpected
  1446.  * result code was returned. */
  1447.     int returnCode; /* The unexpected result code. */
  1448. {
  1449.     Tcl_ResetResult(interp);
  1450.     if (returnCode == TCL_BREAK) {
  1451. Tcl_AppendToObj(Tcl_GetObjResult(interp),
  1452.         "invoked "break" outside of a loop", -1);
  1453.     } else if (returnCode == TCL_CONTINUE) {
  1454. Tcl_AppendToObj(Tcl_GetObjResult(interp),
  1455. "invoked "continue" outside of a loop", -1);
  1456.     } else {
  1457.         char buf[30 + TCL_INTEGER_SPACE];
  1458. sprintf(buf, "command returned bad code: %d", returnCode);
  1459. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1460.     }
  1461. }
  1462. /*
  1463.  *---------------------------------------------------------------------------
  1464.  *
  1465.  * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
  1466.  *
  1467.  * Procedures to evaluate an expression and return its value in a
  1468.  * particular form.
  1469.  *
  1470.  * Results:
  1471.  * Each of the procedures below returns a standard Tcl result. If an
  1472.  * error occurs then an error message is left in the interp's result.
  1473.  * Otherwise the value of the expression, in the appropriate form,
  1474.  * is stored at *ptr. If the expression had a result that was
  1475.  * incompatible with the desired form then an error is returned.
  1476.  *
  1477.  * Side effects:
  1478.  * None.
  1479.  *
  1480.  *---------------------------------------------------------------------------
  1481.  */
  1482. int
  1483. Tcl_ExprLong(interp, string, ptr)
  1484.     Tcl_Interp *interp; /* Context in which to evaluate the
  1485.  * expression. */
  1486.     CONST char *string; /* Expression to evaluate. */
  1487.     long *ptr; /* Where to store result. */
  1488. {
  1489.     register Tcl_Obj *exprPtr;
  1490.     Tcl_Obj *resultPtr;
  1491.     int length = strlen(string);
  1492.     int result = TCL_OK;
  1493.     if (length > 0) {
  1494. exprPtr = Tcl_NewStringObj(string, length);
  1495. Tcl_IncrRefCount(exprPtr);
  1496. result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
  1497. if (result == TCL_OK) {
  1498.     /*
  1499.      * Store an integer based on the expression result.
  1500.      */
  1501.     if (resultPtr->typePtr == &tclIntType) {
  1502. *ptr = resultPtr->internalRep.longValue;
  1503.     } else if (resultPtr->typePtr == &tclDoubleType) {
  1504. *ptr = (long) resultPtr->internalRep.doubleValue;
  1505.     } else if (resultPtr->typePtr == &tclWideIntType) {
  1506. #ifndef TCL_WIDE_INT_IS_LONG
  1507. /*
  1508.  * See Tcl_GetIntFromObj for conversion comments.
  1509.  */
  1510. Tcl_WideInt w = resultPtr->internalRep.wideValue;
  1511. if ((w >= -(Tcl_WideInt)(ULONG_MAX))
  1512. && (w <= (Tcl_WideInt)(ULONG_MAX))) {
  1513.     *ptr = Tcl_WideAsLong(w);
  1514. } else {
  1515.     Tcl_SetResult(interp,
  1516.     "integer value too large to represent as non-long integer",
  1517.     TCL_STATIC);
  1518.     result = TCL_ERROR;
  1519. }
  1520. #else
  1521. *ptr = resultPtr->internalRep.longValue;
  1522. #endif
  1523.     } else {
  1524. Tcl_SetResult(interp,
  1525.         "expression didn't have numeric value", TCL_STATIC);
  1526. result = TCL_ERROR;
  1527.     }
  1528.     Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  1529. } else {
  1530.     /*
  1531.      * Move the interpreter's object result to the string result, 
  1532.      * then reset the object result.
  1533.      */
  1534.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  1535.             TCL_VOLATILE);
  1536. }
  1537. Tcl_DecrRefCount(exprPtr);  /* discard the expression object */
  1538.     } else {
  1539. /*
  1540.  * An empty string. Just set the result integer to 0.
  1541.  */
  1542. *ptr = 0;
  1543.     }
  1544.     return result;
  1545. }
  1546. int
  1547. Tcl_ExprDouble(interp, string, ptr)
  1548.     Tcl_Interp *interp; /* Context in which to evaluate the
  1549.  * expression. */
  1550.     CONST char *string; /* Expression to evaluate. */
  1551.     double *ptr; /* Where to store result. */
  1552. {
  1553.     register Tcl_Obj *exprPtr;
  1554.     Tcl_Obj *resultPtr;
  1555.     int length = strlen(string);
  1556.     int result = TCL_OK;
  1557.     if (length > 0) {
  1558. exprPtr = Tcl_NewStringObj(string, length);
  1559. Tcl_IncrRefCount(exprPtr);
  1560. result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
  1561. if (result == TCL_OK) {
  1562.     /*
  1563.      * Store a double  based on the expression result.
  1564.      */
  1565.     if (resultPtr->typePtr == &tclIntType) {
  1566. *ptr = (double) resultPtr->internalRep.longValue;
  1567.     } else if (resultPtr->typePtr == &tclDoubleType) {
  1568. *ptr = resultPtr->internalRep.doubleValue;
  1569.     } else if (resultPtr->typePtr == &tclWideIntType) {
  1570. #ifndef TCL_WIDE_INT_IS_LONG
  1571. /*
  1572.  * See Tcl_GetIntFromObj for conversion comments.
  1573.  */
  1574. Tcl_WideInt w = resultPtr->internalRep.wideValue;
  1575. if ((w >= -(Tcl_WideInt)(ULONG_MAX))
  1576. && (w <= (Tcl_WideInt)(ULONG_MAX))) {
  1577.     *ptr = (double) Tcl_WideAsLong(w);
  1578. } else {
  1579.     Tcl_SetResult(interp,
  1580.     "integer value too large to represent as non-long integer",
  1581.     TCL_STATIC);
  1582.     result = TCL_ERROR;
  1583. }
  1584. #else
  1585. *ptr = (double) resultPtr->internalRep.longValue;
  1586. #endif
  1587.     } else {
  1588. Tcl_SetResult(interp,
  1589.         "expression didn't have numeric value", TCL_STATIC);
  1590. result = TCL_ERROR;
  1591.     }
  1592.     Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  1593. } else {
  1594.     /*
  1595.      * Move the interpreter's object result to the string result, 
  1596.      * then reset the object result.
  1597.      */
  1598.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  1599.             TCL_VOLATILE);
  1600. }
  1601. Tcl_DecrRefCount(exprPtr);  /* discard the expression object */
  1602.     } else {
  1603. /*
  1604.  * An empty string. Just set the result double to 0.0.
  1605.  */
  1606. *ptr = 0.0;
  1607.     }
  1608.     return result;
  1609. }
  1610. int
  1611. Tcl_ExprBoolean(interp, string, ptr)
  1612.     Tcl_Interp *interp; /* Context in which to evaluate the
  1613.          * expression. */
  1614.     CONST char *string; /* Expression to evaluate. */
  1615.     int *ptr; /* Where to store 0/1 result. */
  1616. {
  1617.     register Tcl_Obj *exprPtr;
  1618.     Tcl_Obj *resultPtr;
  1619.     int length = strlen(string);
  1620.     int result = TCL_OK;
  1621.     if (length > 0) {
  1622. exprPtr = Tcl_NewStringObj(string, length);
  1623. Tcl_IncrRefCount(exprPtr);
  1624. result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
  1625. if (result == TCL_OK) {
  1626.     /*
  1627.      * Store a boolean based on the expression result.
  1628.      */
  1629.     if (resultPtr->typePtr == &tclIntType) {
  1630. *ptr = (resultPtr->internalRep.longValue != 0);
  1631.     } else if (resultPtr->typePtr == &tclDoubleType) {
  1632. *ptr = (resultPtr->internalRep.doubleValue != 0.0);
  1633.     } else if (resultPtr->typePtr == &tclWideIntType) {
  1634. #ifndef TCL_WIDE_INT_IS_LONG
  1635. *ptr = (resultPtr->internalRep.wideValue != 0);
  1636. #else
  1637. *ptr = (resultPtr->internalRep.longValue != 0);
  1638. #endif
  1639.     } else {
  1640. result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
  1641.     }
  1642.     Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  1643. }
  1644. if (result != TCL_OK) {
  1645.     /*
  1646.      * Move the interpreter's object result to the string result, 
  1647.      * then reset the object result.
  1648.      */
  1649.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  1650.             TCL_VOLATILE);
  1651. }
  1652. Tcl_DecrRefCount(exprPtr); /* discard the expression object */
  1653.     } else {
  1654. /*
  1655.  * An empty string. Just set the result boolean to 0 (false).
  1656.  */
  1657. *ptr = 0;
  1658.     }
  1659.     return result;
  1660. }
  1661. /*
  1662.  *--------------------------------------------------------------
  1663.  *
  1664.  * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
  1665.  *
  1666.  * Procedures to evaluate an expression in an object and return its
  1667.  * value in a particular form.
  1668.  *
  1669.  * Results:
  1670.  * Each of the procedures below returns a standard Tcl result
  1671.  * object. If an error occurs then an error message is left in the
  1672.  * interpreter's result. Otherwise the value of the expression, in the
  1673.  * appropriate form, is stored at *ptr. If the expression had a result
  1674.  * that was incompatible with the desired form then an error is
  1675.  * returned.
  1676.  *
  1677.  * Side effects:
  1678.  * None.
  1679.  *
  1680.  *--------------------------------------------------------------
  1681.  */
  1682. int
  1683. Tcl_ExprLongObj(interp, objPtr, ptr)
  1684.     Tcl_Interp *interp; /* Context in which to evaluate the
  1685.  * expression. */
  1686.     register Tcl_Obj *objPtr; /* Expression to evaluate. */
  1687.     long *ptr; /* Where to store long result. */
  1688. {
  1689.     Tcl_Obj *resultPtr;
  1690.     int result;
  1691.     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
  1692.     if (result == TCL_OK) {
  1693. if (resultPtr->typePtr == &tclIntType) {
  1694.     *ptr = resultPtr->internalRep.longValue;
  1695. } else if (resultPtr->typePtr == &tclDoubleType) {
  1696.     *ptr = (long) resultPtr->internalRep.doubleValue;
  1697. } else {
  1698.     result = Tcl_GetLongFromObj(interp, resultPtr, ptr);
  1699.     if (result != TCL_OK) {
  1700. return result;
  1701.     }
  1702. }
  1703. Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  1704.     }
  1705.     return result;
  1706. }
  1707. int
  1708. Tcl_ExprDoubleObj(interp, objPtr, ptr)
  1709.     Tcl_Interp *interp; /* Context in which to evaluate the
  1710.  * expression. */
  1711.     register Tcl_Obj *objPtr; /* Expression to evaluate. */
  1712.     double *ptr; /* Where to store double result. */
  1713. {
  1714.     Tcl_Obj *resultPtr;
  1715.     int result;
  1716.     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
  1717.     if (result == TCL_OK) {
  1718. if (resultPtr->typePtr == &tclIntType) {
  1719.     *ptr = (double) resultPtr->internalRep.longValue;
  1720. } else if (resultPtr->typePtr == &tclDoubleType) {
  1721.     *ptr = resultPtr->internalRep.doubleValue;
  1722. } else {
  1723.     result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
  1724.     if (result != TCL_OK) {
  1725. return result;
  1726.     }
  1727. }
  1728. Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  1729.     }
  1730.     return result;
  1731. }
  1732. int
  1733. Tcl_ExprBooleanObj(interp, objPtr, ptr)
  1734.     Tcl_Interp *interp; /* Context in which to evaluate the
  1735.  * expression. */
  1736.     register Tcl_Obj *objPtr; /* Expression to evaluate. */
  1737.     int *ptr; /* Where to store 0/1 result. */
  1738. {
  1739.     Tcl_Obj *resultPtr;
  1740.     int result;
  1741.     result = Tcl_ExprObj(interp, objPtr, &resultPtr);
  1742.     if (result == TCL_OK) {
  1743. if (resultPtr->typePtr == &tclIntType) {
  1744.     *ptr = (resultPtr->internalRep.longValue != 0);
  1745. } else if (resultPtr->typePtr == &tclDoubleType) {
  1746.     *ptr = (resultPtr->internalRep.doubleValue != 0.0);
  1747. } else {
  1748.     result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
  1749. }
  1750. Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  1751.     }
  1752.     return result;
  1753. }
  1754. /*
  1755.  *----------------------------------------------------------------------
  1756.  *
  1757.  * TclInvoke --
  1758.  *
  1759.  * Invokes a Tcl command, given an argv/argc, from either the
  1760.  * exposed or the hidden sets of commands in the given interpreter.
  1761.  * NOTE: The command is invoked in the current stack frame of
  1762.  * the interpreter, thus it can modify local variables.
  1763.  *
  1764.  * Results:
  1765.  * A standard Tcl result.
  1766.  *
  1767.  * Side effects:
  1768.  * Whatever the command does.
  1769.  *
  1770.  *----------------------------------------------------------------------
  1771.  */
  1772. int
  1773. TclInvoke(interp, argc, argv, flags)
  1774.     Tcl_Interp *interp; /* Where to invoke the command. */
  1775.     int argc; /* Count of args. */
  1776.     register CONST char **argv; /* The arg strings; argv[0] is the name of
  1777.                                  * the command to invoke. */
  1778.     int flags; /* Combination of flags controlling the
  1779.  * call: TCL_INVOKE_HIDDEN and
  1780.  * TCL_INVOKE_NO_UNKNOWN. */
  1781. {
  1782.     register Tcl_Obj *objPtr;
  1783.     register int i;
  1784.     int length, result;
  1785.     /*
  1786.      * This procedure generates an objv array for object arguments that hold
  1787.      * the argv strings. It starts out with stack-allocated space but uses
  1788.      * dynamically-allocated storage if needed.
  1789.      */
  1790. #define NUM_ARGS 20
  1791.     Tcl_Obj *(objStorage[NUM_ARGS]);
  1792.     register Tcl_Obj **objv = objStorage;
  1793.     /*
  1794.      * Create the object argument array "objv". Make sure objv is large
  1795.      * enough to hold the objc arguments plus 1 extra for the zero
  1796.      * end-of-objv word.
  1797.      */
  1798.     if ((argc + 1) > NUM_ARGS) {
  1799. objv = (Tcl_Obj **)
  1800.     ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
  1801.     }
  1802.     for (i = 0;  i < argc;  i++) {
  1803. length = strlen(argv[i]);
  1804. objv[i] = Tcl_NewStringObj(argv[i], length);
  1805. Tcl_IncrRefCount(objv[i]);
  1806.     }
  1807.     objv[argc] = 0;
  1808.     /*
  1809.      * Use TclObjInterpProc to actually invoke the command.
  1810.      */
  1811.     result = TclObjInvoke(interp, argc, objv, flags);
  1812.     /*
  1813.      * Move the interpreter's object result to the string result, 
  1814.      * then reset the object result.
  1815.      */
  1816.     
  1817.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  1818.     TCL_VOLATILE);
  1819.     /*
  1820.      * Decrement the ref counts on the objv elements since we are done
  1821.      * with them.
  1822.      */
  1823.     for (i = 0;  i < argc;  i++) {
  1824. objPtr = objv[i];
  1825. Tcl_DecrRefCount(objPtr);
  1826.     }
  1827.     
  1828.     /*
  1829.      * Free the objv array if malloc'ed storage was used.
  1830.      */
  1831.     if (objv != objStorage) {
  1832. ckfree((char *) objv);
  1833.     }
  1834.     return result;
  1835. #undef NUM_ARGS
  1836. }
  1837. /*
  1838.  *----------------------------------------------------------------------
  1839.  *
  1840.  * TclGlobalInvoke --
  1841.  *
  1842.  * Invokes a Tcl command, given an argv/argc, from either the
  1843.  * exposed or hidden sets of commands in the given interpreter.
  1844.  * NOTE: The command is invoked in the global stack frame of
  1845.  * the interpreter, thus it cannot see any current state on
  1846.  * the stack for that interpreter.
  1847.  *
  1848.  * Results:
  1849.  * A standard Tcl result.
  1850.  *
  1851.  * Side effects:
  1852.  * Whatever the command does.
  1853.  *
  1854.  *----------------------------------------------------------------------
  1855.  */
  1856. int
  1857. TclGlobalInvoke(interp, argc, argv, flags)
  1858.     Tcl_Interp *interp; /* Where to invoke the command. */
  1859.     int argc; /* Count of args. */
  1860.     register CONST char **argv; /* The arg strings; argv[0] is the name of
  1861.                                  * the command to invoke. */
  1862.     int flags; /* Combination of flags controlling the
  1863.  * call: TCL_INVOKE_HIDDEN and
  1864.  * TCL_INVOKE_NO_UNKNOWN. */
  1865. {
  1866.     register Interp *iPtr = (Interp *) interp;
  1867.     int result;
  1868.     CallFrame *savedVarFramePtr;
  1869.     savedVarFramePtr = iPtr->varFramePtr;
  1870.     iPtr->varFramePtr = NULL;
  1871.     result = TclInvoke(interp, argc, argv, flags);
  1872.     iPtr->varFramePtr = savedVarFramePtr;
  1873.     return result;
  1874. }
  1875. /*
  1876.  *----------------------------------------------------------------------
  1877.  *
  1878.  * TclObjInvokeGlobal --
  1879.  *
  1880.  * Object version: Invokes a Tcl command, given an objv/objc, from
  1881.  * either the exposed or hidden set of commands in the given
  1882.  * interpreter.
  1883.  * NOTE: The command is invoked in the global stack frame of the
  1884.  * interpreter, thus it cannot see any current state on the
  1885.  * stack of that interpreter.
  1886.  *
  1887.  * Results:
  1888.  * A standard Tcl result.
  1889.  *
  1890.  * Side effects:
  1891.  * Whatever the command does.
  1892.  *
  1893.  *----------------------------------------------------------------------
  1894.  */
  1895. int
  1896. TclObjInvokeGlobal(interp, objc, objv, flags)
  1897.     Tcl_Interp *interp; /* Interpreter in which command is to be
  1898.  * invoked. */
  1899.     int objc; /* Count of arguments. */
  1900.     Tcl_Obj *CONST objv[]; /* Argument objects; objv[0] points to the
  1901.  * name of the command to invoke. */
  1902.     int flags; /* Combination of flags controlling the
  1903.  * call: TCL_INVOKE_HIDDEN,
  1904.  * TCL_INVOKE_NO_UNKNOWN, or
  1905.  * TCL_INVOKE_NO_TRACEBACK. */
  1906. {
  1907.     register Interp *iPtr = (Interp *) interp;
  1908.     int result;
  1909.     CallFrame *savedVarFramePtr;
  1910.     savedVarFramePtr = iPtr->varFramePtr;
  1911.     iPtr->varFramePtr = NULL;
  1912.     result = TclObjInvoke(interp, objc, objv, flags);
  1913.     iPtr->varFramePtr = savedVarFramePtr;
  1914.     return result;
  1915. }
  1916. /*
  1917.  *----------------------------------------------------------------------
  1918.  *
  1919.  * TclObjInvoke --
  1920.  *
  1921.  * Invokes a Tcl command, given an objv/objc, from either the
  1922.  * exposed or the hidden sets of commands in the given interpreter.
  1923.  *
  1924.  * Results:
  1925.  * A standard Tcl object result.
  1926.  *
  1927.  * Side effects:
  1928.  * Whatever the command does.
  1929.  *
  1930.  *----------------------------------------------------------------------
  1931.  */
  1932. int
  1933. TclObjInvoke(interp, objc, objv, flags)
  1934.     Tcl_Interp *interp; /* Interpreter in which command is to be
  1935.  * invoked. */
  1936.     int objc; /* Count of arguments. */
  1937.     Tcl_Obj *CONST objv[]; /* Argument objects; objv[0] points to the
  1938.  * name of the command to invoke. */
  1939.     int flags; /* Combination of flags controlling the
  1940.  * call: TCL_INVOKE_HIDDEN,
  1941.  * TCL_INVOKE_NO_UNKNOWN, or
  1942.  * TCL_INVOKE_NO_TRACEBACK. */
  1943. {
  1944.     register Interp *iPtr = (Interp *) interp;
  1945.     Tcl_HashTable *hTblPtr; /* Table of hidden commands. */
  1946.     char *cmdName; /* Name of the command from objv[0]. */
  1947.     register Tcl_HashEntry *hPtr;
  1948.     Tcl_Command cmd;
  1949.     Command *cmdPtr;
  1950.     int localObjc; /* Used to invoke "unknown" if the */
  1951.     Tcl_Obj **localObjv = NULL; /* command is not found. */
  1952.     register int i;
  1953.     int result;
  1954.     if (interp == (Tcl_Interp *) NULL) {
  1955.         return TCL_ERROR;
  1956.     }
  1957.     if ((objc < 1) || (objv == (Tcl_Obj **) NULL)) {
  1958.         Tcl_AppendToObj(Tcl_GetObjResult(interp),
  1959.         "illegal argument vector", -1);
  1960.         return TCL_ERROR;
  1961.     }
  1962.     cmdName = Tcl_GetString(objv[0]);
  1963.     if (flags & TCL_INVOKE_HIDDEN) {
  1964.         /*
  1965.          * We never invoke "unknown" for hidden commands.
  1966.          */
  1967.         
  1968. hPtr = NULL;
  1969.         hTblPtr = ((Interp *) interp)->hiddenCmdTablePtr;
  1970.         if (hTblPtr != NULL) {
  1971.     hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
  1972. }
  1973. if (hPtr == NULL) {
  1974.     Tcl_ResetResult(interp);
  1975.     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1976.      "invalid hidden command name "", cmdName, """,
  1977.      (char *) NULL);
  1978.             return TCL_ERROR;
  1979.         }
  1980. cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
  1981.     } else {
  1982. cmdPtr = NULL;
  1983. cmd = Tcl_FindCommand(interp, cmdName,
  1984.         (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
  1985.         if (cmd != (Tcl_Command) NULL) {
  1986.     cmdPtr = (Command *) cmd;
  1987.         }
  1988. if (cmdPtr == NULL) {
  1989.             if (!(flags & TCL_INVOKE_NO_UNKNOWN)) {
  1990. cmd = Tcl_FindCommand(interp, "unknown",
  1991.                         (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
  1992. if (cmd != (Tcl_Command) NULL) {
  1993.             cmdPtr = (Command *) cmd;
  1994.                 }
  1995.                 if (cmdPtr != NULL) {
  1996.                     localObjc = (objc + 1);
  1997.                     localObjv = (Tcl_Obj **)
  1998. ckalloc((unsigned) (sizeof(Tcl_Obj *) * localObjc));
  1999.     localObjv[0] = Tcl_NewStringObj("unknown", -1);
  2000.     Tcl_IncrRefCount(localObjv[0]);
  2001.                     for (i = 0;  i < objc;  i++) {
  2002.                         localObjv[i+1] = objv[i];
  2003.                     }
  2004.                     objc = localObjc;
  2005.                     objv = localObjv;
  2006.                 }
  2007.             }
  2008.             /*
  2009.              * Check again if we found the command. If not, "unknown" is
  2010.              * not present and we cannot help, or the caller said not to
  2011.              * call "unknown" (they specified TCL_INVOKE_NO_UNKNOWN).
  2012.              */
  2013.             if (cmdPtr == NULL) {
  2014. Tcl_ResetResult(interp);
  2015. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  2016. "invalid command name "",  cmdName, """, 
  2017.  (char *) NULL);
  2018.                 return TCL_ERROR;
  2019.             }
  2020.         }
  2021.     }
  2022.     /*
  2023.      * Invoke the command procedure. First reset the interpreter's string
  2024.      * and object results to their default empty values since they could
  2025.      * have gotten changed by earlier invocations.
  2026.      */
  2027.     Tcl_ResetResult(interp);
  2028.     iPtr->cmdCount++;
  2029.     result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
  2030.     /*
  2031.      * If an error occurred, record information about what was being
  2032.      * executed when the error occurred.
  2033.      */
  2034.     if ((result == TCL_ERROR)
  2035.     && ((flags & TCL_INVOKE_NO_TRACEBACK) == 0)
  2036.     && ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
  2037. Tcl_Obj *msg;
  2038.         
  2039.         if (!(iPtr->flags & ERR_IN_PROGRESS)) {
  2040.             msg = Tcl_NewStringObj("n    while invokingn"", -1);
  2041.         } else {
  2042.             msg = Tcl_NewStringObj("n    invoked from withinn"", -1);
  2043.         }
  2044. Tcl_IncrRefCount(msg);
  2045.         for (i = 0;  i < objc;  i++) {
  2046.     CONST char *bytes;
  2047.     int length;
  2048.     Tcl_AppendObjToObj(msg, objv[i]);
  2049.     bytes = Tcl_GetStringFromObj(msg, &length);
  2050.     if (length > 100) {
  2051. /*
  2052.  * Back up truncation point so that we don't truncate
  2053.  * in the middle of a multi-byte character.
  2054.  */
  2055. length = 100;
  2056. while ( (bytes[length] & 0xC0) == 0x80 ) {
  2057.     length--;
  2058. }
  2059. Tcl_SetObjLength(msg, length);
  2060. Tcl_AppendToObj(msg, "...", -1);
  2061. break;
  2062.     }
  2063.     if (i != (objc - 1)) {
  2064. Tcl_AppendToObj(msg, " ", -1);
  2065.     }
  2066.         }
  2067. Tcl_AppendToObj(msg, """, -1);
  2068.         Tcl_AddObjErrorInfo(interp, Tcl_GetString(msg), -1);
  2069. Tcl_DecrRefCount(msg);
  2070. iPtr->flags &= ~ERR_ALREADY_LOGGED;
  2071.     }
  2072.     /*
  2073.      * Free any locally allocated storage used to call "unknown".
  2074.      */
  2075.     if (localObjv != (Tcl_Obj **) NULL) {
  2076. Tcl_DecrRefCount(localObjv[0]);
  2077.         ckfree((char *) localObjv);
  2078.     }
  2079.     return result;
  2080. }
  2081. /*
  2082.  *---------------------------------------------------------------------------
  2083.  *
  2084.  * Tcl_ExprString --
  2085.  *
  2086.  * Evaluate an expression in a string and return its value in string
  2087.  * form.
  2088.  *
  2089.  * Results:
  2090.  * A standard Tcl result. If the result is TCL_OK, then the interp's
  2091.  * result is set to the string value of the expression. If the result
  2092.  * is TCL_ERROR, then the interp's result contains an error message.
  2093.  *
  2094.  * Side effects:
  2095.  * A Tcl object is allocated to hold a copy of the expression string.
  2096.  * This expression object is passed to Tcl_ExprObj and then
  2097.  * deallocated.
  2098.  *
  2099.  *---------------------------------------------------------------------------
  2100.  */
  2101. int
  2102. Tcl_ExprString(interp, string)
  2103.     Tcl_Interp *interp; /* Context in which to evaluate the
  2104.  * expression. */
  2105.     CONST char *string; /* Expression to evaluate. */
  2106. {
  2107.     register Tcl_Obj *exprPtr;
  2108.     Tcl_Obj *resultPtr;
  2109.     int length = strlen(string);
  2110.     char buf[TCL_DOUBLE_SPACE];
  2111.     int result = TCL_OK;
  2112.     if (length > 0) {
  2113. TclNewObj(exprPtr);
  2114. TclInitStringRep(exprPtr, string, length);
  2115. Tcl_IncrRefCount(exprPtr);
  2116. result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
  2117. if (result == TCL_OK) {
  2118.     /*
  2119.      * Set the interpreter's string result from the result object.
  2120.      */
  2121.     
  2122.     if (resultPtr->typePtr == &tclIntType) {
  2123. sprintf(buf, "%ld", resultPtr->internalRep.longValue);
  2124. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2125.     } else if (resultPtr->typePtr == &tclDoubleType) {
  2126. Tcl_PrintDouble((Tcl_Interp *) NULL,
  2127.         resultPtr->internalRep.doubleValue, buf);
  2128. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2129.     } else {
  2130. /*
  2131.  * Set interpreter's string result from the result object.
  2132.  */
  2133.     
  2134. Tcl_SetResult(interp, TclGetString(resultPtr),
  2135.         TCL_VOLATILE);
  2136.     }
  2137.     Tcl_DecrRefCount(resultPtr);  /* discard the result object */
  2138. } else {
  2139.     /*
  2140.      * Move the interpreter's object result to the string result, 
  2141.      * then reset the object result.
  2142.      */
  2143.     
  2144.     Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  2145.             TCL_VOLATILE);
  2146. }
  2147. Tcl_DecrRefCount(exprPtr); /* discard the expression object */
  2148.     } else {
  2149. /*
  2150.  * An empty string. Just set the interpreter's result to 0.
  2151.  */
  2152. Tcl_SetResult(interp, "0", TCL_VOLATILE);
  2153.     }
  2154.     return result;
  2155. }
  2156. /*
  2157.  *----------------------------------------------------------------------
  2158.  *
  2159.  * Tcl_CreateObjTrace --
  2160.  *
  2161.  * Arrange for a procedure to be called to trace command execution.
  2162.  *
  2163.  * Results:
  2164.  * The return value is a token for the trace, which may be passed
  2165.  * to Tcl_DeleteTrace to eliminate the trace.
  2166.  *
  2167.  * Side effects:
  2168.  * From now on, proc will be called just before a command procedure
  2169.  * is called to execute a Tcl command.  Calls to proc will have the
  2170.  * following form:
  2171.  *
  2172.  *      void proc( ClientData     clientData,
  2173.  *                 Tcl_Interp*    interp,
  2174.  *                 int            level,
  2175.  *                 CONST char*    command,
  2176.  *                 Tcl_Command    commandInfo,
  2177.  *                 int            objc,
  2178.  *                 Tcl_Obj *CONST objv[] );
  2179.  *
  2180.  *      The 'clientData' and 'interp' arguments to 'proc' will be the
  2181.  *      same as the arguments to Tcl_CreateObjTrace.  The 'level'
  2182.  * argument gives the nesting depth of command interpretation within
  2183.  * the interpreter.  The 'command' argument is the ASCII text of
  2184.  * the command being evaluated -- before any substitutions are
  2185.  * performed.  The 'commandInfo' argument gives a handle to the
  2186.  * command procedure that will be evaluated.  The 'objc' and 'objv'
  2187.  * parameters give the parameter vector that will be passed to the
  2188.  * command procedure.  proc does not return a value.
  2189.  *
  2190.  *      It is permissible for 'proc' to call Tcl_SetCommandTokenInfo
  2191.  *      to change the command procedure or client data for the command
  2192.  *      being evaluated, and these changes will take effect with the
  2193.  *      current evaluation.
  2194.  *
  2195.  * The 'level' argument specifies the maximum nesting level of calls
  2196.  * to be traced.  If the execution depth of the interpreter exceeds
  2197.  * 'level', the trace callback is not executed.
  2198.  *
  2199.  * The 'flags' argument is either zero or the value,
  2200.  * TCL_ALLOW_INLINE_COMPILATION.  If the TCL_ALLOW_INLINE_COMPILATION
  2201.  * flag is not present, the bytecode compiler will not generate inline
  2202.  * code for Tcl's built-in commands.  This behavior will have a significant
  2203.  * impact on performance, but will ensure that all command evaluations are
  2204.  * traced.  If the TCL_ALLOW_INLINE_COMPILATION flag is present, the
  2205.  * bytecode compiler will have its normal behavior of compiling in-line
  2206.  * code for some of Tcl's built-in commands.  In this case, the tracing
  2207.  * will be imprecise -- in-line code will not be traced -- but run-time
  2208.  * performance will be improved.  The latter behavior is desired for
  2209.  * many applications such as profiling of run time.
  2210.  *
  2211.  * When the trace is deleted, the 'delProc' procedure will be invoked,
  2212.  * passing it the original client data.  
  2213.  *
  2214.  *----------------------------------------------------------------------
  2215.  */
  2216. Tcl_Trace
  2217. Tcl_CreateObjTrace( interp, level, flags, proc, clientData, delProc )
  2218.     Tcl_Interp* interp; /* Tcl interpreter */
  2219.     int level; /* Maximum nesting level */
  2220.     int flags; /* Flags, see above */
  2221.     Tcl_CmdObjTraceProc* proc; /* Trace callback */
  2222.     ClientData clientData; /* Client data for the callback */
  2223.     Tcl_CmdObjTraceDeleteProc* delProc;
  2224. /* Procedure to call when trace is deleted */
  2225. {
  2226.     register Trace *tracePtr;
  2227.     register Interp *iPtr = (Interp *) interp;
  2228.     /* Test if this trace allows inline compilation of commands */
  2229.     if (!(flags & TCL_ALLOW_INLINE_COMPILATION)) {
  2230. if (iPtr->tracesForbiddingInline == 0) {
  2231.     /*
  2232.      * When the first trace forbidding inline compilation is
  2233.      * created, invalidate existing compiled code for this
  2234.      * interpreter and arrange (by setting the
  2235.      * DONT_COMPILE_CMDS_INLINE flag) that when compiling new
  2236.      * code, no commands will be compiled inline (i.e., into
  2237.      * an inline sequence of instructions). We do this because
  2238.      * commands that were compiled inline will never result in
  2239.      * a command trace being called.
  2240.      */
  2241.     iPtr->compileEpoch++;
  2242.     iPtr->flags |= DONT_COMPILE_CMDS_INLINE;
  2243. }
  2244. iPtr->tracesForbiddingInline++;
  2245.     }
  2246.     
  2247.     tracePtr = (Trace *) ckalloc(sizeof(Trace));
  2248.     tracePtr->level = level;
  2249.     tracePtr->proc = proc;
  2250.     tracePtr->clientData = clientData;
  2251.     tracePtr->delProc           = delProc;
  2252.     tracePtr->nextPtr = iPtr->tracePtr;
  2253.     tracePtr->flags = flags;
  2254.     iPtr->tracePtr = tracePtr;
  2255.     return (Tcl_Trace) tracePtr;
  2256. }
  2257. /*
  2258.  *----------------------------------------------------------------------
  2259.  *
  2260.  * Tcl_CreateTrace --
  2261.  *
  2262.  * Arrange for a procedure to be called to trace command execution.
  2263.  *
  2264.  * Results:
  2265.  * The return value is a token for the trace, which may be passed
  2266.  * to Tcl_DeleteTrace to eliminate the trace.
  2267.  *
  2268.  * Side effects:
  2269.  * From now on, proc will be called just before a command procedure
  2270.  * is called to execute a Tcl command.  Calls to proc will have the
  2271.  * following form:
  2272.  *
  2273.  * void
  2274.  * proc(clientData, interp, level, command, cmdProc, cmdClientData,
  2275.  * argc, argv)
  2276.  *     ClientData clientData;
  2277.  *     Tcl_Interp *interp;
  2278.  *     int level;
  2279.  *     char *command;
  2280.  *     int (*cmdProc)();
  2281.  *     ClientData cmdClientData;
  2282.  *     int argc;
  2283.  *     char **argv;
  2284.  * {
  2285.  * }
  2286.  *
  2287.  * The clientData and interp arguments to proc will be the same
  2288.  * as the corresponding arguments to this procedure.  Level gives
  2289.  * the nesting level of command interpretation for this interpreter
  2290.  * (0 corresponds to top level).  Command gives the ASCII text of
  2291.  * the raw command, cmdProc and cmdClientData give the procedure that
  2292.  * will be called to process the command and the ClientData value it
  2293.  * will receive, and argc and argv give the arguments to the
  2294.  * command, after any argument parsing and substitution.  Proc
  2295.  * does not return a value.
  2296.  *
  2297.  *----------------------------------------------------------------------
  2298.  */
  2299. Tcl_Trace
  2300. Tcl_CreateTrace(interp, level, proc, clientData)
  2301.     Tcl_Interp *interp; /* Interpreter in which to create trace. */
  2302.     int level; /* Only call proc for commands at nesting
  2303.  * level<=argument level (1=>top level). */
  2304.     Tcl_CmdTraceProc *proc; /* Procedure to call before executing each
  2305.  * command. */
  2306.     ClientData clientData; /* Arbitrary value word to pass to proc. */
  2307. {
  2308.     StringTraceData* data;
  2309.     data = (StringTraceData*) ckalloc( sizeof( *data ));
  2310.     data->clientData = clientData;
  2311.     data->proc = proc;
  2312.     return Tcl_CreateObjTrace( interp, level, 0, StringTraceProc,
  2313.        (ClientData) data, StringTraceDeleteProc );
  2314. }
  2315. /*
  2316.  *----------------------------------------------------------------------
  2317.  *
  2318.  * StringTraceProc --
  2319.  *
  2320.  * Invoke a string-based trace procedure from an object-based
  2321.  * callback.
  2322.  *
  2323.  * Results:
  2324.  * None.
  2325.  *
  2326.  * Side effects:
  2327.  * Whatever the string-based trace procedure does.
  2328.  *
  2329.  *----------------------------------------------------------------------
  2330.  */
  2331. static int
  2332. StringTraceProc( clientData, interp, level, command, commandInfo, objc, objv )
  2333.     ClientData clientData;
  2334.     Tcl_Interp* interp;
  2335.     int level;
  2336.     CONST char* command;
  2337.     Tcl_Command commandInfo;
  2338.     int objc;
  2339.     Tcl_Obj *CONST *objv;
  2340. {
  2341.     StringTraceData* data = (StringTraceData*) clientData;
  2342.     Command* cmdPtr = (Command*) commandInfo;
  2343.     CONST char** argv; /* Args to pass to string trace proc */
  2344.     int i;
  2345.     /*
  2346.      * This is a bit messy because we have to emulate the old trace
  2347.      * interface, which uses strings for everything.
  2348.      */
  2349.     
  2350.     argv = (CONST char **) ckalloc((unsigned) ( (objc + 1)
  2351. * sizeof(CONST char *) ));
  2352.     for (i = 0; i < objc; i++) {
  2353. argv[i] = Tcl_GetString(objv[i]);
  2354.     }
  2355.     argv[objc] = 0;
  2356.     /*
  2357.      * Invoke the command procedure.  Note that we cast away const-ness
  2358.      * on two parameters for compatibility with legacy code; the code
  2359.      * MUST NOT modify either command or argv.
  2360.      */
  2361.           
  2362.     ( data->proc )( data->clientData, interp, level,
  2363.     (char*) command, cmdPtr->proc, cmdPtr->clientData,
  2364.     objc, argv );
  2365.     ckfree( (char*) argv );
  2366.     return TCL_OK;
  2367. }
  2368. /*
  2369.  *----------------------------------------------------------------------
  2370.  *
  2371.  * StringTraceDeleteProc --
  2372.  *
  2373.  * Clean up memory when a string-based trace is deleted.
  2374.  *
  2375.  * Results:
  2376.  * None.
  2377.  *
  2378.  * Side effects:
  2379.  * Allocated memory is returned to the system.
  2380.  *
  2381.  *----------------------------------------------------------------------
  2382.  */
  2383. static void
  2384. StringTraceDeleteProc( clientData )
  2385.     ClientData clientData;
  2386. {
  2387.     ckfree( (char*) clientData );
  2388. }
  2389. /*
  2390.  *----------------------------------------------------------------------
  2391.  *
  2392.  * Tcl_DeleteTrace --
  2393.  *
  2394.  * Remove a trace.
  2395.  *
  2396.  * Results:
  2397.  * None.
  2398.  *
  2399.  * Side effects:
  2400.  * From now on there will be no more calls to the procedure given
  2401.  * in trace.
  2402.  *
  2403.  *----------------------------------------------------------------------
  2404.  */
  2405. void
  2406. Tcl_DeleteTrace(interp, trace)
  2407.     Tcl_Interp *interp; /* Interpreter that contains trace. */
  2408.     Tcl_Trace trace; /* Token for trace (returned previously by
  2409.  * Tcl_CreateTrace). */
  2410. {
  2411.     Interp *iPtr = (Interp *) interp;
  2412.     Trace *prevPtr, *tracePtr = (Trace *) trace;
  2413.     register Trace **tracePtr2 = &(iPtr->tracePtr);
  2414.     ActiveInterpTrace *activePtr;
  2415.     /*
  2416.      * Locate the trace entry in the interpreter's trace list,
  2417.      * and remove it from the list.
  2418.      */
  2419.     prevPtr = NULL;
  2420.     while ((*tracePtr2) != NULL && (*tracePtr2) != tracePtr) {
  2421. prevPtr = *tracePtr2;
  2422. tracePtr2 = &((*tracePtr2)->nextPtr);
  2423.     }
  2424.     if (*tracePtr2 == NULL) {
  2425. return;
  2426.     }
  2427.     (*tracePtr2) = (*tracePtr2)->nextPtr;
  2428.     /*
  2429.      * The code below makes it possible to delete traces while traces
  2430.      * are active: it makes sure that the deleted trace won't be
  2431.      * processed by TclCheckInterpTraces.
  2432.      */
  2433.     for (activePtr = iPtr->activeInterpTracePtr;  activePtr != NULL;
  2434.     activePtr = activePtr->nextPtr) {
  2435. if (activePtr->nextTracePtr == tracePtr) {
  2436.     if (activePtr->reverseScan) {
  2437. activePtr->nextTracePtr = prevPtr;
  2438.     } else {
  2439. activePtr->nextTracePtr = tracePtr->nextPtr;
  2440.     }
  2441. }
  2442.     }
  2443.     /*
  2444.      * If the trace forbids bytecode compilation, change the interpreter's
  2445.      * state.  If bytecode compilation is now permitted, flag the fact and
  2446.      * advance the compilation epoch so that procs will be recompiled to
  2447.      * take advantage of it.
  2448.      */
  2449.     if (!(tracePtr->flags & TCL_ALLOW_INLINE_COMPILATION)) {
  2450. iPtr->tracesForbiddingInline--;
  2451. if (iPtr->tracesForbiddingInline == 0) {
  2452.     iPtr->flags &= ~DONT_COMPILE_CMDS_INLINE;
  2453.     iPtr->compileEpoch++;
  2454. }
  2455.     }
  2456.     /*
  2457.      * Execute any delete callback.
  2458.      */
  2459.     if (tracePtr->delProc != NULL) {
  2460. (tracePtr->delProc)(tracePtr->clientData);
  2461.     }
  2462.     /* Delete the trace object */
  2463.     Tcl_EventuallyFree((char*)tracePtr, TCL_DYNAMIC);
  2464. }
  2465. /*
  2466.  *----------------------------------------------------------------------
  2467.  *
  2468.  * Tcl_AddErrorInfo --
  2469.  *
  2470.  * Add information to the "errorInfo" variable that describes the
  2471.  * current error.
  2472.  *
  2473.  * Results:
  2474.  * None.
  2475.  *
  2476.  * Side effects:
  2477.  * The contents of message are added to the "errorInfo" variable.
  2478.  * If Tcl_Eval has been called since the current value of errorInfo
  2479.  * was set, errorInfo is cleared before adding the new message.
  2480.  * If we are just starting to log an error, errorInfo is initialized
  2481.  * from the error message in the interpreter's result.
  2482.  *
  2483.  *----------------------------------------------------------------------
  2484.  */
  2485. void
  2486. Tcl_AddErrorInfo(interp, message)
  2487.     Tcl_Interp *interp; /* Interpreter to which error information
  2488.  * pertains. */
  2489.     CONST char *message; /* Message to record. */
  2490. {
  2491.     Tcl_AddObjErrorInfo(interp, message, -1);
  2492. }
  2493. /*
  2494.  *----------------------------------------------------------------------
  2495.  *
  2496.  * Tcl_AddObjErrorInfo --
  2497.  *
  2498.  * Add information to the "errorInfo" variable that describes the
  2499.  * current error. This routine differs from Tcl_AddErrorInfo by
  2500.  * taking a byte pointer and length.
  2501.  *
  2502.  * Results:
  2503.  * None.
  2504.  *
  2505.  * Side effects:
  2506.  * "length" bytes from "message" are added to the "errorInfo" variable.
  2507.  * If "length" is negative, use bytes up to the first NULL byte.
  2508.  * If Tcl_EvalObj has been called since the current value of errorInfo
  2509.  * was set, errorInfo is cleared before adding the new message.
  2510.  * If we are just starting to log an error, errorInfo is initialized
  2511.  * from the error message in the interpreter's result.
  2512.  *
  2513.  *----------------------------------------------------------------------
  2514.  */
  2515. void
  2516. Tcl_AddObjErrorInfo(interp, message, length)
  2517.     Tcl_Interp *interp; /* Interpreter to which error information
  2518.  * pertains. */
  2519.     CONST char *message; /* Points to the first byte of an array of
  2520.  * bytes of the message. */
  2521.     int length; /* The number of bytes in the message.
  2522.  * If < 0, then append all bytes up to a
  2523.  * NULL byte. */
  2524. {
  2525.     register Interp *iPtr = (Interp *) interp;
  2526.     Tcl_Obj *objPtr;
  2527.     
  2528.     /*
  2529.      * If we are just starting to log an error, errorInfo is initialized
  2530.      * from the error message in the interpreter's result.
  2531.      */
  2532.     if (!(iPtr->flags & ERR_IN_PROGRESS)) { /* just starting to log error */
  2533. iPtr->flags |= ERR_IN_PROGRESS;
  2534. if (iPtr->result[0] == 0) {
  2535.     Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL, 
  2536.             iPtr->objResultPtr, TCL_GLOBAL_ONLY);
  2537. } else { /* use the string result */
  2538.     objPtr = Tcl_NewStringObj(interp->result, -1);
  2539.     Tcl_IncrRefCount(objPtr);
  2540.     Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL, 
  2541.             objPtr, TCL_GLOBAL_ONLY);
  2542.     Tcl_DecrRefCount(objPtr);
  2543. }
  2544. /*
  2545.  * If the errorCode variable wasn't set by the code that generated
  2546.  * the error, set it to "NONE".
  2547.  */
  2548. if (!(iPtr->flags & ERROR_CODE_SET)) {
  2549.     objPtr = Tcl_NewStringObj("NONE", -1);
  2550.     Tcl_IncrRefCount(objPtr);
  2551.     Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorCode, NULL, 
  2552.             objPtr, TCL_GLOBAL_ONLY);
  2553.     Tcl_DecrRefCount(objPtr);
  2554. }
  2555.     }
  2556.     /*
  2557.      * Now append "message" to the end of errorInfo.
  2558.      */
  2559.     if (length != 0) {
  2560. objPtr = Tcl_NewStringObj(message, length);
  2561. Tcl_IncrRefCount(objPtr);
  2562. Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL, 
  2563.         objPtr, (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE));
  2564. Tcl_DecrRefCount(objPtr); /* free msg object appended above */
  2565.     }
  2566. }
  2567. /*
  2568.  *---------------------------------------------------------------------------
  2569.  *
  2570.  * Tcl_VarEvalVA --
  2571.  *
  2572.  * Given a variable number of string arguments, concatenate them
  2573.  * all together and execute the result as a Tcl command.
  2574.  *
  2575.  * Results:
  2576.  * A standard Tcl return result.  An error message or other result may
  2577.  * be left in the interp's result.
  2578.  *
  2579.  * Side effects:
  2580.  * Depends on what was done by the command.
  2581.  *
  2582.  *---------------------------------------------------------------------------
  2583.  */
  2584. int
  2585. Tcl_VarEvalVA (interp, argList)
  2586.     Tcl_Interp *interp; /* Interpreter in which to evaluate command. */
  2587.     va_list argList; /* Variable argument list. */
  2588. {
  2589.     Tcl_DString buf;
  2590.     char *string;
  2591.     int result;
  2592.     /*
  2593.      * Copy the strings one after the other into a single larger
  2594.      * string.  Use stack-allocated space for small commands, but if
  2595.      * the command gets too large than call ckalloc to create the
  2596.      * space.
  2597.      */
  2598.     Tcl_DStringInit(&buf);
  2599.     while (1) {
  2600. string = va_arg(argList, char *);
  2601. if (string == NULL) {
  2602.     break;
  2603. }
  2604. Tcl_DStringAppend(&buf, string, -1);
  2605.     }
  2606.     result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
  2607.     Tcl_DStringFree(&buf);
  2608.     return result;
  2609. }
  2610. /*
  2611.  *----------------------------------------------------------------------
  2612.  *
  2613.  * Tcl_VarEval --
  2614.  *
  2615.  * Given a variable number of string arguments, concatenate them
  2616.  * all together and execute the result as a Tcl command.
  2617.  *
  2618.  * Results:
  2619.  * A standard Tcl return result.  An error message or other
  2620.  * result may be left in interp->result.
  2621.  *
  2622.  * Side effects:
  2623.  * Depends on what was done by the command.
  2624.  *
  2625.  *----------------------------------------------------------------------
  2626.  */
  2627. /* VARARGS2 */ /* ARGSUSED */
  2628. int
  2629. Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1)
  2630. {
  2631.     Tcl_Interp *interp;
  2632.     va_list argList;
  2633.     int result;
  2634.     interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
  2635.     result = Tcl_VarEvalVA(interp, argList);
  2636.     va_end(argList);
  2637.     return result;
  2638. }
  2639. /*
  2640.  *---------------------------------------------------------------------------
  2641.  *
  2642.  * Tcl_GlobalEval --
  2643.  *
  2644.  * Evaluate a command at global level in an interpreter.
  2645.  *
  2646.  * Results:
  2647.  * A standard Tcl result is returned, and the interp's result is
  2648.  * modified accordingly.
  2649.  *
  2650.  * Side effects:
  2651.  * The command string is executed in interp, and the execution
  2652.  * is carried out in the variable context of global level (no
  2653.  * procedures active), just as if an "uplevel #0" command were
  2654.  * being executed.
  2655.  *
  2656.  ---------------------------------------------------------------------------
  2657.  */
  2658. int
  2659. Tcl_GlobalEval(interp, command)
  2660.     Tcl_Interp *interp; /* Interpreter in which to evaluate command. */
  2661.     CONST char *command; /* Command to evaluate. */
  2662. {
  2663.     register Interp *iPtr = (Interp *) interp;
  2664.     int result;
  2665.     CallFrame *savedVarFramePtr;
  2666.     savedVarFramePtr = iPtr->varFramePtr;
  2667.     iPtr->varFramePtr = NULL;
  2668.     result = Tcl_Eval(interp, command);
  2669.     iPtr->varFramePtr = savedVarFramePtr;
  2670.     return result;
  2671. }
  2672. /*
  2673.  *----------------------------------------------------------------------
  2674.  *
  2675.  * Tcl_SetRecursionLimit --
  2676.  *
  2677.  * Set the maximum number of recursive calls that may be active
  2678.  * for an interpreter at once.
  2679.  *
  2680.  * Results:
  2681.  * The return value is the old limit on nesting for interp.
  2682.  *
  2683.  * Side effects:
  2684.  * None.
  2685.  *
  2686.  *----------------------------------------------------------------------
  2687.  */
  2688. int
  2689. Tcl_SetRecursionLimit(interp, depth)
  2690.     Tcl_Interp *interp; /* Interpreter whose nesting limit
  2691.  * is to be set. */
  2692.     int depth; /* New value for maximimum depth. */
  2693. {
  2694.     Interp *iPtr = (Interp *) interp;
  2695.     int old;
  2696.     old = iPtr->maxNestingDepth;
  2697.     if (depth > 0) {
  2698. iPtr->maxNestingDepth = depth;
  2699.     }
  2700.     return old;
  2701. }
  2702. /*
  2703.  *----------------------------------------------------------------------
  2704.  *
  2705.  * Tcl_AllowExceptions --
  2706.  *
  2707.  * Sets a flag in an interpreter so that exceptions can occur
  2708.  * in the next call to Tcl_Eval without them being turned into
  2709.  * errors.
  2710.  *
  2711.  * Results:
  2712.  * None.
  2713.  *
  2714.  * Side effects:
  2715.  * The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's
  2716.  * evalFlags structure.  See the reference documentation for
  2717.  * more details.
  2718.  *
  2719.  *----------------------------------------------------------------------
  2720.  */
  2721. void
  2722. Tcl_AllowExceptions(interp)
  2723.     Tcl_Interp *interp; /* Interpreter in which to set flag. */
  2724. {
  2725.     Interp *iPtr = (Interp *) interp;
  2726.     iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS;
  2727. }
  2728. /*
  2729.  *----------------------------------------------------------------------
  2730.  *
  2731.  * Tcl_GetVersion
  2732.  *
  2733.  * Get the Tcl major, minor, and patchlevel version numbers and
  2734.  *      the release type.  A patch is a release type TCL_FINAL_RELEASE
  2735.  *      with a patchLevel > 0.
  2736.  *
  2737.  * Results:
  2738.  * None.
  2739.  *
  2740.  * Side effects:
  2741.  * None.
  2742.  *
  2743.  *----------------------------------------------------------------------
  2744.  */
  2745. void
  2746. Tcl_GetVersion(majorV, minorV, patchLevelV, type)
  2747.     int *majorV;
  2748.     int *minorV;
  2749.     int *patchLevelV;
  2750.     int *type;
  2751. {
  2752.     if (majorV != NULL) {
  2753.         *majorV = TCL_MAJOR_VERSION;
  2754.     }
  2755.     if (minorV != NULL) {
  2756.         *minorV = TCL_MINOR_VERSION;
  2757.     }
  2758.     if (patchLevelV != NULL) {
  2759.         *patchLevelV = TCL_RELEASE_SERIAL;
  2760.     }
  2761.     if (type != NULL) {
  2762.         *type = TCL_RELEASE_LEVEL;
  2763.     }
  2764. }
  2765. #ifdef USE_DTRACE
  2766. /*
  2767.  *----------------------------------------------------------------------
  2768.  *
  2769.  * DTraceObjCmd --
  2770.  *
  2771.  * This function is invoked to process the "::tcl::dtrace" Tcl command.
  2772.  *
  2773.  * Results:
  2774.  * A standard Tcl object result.
  2775.  *
  2776.  * Side effects:
  2777.  * The 'tcl-probe' DTrace probe is triggered (if it is enabled).
  2778.  *
  2779.  *----------------------------------------------------------------------
  2780.  */
  2781. static int
  2782. DTraceObjCmd(
  2783.     ClientData dummy, /* Not used. */
  2784.     Tcl_Interp *interp, /* Current interpreter. */
  2785.     int objc, /* Number of arguments. */
  2786.     Tcl_Obj *CONST objv[]) /* Argument objects. */
  2787. {
  2788.     if (TCL_DTRACE_TCL_PROBE_ENABLED()) {
  2789. char *a[10];
  2790. int i = 0;
  2791. while (i++ < 10) {
  2792.     a[i-1] = i < objc ? TclGetString(objv[i]) : NULL;
  2793. }
  2794. TCL_DTRACE_TCL_PROBE(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
  2795. a[8], a[9]);
  2796.     }
  2797.     return TCL_OK;
  2798. }
  2799. #endif /* USE_DTRACE */
  2800. /*
  2801.  * Local Variables:
  2802.  * mode: c
  2803.  * c-basic-offset: 4
  2804.  * fill-column: 78
  2805.  * End:
  2806.  */