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

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclResult.c --
  3.  *
  4.  * This file contains code to manage the interpreter result.
  5.  *
  6.  * Copyright (c) 1997 by Sun Microsystems, Inc.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * RCS: @(#) $Id: tclResult.c,v 1.5.2.2 2004/09/30 22:45:15 dgp Exp $
  12.  */
  13. #include "tclInt.h"
  14. /*
  15.  * Function prototypes for local procedures in this file:
  16.  */
  17. static void             ResetObjResult _ANSI_ARGS_((Interp *iPtr));
  18. static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
  19.     int newSpace));
  20. /*
  21.  *----------------------------------------------------------------------
  22.  *
  23.  * Tcl_SaveResult --
  24.  *
  25.  *      Takes a snapshot of the current result state of the interpreter.
  26.  *      The snapshot can be restored at any point by
  27.  *      Tcl_RestoreResult. Note that this routine does not 
  28.  * preserve the errorCode, errorInfo, or flags fields so it
  29.  * should not be used if an error is in progress.
  30.  *
  31.  *      Once a snapshot is saved, it must be restored by calling
  32.  *      Tcl_RestoreResult, or discarded by calling
  33.  *      Tcl_DiscardResult.
  34.  *
  35.  * Results:
  36.  * None.
  37.  *
  38.  * Side effects:
  39.  * Resets the interpreter result.
  40.  *
  41.  *----------------------------------------------------------------------
  42.  */
  43. void
  44. Tcl_SaveResult(interp, statePtr)
  45.     Tcl_Interp *interp; /* Interpreter to save. */
  46.     Tcl_SavedResult *statePtr; /* Pointer to state structure. */
  47. {
  48.     Interp *iPtr = (Interp *) interp;
  49.     /*
  50.      * Move the result object into the save state.  Note that we don't need
  51.      * to change its refcount because we're moving it, not adding a new
  52.      * reference.  Put an empty object into the interpreter.
  53.      */
  54.     statePtr->objResultPtr = iPtr->objResultPtr;
  55.     iPtr->objResultPtr = Tcl_NewObj(); 
  56.     Tcl_IncrRefCount(iPtr->objResultPtr); 
  57.     /*
  58.      * Save the string result. 
  59.      */
  60.     statePtr->freeProc = iPtr->freeProc;
  61.     if (iPtr->result == iPtr->resultSpace) {
  62. /*
  63.  * Copy the static string data out of the interp buffer.
  64.  */
  65. statePtr->result = statePtr->resultSpace;
  66. strcpy(statePtr->result, iPtr->result);
  67. statePtr->appendResult = NULL;
  68.     } else if (iPtr->result == iPtr->appendResult) {
  69. /*
  70.  * Move the append buffer out of the interp.
  71.  */
  72. statePtr->appendResult = iPtr->appendResult;
  73. statePtr->appendAvl = iPtr->appendAvl;
  74. statePtr->appendUsed = iPtr->appendUsed;
  75. statePtr->result = statePtr->appendResult;
  76. iPtr->appendResult = NULL;
  77. iPtr->appendAvl = 0;
  78. iPtr->appendUsed = 0;
  79.     } else {
  80. /*
  81.  * Move the dynamic or static string out of the interpreter.
  82.  */
  83. statePtr->result = iPtr->result;
  84. statePtr->appendResult = NULL;
  85.     }
  86.     iPtr->result = iPtr->resultSpace;
  87.     iPtr->resultSpace[0] = 0;
  88.     iPtr->freeProc = 0;
  89. }
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * Tcl_RestoreResult --
  94.  *
  95.  *      Restores the state of the interpreter to a snapshot taken
  96.  *      by Tcl_SaveResult.  After this call, the token for
  97.  *      the interpreter state is no longer valid.
  98.  *
  99.  * Results:
  100.  *      None.
  101.  *
  102.  * Side effects:
  103.  *      Restores the interpreter result.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107. void
  108. Tcl_RestoreResult(interp, statePtr)
  109.     Tcl_Interp* interp; /* Interpreter being restored. */
  110.     Tcl_SavedResult *statePtr; /* State returned by Tcl_SaveResult. */
  111. {
  112.     Interp *iPtr = (Interp *) interp;
  113.     Tcl_ResetResult(interp);
  114.     /*
  115.      * Restore the string result.
  116.      */
  117.     iPtr->freeProc = statePtr->freeProc;
  118.     if (statePtr->result == statePtr->resultSpace) {
  119. /*
  120.  * Copy the static string data into the interp buffer.
  121.  */
  122. iPtr->result = iPtr->resultSpace;
  123. strcpy(iPtr->result, statePtr->result);
  124.     } else if (statePtr->result == statePtr->appendResult) {
  125. /*
  126.  * Move the append buffer back into the interp.
  127.  */
  128. if (iPtr->appendResult != NULL) {
  129.     ckfree((char *)iPtr->appendResult);
  130. }
  131. iPtr->appendResult = statePtr->appendResult;
  132. iPtr->appendAvl = statePtr->appendAvl;
  133. iPtr->appendUsed = statePtr->appendUsed;
  134. iPtr->result = iPtr->appendResult;
  135.     } else {
  136. /*
  137.  * Move the dynamic or static string back into the interpreter.
  138.  */
  139. iPtr->result = statePtr->result;
  140.     }
  141.     /*
  142.      * Restore the object result.
  143.      */
  144.     Tcl_DecrRefCount(iPtr->objResultPtr);
  145.     iPtr->objResultPtr = statePtr->objResultPtr;
  146. }
  147. /*
  148.  *----------------------------------------------------------------------
  149.  *
  150.  * Tcl_DiscardResult --
  151.  *
  152.  *      Frees the memory associated with an interpreter snapshot
  153.  *      taken by Tcl_SaveResult.  If the snapshot is not
  154.  *      restored, this procedure must be called to discard it,
  155.  *      or the memory will be lost.
  156.  *
  157.  * Results:
  158.  *      None.
  159.  *
  160.  * Side effects:
  161.  *      None.
  162.  *
  163.  *----------------------------------------------------------------------
  164.  */
  165. void
  166. Tcl_DiscardResult(statePtr)
  167.     Tcl_SavedResult *statePtr; /* State returned by Tcl_SaveResult. */
  168. {
  169.     TclDecrRefCount(statePtr->objResultPtr);
  170.     if (statePtr->result == statePtr->appendResult) {
  171. ckfree(statePtr->appendResult);
  172.     } else if (statePtr->freeProc) {
  173. if (statePtr->freeProc == TCL_DYNAMIC) {
  174.     ckfree(statePtr->result);
  175. } else {
  176.     (*statePtr->freeProc)(statePtr->result);
  177. }
  178.     }
  179. }
  180. /*
  181.  *----------------------------------------------------------------------
  182.  *
  183.  * Tcl_SetResult --
  184.  *
  185.  * Arrange for "string" to be the Tcl return value.
  186.  *
  187.  * Results:
  188.  * None.
  189.  *
  190.  * Side effects:
  191.  * interp->result is left pointing either to "string" (if "copy" is 0)
  192.  * or to a copy of string. Also, the object result is reset.
  193.  *
  194.  *----------------------------------------------------------------------
  195.  */
  196. void
  197. Tcl_SetResult(interp, string, freeProc)
  198.     Tcl_Interp *interp; /* Interpreter with which to associate the
  199.  * return value. */
  200.     register char *string; /* Value to be returned.  If NULL, the
  201.  * result is set to an empty string. */
  202.     Tcl_FreeProc *freeProc; /* Gives information about the string:
  203.  * TCL_STATIC, TCL_VOLATILE, or the address
  204.  * of a Tcl_FreeProc such as free. */
  205. {
  206.     Interp *iPtr = (Interp *) interp;
  207.     int length;
  208.     register Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
  209.     char *oldResult = iPtr->result;
  210.     if (string == NULL) {
  211. iPtr->resultSpace[0] = 0;
  212. iPtr->result = iPtr->resultSpace;
  213. iPtr->freeProc = 0;
  214.     } else if (freeProc == TCL_VOLATILE) {
  215. length = strlen(string);
  216. if (length > TCL_RESULT_SIZE) {
  217.     iPtr->result = (char *) ckalloc((unsigned) length+1);
  218.     iPtr->freeProc = TCL_DYNAMIC;
  219. } else {
  220.     iPtr->result = iPtr->resultSpace;
  221.     iPtr->freeProc = 0;
  222. }
  223. strcpy(iPtr->result, string);
  224.     } else {
  225. iPtr->result = string;
  226. iPtr->freeProc = freeProc;
  227.     }
  228.     /*
  229.      * If the old result was dynamically-allocated, free it up.  Do it
  230.      * here, rather than at the beginning, in case the new result value
  231.      * was part of the old result value.
  232.      */
  233.     if (oldFreeProc != 0) {
  234. if (oldFreeProc == TCL_DYNAMIC) {
  235.     ckfree(oldResult);
  236. } else {
  237.     (*oldFreeProc)(oldResult);
  238. }
  239.     }
  240.     /*
  241.      * Reset the object result since we just set the string result.
  242.      */
  243.     ResetObjResult(iPtr);
  244. }
  245. /*
  246.  *----------------------------------------------------------------------
  247.  *
  248.  * Tcl_GetStringResult --
  249.  *
  250.  * Returns an interpreter's result value as a string.
  251.  *
  252.  * Results:
  253.  * The interpreter's result as a string.
  254.  *
  255.  * Side effects:
  256.  * If the string result is empty, the object result is moved to the
  257.  * string result, then the object result is reset.
  258.  *
  259.  *----------------------------------------------------------------------
  260.  */
  261. CONST char *
  262. Tcl_GetStringResult(interp)
  263.      register Tcl_Interp *interp; /* Interpreter whose result to return. */
  264. {
  265.     /*
  266.      * If the string result is empty, move the object result to the
  267.      * string result, then reset the object result.
  268.      */
  269.     
  270.     if (*(interp->result) == 0) {
  271. Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  272.         TCL_VOLATILE);
  273.     }
  274.     return interp->result;
  275. }
  276. /*
  277.  *----------------------------------------------------------------------
  278.  *
  279.  * Tcl_SetObjResult --
  280.  *
  281.  * Arrange for objPtr to be an interpreter's result value.
  282.  *
  283.  * Results:
  284.  * None.
  285.  *
  286.  * Side effects:
  287.  * interp->objResultPtr is left pointing to the object referenced
  288.  * by objPtr. The object's reference count is incremented since
  289.  * there is now a new reference to it. The reference count for any
  290.  * old objResultPtr value is decremented. Also, the string result
  291.  * is reset.
  292.  *
  293.  *----------------------------------------------------------------------
  294.  */
  295. void
  296. Tcl_SetObjResult(interp, objPtr)
  297.     Tcl_Interp *interp; /* Interpreter with which to associate the
  298.  * return object value. */
  299.     register Tcl_Obj *objPtr; /* Tcl object to be returned. If NULL, the
  300.  * obj result is made an empty string
  301.  * object. */
  302. {
  303.     register Interp *iPtr = (Interp *) interp;
  304.     register Tcl_Obj *oldObjResult = iPtr->objResultPtr;
  305.     iPtr->objResultPtr = objPtr;
  306.     Tcl_IncrRefCount(objPtr); /* since interp result is a reference */
  307.     /*
  308.      * We wait until the end to release the old object result, in case
  309.      * we are setting the result to itself.
  310.      */
  311.     
  312.     TclDecrRefCount(oldObjResult);
  313.     /*
  314.      * Reset the string result since we just set the result object.
  315.      */
  316.     if (iPtr->freeProc != NULL) {
  317. if (iPtr->freeProc == TCL_DYNAMIC) {
  318.     ckfree(iPtr->result);
  319. } else {
  320.     (*iPtr->freeProc)(iPtr->result);
  321. }
  322. iPtr->freeProc = 0;
  323.     }
  324.     iPtr->result = iPtr->resultSpace;
  325.     iPtr->resultSpace[0] = 0;
  326. }
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * Tcl_GetObjResult --
  331.  *
  332.  * Returns an interpreter's result value as a Tcl object. The object's
  333.  * reference count is not modified; the caller must do that if it
  334.  * needs to hold on to a long-term reference to it.
  335.  *
  336.  * Results:
  337.  * The interpreter's result as an object.
  338.  *
  339.  * Side effects:
  340.  * If the interpreter has a non-empty string result, the result object
  341.  * is either empty or stale because some procedure set interp->result
  342.  * directly. If so, the string result is moved to the result object
  343.  * then the string result is reset.
  344.  *
  345.  *----------------------------------------------------------------------
  346.  */
  347. Tcl_Obj *
  348. Tcl_GetObjResult(interp)
  349.     Tcl_Interp *interp; /* Interpreter whose result to return. */
  350. {
  351.     register Interp *iPtr = (Interp *) interp;
  352.     Tcl_Obj *objResultPtr;
  353.     int length;
  354.     /*
  355.      * If the string result is non-empty, move the string result to the
  356.      * object result, then reset the string result.
  357.      */
  358.     
  359.     if (*(iPtr->result) != 0) {
  360. ResetObjResult(iPtr);
  361. objResultPtr = iPtr->objResultPtr;
  362. length = strlen(iPtr->result);
  363. TclInitStringRep(objResultPtr, iPtr->result, length);
  364. if (iPtr->freeProc != NULL) {
  365.     if (iPtr->freeProc == TCL_DYNAMIC) {
  366. ckfree(iPtr->result);
  367.     } else {
  368. (*iPtr->freeProc)(iPtr->result);
  369.     }
  370.     iPtr->freeProc = 0;
  371. }
  372. iPtr->result = iPtr->resultSpace;
  373. iPtr->resultSpace[0] = 0;
  374.     }
  375.     return iPtr->objResultPtr;
  376. }
  377. /*
  378.  *----------------------------------------------------------------------
  379.  *
  380.  * Tcl_AppendResultVA --
  381.  *
  382.  * Append a variable number of strings onto the interpreter's string
  383.  * result.
  384.  *
  385.  * Results:
  386.  * None.
  387.  *
  388.  * Side effects:
  389.  * The result of the interpreter given by the first argument is
  390.  * extended by the strings in the va_list (up to a terminating NULL
  391.  * argument).
  392.  *
  393.  * If the string result is empty, the object result is moved to the
  394.  * string result, then the object result is reset.
  395.  *
  396.  *----------------------------------------------------------------------
  397.  */
  398. void
  399. Tcl_AppendResultVA (interp, argList)
  400.     Tcl_Interp *interp; /* Interpreter with which to associate the
  401.  * return value. */
  402.     va_list argList; /* Variable argument list. */
  403. {
  404. #define STATIC_LIST_SIZE 16
  405.     Interp *iPtr = (Interp *) interp;
  406.     char *string, *static_list[STATIC_LIST_SIZE];
  407.     char **args = static_list;
  408.     int nargs_space = STATIC_LIST_SIZE;
  409.     int nargs, newSpace, i;
  410.     /*
  411.      * If the string result is empty, move the object result to the
  412.      * string result, then reset the object result.
  413.      */
  414.     if (*(iPtr->result) == 0) {
  415. Tcl_SetResult((Tcl_Interp *) iPtr,
  416.         TclGetString(Tcl_GetObjResult((Tcl_Interp *) iPtr)),
  417.         TCL_VOLATILE);
  418.     }
  419.     
  420.     /*
  421.      * Scan through all the arguments to see how much space is needed
  422.      * and save pointers to the arguments in the args array,
  423.      * reallocating as necessary.
  424.      */
  425.     nargs = 0;
  426.     newSpace = 0;
  427.     while (1) {
  428.   string = va_arg(argList, char *);
  429. if (string == NULL) {
  430.     break;
  431. }
  432.   if (nargs >= nargs_space) {
  433.       /* 
  434.        * Expand the args buffer
  435.        */
  436.       nargs_space += STATIC_LIST_SIZE;
  437.       if (args == static_list) {
  438.        args = (void *)ckalloc(nargs_space * sizeof(char *));
  439.   for (i = 0; i < nargs; ++i) {
  440.       args[i] = static_list[i];
  441.   }
  442.       } else {
  443.   args = (void *)ckrealloc((void *)args,
  444. nargs_space * sizeof(char *));
  445.       }
  446.   }
  447.    newSpace += strlen(string);
  448. args[nargs++] = string;
  449.     }
  450.     /*
  451.      * If the append buffer isn't already setup and large enough to hold
  452.      * the new data, set it up.
  453.      */
  454.     if ((iPtr->result != iPtr->appendResult)
  455.     || (iPtr->appendResult[iPtr->appendUsed] != 0)
  456.     || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) {
  457.        SetupAppendBuffer(iPtr, newSpace);
  458.     }
  459.     /*
  460.      * Now go through all the argument strings again, copying them into the
  461.      * buffer.
  462.      */
  463.     for (i = 0; i < nargs; ++i) {
  464.   string = args[i];
  465.    strcpy(iPtr->appendResult + iPtr->appendUsed, string);
  466.    iPtr->appendUsed += strlen(string);
  467.     }
  468.  
  469.     /*
  470.      * If we had to allocate a buffer from the heap, 
  471.      * free it now.
  472.      */
  473.  
  474.     if (args != static_list) {
  475.       ckfree((void *)args);
  476.     }
  477. #undef STATIC_LIST_SIZE
  478. }
  479. /*
  480.  *----------------------------------------------------------------------
  481.  *
  482.  * Tcl_AppendResult --
  483.  *
  484.  * Append a variable number of strings onto the interpreter's string
  485.  * result.
  486.  *
  487.  * Results:
  488.  * None.
  489.  *
  490.  * Side effects:
  491.  * The result of the interpreter given by the first argument is
  492.  * extended by the strings given by the second and following arguments
  493.  * (up to a terminating NULL argument).
  494.  *
  495.  * If the string result is empty, the object result is moved to the
  496.  * string result, then the object result is reset.
  497.  *
  498.  *----------------------------------------------------------------------
  499.  */
  500. void
  501. Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1)
  502. {
  503.     Tcl_Interp *interp;
  504.     va_list argList;
  505.     interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
  506.     Tcl_AppendResultVA(interp, argList);
  507.     va_end(argList);
  508. }
  509. /*
  510.  *----------------------------------------------------------------------
  511.  *
  512.  * Tcl_AppendElement --
  513.  *
  514.  * Convert a string to a valid Tcl list element and append it to the
  515.  * result (which is ostensibly a list).
  516.  *
  517.  * Results:
  518.  * None.
  519.  *
  520.  * Side effects:
  521.  * The result in the interpreter given by the first argument is
  522.  * extended with a list element converted from string. A separator
  523.  * space is added before the converted list element unless the current
  524.  * result is empty, contains the single character "{", or ends in " {".
  525.  *
  526.  * If the string result is empty, the object result is moved to the
  527.  * string result, then the object result is reset.
  528.  *
  529.  *----------------------------------------------------------------------
  530.  */
  531. void
  532. Tcl_AppendElement(interp, string)
  533.     Tcl_Interp *interp; /* Interpreter whose result is to be
  534.  * extended. */
  535.     CONST char *string; /* String to convert to list element and
  536.  * add to result. */
  537. {
  538.     Interp *iPtr = (Interp *) interp;
  539.     char *dst;
  540.     int size;
  541.     int flags;
  542.     /*
  543.      * If the string result is empty, move the object result to the
  544.      * string result, then reset the object result.
  545.      */
  546.     if (*(iPtr->result) == 0) {
  547. Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
  548.         TCL_VOLATILE);
  549.     }
  550.     /*
  551.      * See how much space is needed, and grow the append buffer if
  552.      * needed to accommodate the list element.
  553.      */
  554.     size = Tcl_ScanElement(string, &flags) + 1;
  555.     if ((iPtr->result != iPtr->appendResult)
  556.     || (iPtr->appendResult[iPtr->appendUsed] != 0)
  557.     || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
  558.        SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
  559.     }
  560.     /*
  561.      * Convert the string into a list element and copy it to the
  562.      * buffer that's forming, with a space separator if needed.
  563.      */
  564.     dst = iPtr->appendResult + iPtr->appendUsed;
  565.     if (TclNeedSpace(iPtr->appendResult, dst)) {
  566. iPtr->appendUsed++;
  567. *dst = ' ';
  568. dst++;
  569.     }
  570.     iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
  571. }
  572. /*
  573.  *----------------------------------------------------------------------
  574.  *
  575.  * SetupAppendBuffer --
  576.  *
  577.  * This procedure makes sure that there is an append buffer properly
  578.  * initialized, if necessary, from the interpreter's result, and
  579.  * that it has at least enough room to accommodate newSpace new
  580.  * bytes of information.
  581.  *
  582.  * Results:
  583.  * None.
  584.  *
  585.  * Side effects:
  586.  * None.
  587.  *
  588.  *----------------------------------------------------------------------
  589.  */
  590. static void
  591. SetupAppendBuffer(iPtr, newSpace)
  592.     Interp *iPtr; /* Interpreter whose result is being set up. */
  593.     int newSpace; /* Make sure that at least this many bytes
  594.  * of new information may be added. */
  595. {
  596.     int totalSpace;
  597.     /*
  598.      * Make the append buffer larger, if that's necessary, then copy the
  599.      * result into the append buffer and make the append buffer the official
  600.      * Tcl result.
  601.      */
  602.     if (iPtr->result != iPtr->appendResult) {
  603. /*
  604.  * If an oversized buffer was used recently, then free it up
  605.  * so we go back to a smaller buffer.  This avoids tying up
  606.  * memory forever after a large operation.
  607.  */
  608. if (iPtr->appendAvl > 500) {
  609.     ckfree(iPtr->appendResult);
  610.     iPtr->appendResult = NULL;
  611.     iPtr->appendAvl = 0;
  612. }
  613. iPtr->appendUsed = strlen(iPtr->result);
  614.     } else if (iPtr->result[iPtr->appendUsed] != 0) {
  615. /*
  616.  * Most likely someone has modified a result created by
  617.  * Tcl_AppendResult et al. so that it has a different size.
  618.  * Just recompute the size.
  619.  */
  620. iPtr->appendUsed = strlen(iPtr->result);
  621.     }
  622.     
  623.     totalSpace = newSpace + iPtr->appendUsed;
  624.     if (totalSpace >= iPtr->appendAvl) {
  625. char *new;
  626. if (totalSpace < 100) {
  627.     totalSpace = 200;
  628. } else {
  629.     totalSpace *= 2;
  630. }
  631. new = (char *) ckalloc((unsigned) totalSpace);
  632. strcpy(new, iPtr->result);
  633. if (iPtr->appendResult != NULL) {
  634.     ckfree(iPtr->appendResult);
  635. }
  636. iPtr->appendResult = new;
  637. iPtr->appendAvl = totalSpace;
  638.     } else if (iPtr->result != iPtr->appendResult) {
  639. strcpy(iPtr->appendResult, iPtr->result);
  640.     }
  641.     
  642.     Tcl_FreeResult((Tcl_Interp *) iPtr);
  643.     iPtr->result = iPtr->appendResult;
  644. }
  645. /*
  646.  *----------------------------------------------------------------------
  647.  *
  648.  * Tcl_FreeResult --
  649.  *
  650.  * This procedure frees up the memory associated with an interpreter's
  651.  * string result. It also resets the interpreter's result object.
  652.  * Tcl_FreeResult is most commonly used when a procedure is about to
  653.  * replace one result value with another.
  654.  *
  655.  * Results:
  656.  * None.
  657.  *
  658.  * Side effects:
  659.  * Frees the memory associated with interp's string result and sets
  660.  * interp->freeProc to zero, but does not change interp->result or
  661.  * clear error state. Resets interp's result object to an unshared
  662.  * empty object.
  663.  *
  664.  *----------------------------------------------------------------------
  665.  */
  666. void
  667. Tcl_FreeResult(interp)
  668.     register Tcl_Interp *interp; /* Interpreter for which to free result. */
  669. {
  670.     register Interp *iPtr = (Interp *) interp;
  671.     
  672.     if (iPtr->freeProc != NULL) {
  673. if (iPtr->freeProc == TCL_DYNAMIC) {
  674.     ckfree(iPtr->result);
  675. } else {
  676.     (*iPtr->freeProc)(iPtr->result);
  677. }
  678. iPtr->freeProc = 0;
  679.     }
  680.     
  681.     ResetObjResult(iPtr);
  682. }
  683. /*
  684.  *----------------------------------------------------------------------
  685.  *
  686.  * Tcl_ResetResult --
  687.  *
  688.  * This procedure resets both the interpreter's string and object
  689.  * results.
  690.  *
  691.  * Results:
  692.  * None.
  693.  *
  694.  * Side effects:
  695.  * It resets the result object to an unshared empty object. It
  696.  * then restores the interpreter's string result area to its default
  697.  * initialized state, freeing up any memory that may have been
  698.  * allocated. It also clears any error information for the interpreter.
  699.  *
  700.  *----------------------------------------------------------------------
  701.  */
  702. void
  703. Tcl_ResetResult(interp)
  704.     register Tcl_Interp *interp; /* Interpreter for which to clear result. */
  705. {
  706.     register Interp *iPtr = (Interp *) interp;
  707.     ResetObjResult(iPtr);
  708.     if (iPtr->freeProc != NULL) {
  709. if (iPtr->freeProc == TCL_DYNAMIC) {
  710.     ckfree(iPtr->result);
  711. } else {
  712.     (*iPtr->freeProc)(iPtr->result);
  713. }
  714. iPtr->freeProc = 0;
  715.     }
  716.     iPtr->result = iPtr->resultSpace;
  717.     iPtr->resultSpace[0] = 0;
  718.     iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET);
  719. }
  720. /*
  721.  *----------------------------------------------------------------------
  722.  *
  723.  * ResetObjResult --
  724.  *
  725.  * Procedure used to reset an interpreter's Tcl result object.
  726.  *
  727.  * Results:
  728.  * None.
  729.  *
  730.  * Side effects:
  731.  * Resets the interpreter's result object to an unshared empty string
  732.  * object with ref count one. It does not clear any error information
  733.  * in the interpreter.
  734.  *
  735.  *----------------------------------------------------------------------
  736.  */
  737. static void
  738. ResetObjResult(iPtr)
  739.     register Interp *iPtr; /* Points to the interpreter whose result
  740.  * object should be reset. */
  741. {
  742.     register Tcl_Obj *objResultPtr = iPtr->objResultPtr;
  743.     if (Tcl_IsShared(objResultPtr)) {
  744. TclDecrRefCount(objResultPtr);
  745. TclNewObj(objResultPtr);
  746. Tcl_IncrRefCount(objResultPtr);
  747. iPtr->objResultPtr = objResultPtr;
  748.     } else {
  749. if ((objResultPtr->bytes != NULL)
  750.         && (objResultPtr->bytes != tclEmptyStringRep)) {
  751.     ckfree((char *) objResultPtr->bytes);
  752. }
  753. objResultPtr->bytes  = tclEmptyStringRep;
  754. objResultPtr->length = 0;
  755. if ((objResultPtr->typePtr != NULL)
  756.         && (objResultPtr->typePtr->freeIntRepProc != NULL)) {
  757.     objResultPtr->typePtr->freeIntRepProc(objResultPtr);
  758. }
  759. objResultPtr->typePtr = (Tcl_ObjType *) NULL;
  760.     }
  761. }
  762. /*
  763.  *----------------------------------------------------------------------
  764.  *
  765.  * Tcl_SetErrorCodeVA --
  766.  *
  767.  * This procedure is called to record machine-readable information
  768.  * about an error that is about to be returned.
  769.  *
  770.  * Results:
  771.  * None.
  772.  *
  773.  * Side effects:
  774.  * The errorCode global variable is modified to hold all of the
  775.  * arguments to this procedure, in a list form with each argument
  776.  * becoming one element of the list.  A flag is set internally
  777.  * to remember that errorCode has been set, so the variable doesn't
  778.  * get set automatically when the error is returned.
  779.  *
  780.  *----------------------------------------------------------------------
  781.  */
  782. void
  783. Tcl_SetErrorCodeVA (interp, argList)
  784.     Tcl_Interp *interp; /* Interpreter in which to access the errorCode
  785.  * variable. */
  786.     va_list argList; /* Variable argument list. */
  787. {
  788.     char *string;
  789.     int flags;
  790.     Interp *iPtr = (Interp *) interp;
  791.     /*
  792.      * Scan through the arguments one at a time, appending them to
  793.      * $errorCode as list elements.
  794.      */
  795.     flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT;
  796.     while (1) {
  797. string = va_arg(argList, char *);
  798. if (string == NULL) {
  799.     break;
  800. }
  801. (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode",
  802. (char *) NULL, string, flags);
  803. flags |= TCL_APPEND_VALUE;
  804.     }
  805.     iPtr->flags |= ERROR_CODE_SET;
  806. }
  807. /*
  808.  *----------------------------------------------------------------------
  809.  *
  810.  * Tcl_SetErrorCode --
  811.  *
  812.  * This procedure is called to record machine-readable information
  813.  * about an error that is about to be returned.
  814.  *
  815.  * Results:
  816.  * None.
  817.  *
  818.  * Side effects:
  819.  * The errorCode global variable is modified to hold all of the
  820.  * arguments to this procedure, in a list form with each argument
  821.  * becoming one element of the list.  A flag is set internally
  822.  * to remember that errorCode has been set, so the variable doesn't
  823.  * get set automatically when the error is returned.
  824.  *
  825.  *----------------------------------------------------------------------
  826.  */
  827. /* VARARGS2 */
  828. void
  829. Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1)
  830. {
  831.     Tcl_Interp *interp;
  832.     va_list argList;
  833.     /*
  834.      * Scan through the arguments one at a time, appending them to
  835.      * $errorCode as list elements.
  836.      */
  837.     interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
  838.     Tcl_SetErrorCodeVA(interp, argList);
  839.     va_end(argList);
  840. }
  841. /*
  842.  *----------------------------------------------------------------------
  843.  *
  844.  * Tcl_SetObjErrorCode --
  845.  *
  846.  * This procedure is called to record machine-readable information
  847.  * about an error that is about to be returned. The caller should
  848.  * build a list object up and pass it to this routine.
  849.  *
  850.  * Results:
  851.  * None.
  852.  *
  853.  * Side effects:
  854.  * The errorCode global variable is modified to be the new value.
  855.  * A flag is set internally to remember that errorCode has been
  856.  * set, so the variable doesn't get set automatically when the
  857.  * error is returned.
  858.  *
  859.  *----------------------------------------------------------------------
  860.  */
  861. void
  862. Tcl_SetObjErrorCode(interp, errorObjPtr)
  863.     Tcl_Interp *interp;
  864.     Tcl_Obj *errorObjPtr;
  865. {
  866.     Interp *iPtr;
  867.     
  868.     iPtr = (Interp *) interp;
  869.     Tcl_SetVar2Ex(interp, "errorCode", NULL, errorObjPtr, TCL_GLOBAL_ONLY);
  870.     iPtr->flags |= ERROR_CODE_SET;
  871. }
  872. /*
  873.  *-------------------------------------------------------------------------
  874.  *
  875.  * TclTransferResult --
  876.  *
  877.  * Copy the result (and error information) from one interp to 
  878.  * another.  Used when one interp has caused another interp to 
  879.  * evaluate a script and then wants to transfer the results back
  880.  * to itself.
  881.  *
  882.  * This routine copies the string reps of the result and error 
  883.  * information.  It does not simply increment the refcounts of the
  884.  * result and error information objects themselves.
  885.  * It is not legal to exchange objects between interps, because an
  886.  * object may be kept alive by one interp, but have an internal rep 
  887.  * that is only valid while some other interp is alive.  
  888.  *
  889.  * Results:
  890.  * The target interp's result is set to a copy of the source interp's
  891.  * result.  The source's error information "$errorInfo" may be
  892.  * appended to the target's error information and the source's error
  893.  * code "$errorCode" may be stored in the target's error code.
  894.  *
  895.  * Side effects:
  896.  * None.
  897.  *
  898.  *-------------------------------------------------------------------------
  899.  */
  900. void
  901. TclTransferResult(sourceInterp, result, targetInterp)
  902.     Tcl_Interp *sourceInterp; /* Interp whose result and error information
  903.  * should be moved to the target interp.  
  904.  * After moving result, this interp's result 
  905.  * is reset. */
  906.     int result; /* TCL_OK if just the result should be copied, 
  907.  * TCL_ERROR if both the result and error 
  908.  * information should be copied. */
  909.     Tcl_Interp *targetInterp; /* Interp where result and error information 
  910.  * should be stored.  If source and target
  911.  * are the same, nothing is done. */
  912. {
  913.     Interp *iPtr;
  914.     Tcl_Obj *objPtr;
  915.     if (sourceInterp == targetInterp) {
  916. return;
  917.     }
  918.     if (result == TCL_ERROR) {
  919. /*
  920.  * An error occurred, so transfer error information from the source
  921.  * interpreter to the target interpreter.  Setting the flags tells
  922.  * the target interp that it has inherited a partial traceback
  923.  * chain, not just a simple error message.
  924.  */
  925. iPtr = (Interp *) sourceInterp;
  926.         if ((iPtr->flags & ERR_ALREADY_LOGGED) == 0) {
  927.             Tcl_AddErrorInfo(sourceInterp, "");
  928.         }
  929.         iPtr->flags &= ~(ERR_ALREADY_LOGGED);
  930.         
  931.         Tcl_ResetResult(targetInterp);
  932.         
  933. objPtr = Tcl_GetVar2Ex(sourceInterp, "errorInfo", NULL,
  934. TCL_GLOBAL_ONLY);
  935. if (objPtr) {
  936.     Tcl_SetVar2Ex(targetInterp, "errorInfo", NULL, objPtr,
  937.     TCL_GLOBAL_ONLY);
  938.     ((Interp *) targetInterp)->flags |= ERR_IN_PROGRESS;
  939. }
  940. objPtr = Tcl_GetVar2Ex(sourceInterp, "errorCode", NULL,
  941. TCL_GLOBAL_ONLY);
  942. if (objPtr) {
  943.     Tcl_SetObjErrorCode(targetInterp, objPtr);
  944. }
  945.     }
  946.     ((Interp *) targetInterp)->returnCode = ((Interp *) sourceInterp)->returnCode;
  947.     Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp));
  948.     Tcl_ResetResult(sourceInterp);
  949. }