tclResult.c

Go to the documentation of this file.
00001 /*
00002  * tclResult.c --
00003  *
00004  *      This file contains code to manage the interpreter result.
00005  *
00006  * Copyright (c) 1997 by Sun Microsystems, Inc.
00007  *
00008  * See the file "license.terms" for information on usage and redistribution of
00009  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  *
00011  * RCS: @(#) $Id: tclResult.c,v 1.45 2007/12/13 15:23:20 dgp Exp $
00012  */
00013 
00014 #include "tclInt.h"
00015 
00016 /*
00017  * Indices of the standard return options dictionary keys.
00018  */
00019 
00020 enum returnKeys {
00021     KEY_CODE,   KEY_ERRORCODE,  KEY_ERRORINFO,  KEY_ERRORLINE,
00022     KEY_LEVEL,  KEY_OPTIONS,    KEY_LAST
00023 };
00024 
00025 /*
00026  * Function prototypes for local functions in this file:
00027  */
00028 
00029 static Tcl_Obj **       GetKeys(void);
00030 static void             ReleaseKeys(ClientData clientData);
00031 static void             ResetObjResult(Interp *iPtr);
00032 static void             SetupAppendBuffer(Interp *iPtr, int newSpace);
00033 
00034 /*
00035  * This structure is used to take a snapshot of the interpreter state in
00036  * Tcl_SaveInterpState. You can snapshot the state, execute a command, and
00037  * then back up to the result or the error that was previously in progress.
00038  */
00039 
00040 typedef struct InterpState {
00041     int status;                 /* return code status */
00042     int flags;                  /* Each remaining field saves the */
00043     int returnLevel;            /* corresponding field of the Interp */
00044     int returnCode;             /* struct. These fields taken together are */
00045     Tcl_Obj *errorInfo;         /* the "state" of the interp. */
00046     Tcl_Obj *errorCode;
00047     Tcl_Obj *returnOpts;
00048     Tcl_Obj *objResult;
00049 } InterpState;
00050 
00051 /*
00052  *----------------------------------------------------------------------
00053  *
00054  * Tcl_SaveInterpState --
00055  *
00056  *      Fills a token with a snapshot of the current state of the interpreter.
00057  *      The snapshot can be restored at any point by TclRestoreInterpState.
00058  *
00059  *      The token returned must be eventally passed to one of the routines
00060  *      TclRestoreInterpState or TclDiscardInterpState, or there will be a
00061  *      memory leak.
00062  *
00063  * Results:
00064  *      Returns a token representing the interp state.
00065  *
00066  * Side effects:
00067  *      None.
00068  *
00069  *----------------------------------------------------------------------
00070  */
00071 
00072 Tcl_InterpState
00073 Tcl_SaveInterpState(
00074     Tcl_Interp *interp,         /* Interpreter's state to be saved */
00075     int status)                 /* status code for current operation */
00076 {
00077     Interp *iPtr = (Interp *)interp;
00078     InterpState *statePtr = (InterpState *)ckalloc(sizeof(InterpState));
00079 
00080     statePtr->status = status;
00081     statePtr->flags = iPtr->flags & ERR_ALREADY_LOGGED;
00082     statePtr->returnLevel = iPtr->returnLevel;
00083     statePtr->returnCode = iPtr->returnCode;
00084     statePtr->errorInfo = iPtr->errorInfo;
00085     if (statePtr->errorInfo) {
00086         Tcl_IncrRefCount(statePtr->errorInfo);
00087     }
00088     statePtr->errorCode = iPtr->errorCode;
00089     if (statePtr->errorCode) {
00090         Tcl_IncrRefCount(statePtr->errorCode);
00091     }
00092     statePtr->returnOpts = iPtr->returnOpts;
00093     if (statePtr->returnOpts) {
00094         Tcl_IncrRefCount(statePtr->returnOpts);
00095     }
00096     statePtr->objResult = Tcl_GetObjResult(interp);
00097     Tcl_IncrRefCount(statePtr->objResult);
00098     return (Tcl_InterpState) statePtr;
00099 }
00100 
00101 /*
00102  *----------------------------------------------------------------------
00103  *
00104  * Tcl_RestoreInterpState --
00105  *
00106  *      Accepts an interp and a token previously returned by
00107  *      Tcl_SaveInterpState. Restore the state of the interp to what it was at
00108  *      the time of the Tcl_SaveInterpState call.
00109  *
00110  * Results:
00111  *      Returns the status value originally passed in to Tcl_SaveInterpState.
00112  *
00113  * Side effects:
00114  *      Restores the interp state and frees memory held by token.
00115  *
00116  *----------------------------------------------------------------------
00117  */
00118 
00119 int
00120 Tcl_RestoreInterpState(
00121     Tcl_Interp *interp,         /* Interpreter's state to be restored. */
00122     Tcl_InterpState state)      /* Saved interpreter state. */
00123 {
00124     Interp *iPtr = (Interp *)interp;
00125     InterpState *statePtr = (InterpState *)state;
00126     int status = statePtr->status;
00127 
00128     iPtr->flags &= ~ERR_ALREADY_LOGGED;
00129     iPtr->flags |= (statePtr->flags & ERR_ALREADY_LOGGED);
00130 
00131     iPtr->returnLevel = statePtr->returnLevel;
00132     iPtr->returnCode = statePtr->returnCode;
00133     if (iPtr->errorInfo) {
00134         Tcl_DecrRefCount(iPtr->errorInfo);
00135     }
00136     iPtr->errorInfo = statePtr->errorInfo;
00137     if (iPtr->errorInfo) {
00138         Tcl_IncrRefCount(iPtr->errorInfo);
00139     }
00140     if (iPtr->errorCode) {
00141         Tcl_DecrRefCount(iPtr->errorCode);
00142     }
00143     iPtr->errorCode = statePtr->errorCode;
00144     if (iPtr->errorCode) {
00145         Tcl_IncrRefCount(iPtr->errorCode);
00146     }
00147     if (iPtr->returnOpts) {
00148         Tcl_DecrRefCount(iPtr->returnOpts);
00149     }
00150     iPtr->returnOpts = statePtr->returnOpts;
00151     if (iPtr->returnOpts) {
00152         Tcl_IncrRefCount(iPtr->returnOpts);
00153     }
00154     Tcl_SetObjResult(interp, statePtr->objResult);
00155     Tcl_DiscardInterpState(state);
00156     return status;
00157 }
00158 
00159 /*
00160  *----------------------------------------------------------------------
00161  *
00162  * Tcl_DiscardInterpState --
00163  *
00164  *      Accepts a token previously returned by Tcl_SaveInterpState. Frees the
00165  *      memory it uses.
00166  *
00167  * Results:
00168  *      None.
00169  *
00170  * Side effects:
00171  *      Frees memory.
00172  *
00173  *----------------------------------------------------------------------
00174  */
00175 
00176 void
00177 Tcl_DiscardInterpState(
00178     Tcl_InterpState state)      /* saved interpreter state */
00179 {
00180     InterpState *statePtr = (InterpState *)state;
00181 
00182     if (statePtr->errorInfo) {
00183         Tcl_DecrRefCount(statePtr->errorInfo);
00184     }
00185     if (statePtr->errorCode) {
00186         Tcl_DecrRefCount(statePtr->errorCode);
00187     }
00188     if (statePtr->returnOpts) {
00189         Tcl_DecrRefCount(statePtr->returnOpts);
00190     }
00191     Tcl_DecrRefCount(statePtr->objResult);
00192     ckfree((char *) statePtr);
00193 }
00194 
00195 /*
00196  *----------------------------------------------------------------------
00197  *
00198  * Tcl_SaveResult --
00199  *
00200  *      Takes a snapshot of the current result state of the interpreter. The
00201  *      snapshot can be restored at any point by Tcl_RestoreResult. Note that
00202  *      this routine does not preserve the errorCode, errorInfo, or flags
00203  *      fields so it should not be used if an error is in progress.
00204  *
00205  *      Once a snapshot is saved, it must be restored by calling
00206  *      Tcl_RestoreResult, or discarded by calling Tcl_DiscardResult.
00207  *
00208  * Results:
00209  *      None.
00210  *
00211  * Side effects:
00212  *      Resets the interpreter result.
00213  *
00214  *----------------------------------------------------------------------
00215  */
00216 
00217 void
00218 Tcl_SaveResult(
00219     Tcl_Interp *interp,         /* Interpreter to save. */
00220     Tcl_SavedResult *statePtr)  /* Pointer to state structure. */
00221 {
00222     Interp *iPtr = (Interp *) interp;
00223 
00224     /*
00225      * Move the result object into the save state. Note that we don't need to
00226      * change its refcount because we're moving it, not adding a new
00227      * reference. Put an empty object into the interpreter.
00228      */
00229 
00230     statePtr->objResultPtr = iPtr->objResultPtr;
00231     iPtr->objResultPtr = Tcl_NewObj();
00232     Tcl_IncrRefCount(iPtr->objResultPtr);
00233 
00234     /*
00235      * Save the string result.
00236      */
00237 
00238     statePtr->freeProc = iPtr->freeProc;
00239     if (iPtr->result == iPtr->resultSpace) {
00240         /*
00241          * Copy the static string data out of the interp buffer.
00242          */
00243 
00244         statePtr->result = statePtr->resultSpace;
00245         strcpy(statePtr->result, iPtr->result);
00246         statePtr->appendResult = NULL;
00247     } else if (iPtr->result == iPtr->appendResult) {
00248         /*
00249          * Move the append buffer out of the interp.
00250          */
00251 
00252         statePtr->appendResult = iPtr->appendResult;
00253         statePtr->appendAvl = iPtr->appendAvl;
00254         statePtr->appendUsed = iPtr->appendUsed;
00255         statePtr->result = statePtr->appendResult;
00256         iPtr->appendResult = NULL;
00257         iPtr->appendAvl = 0;
00258         iPtr->appendUsed = 0;
00259     } else {
00260         /*
00261          * Move the dynamic or static string out of the interpreter.
00262          */
00263 
00264         statePtr->result = iPtr->result;
00265         statePtr->appendResult = NULL;
00266     }
00267 
00268     iPtr->result = iPtr->resultSpace;
00269     iPtr->resultSpace[0] = 0;
00270     iPtr->freeProc = 0;
00271 }
00272 
00273 /*
00274  *----------------------------------------------------------------------
00275  *
00276  * Tcl_RestoreResult --
00277  *
00278  *      Restores the state of the interpreter to a snapshot taken by
00279  *      Tcl_SaveResult. After this call, the token for the interpreter state
00280  *      is no longer valid.
00281  *
00282  * Results:
00283  *      None.
00284  *
00285  * Side effects:
00286  *      Restores the interpreter result.
00287  *
00288  *----------------------------------------------------------------------
00289  */
00290 
00291 void
00292 Tcl_RestoreResult(
00293     Tcl_Interp *interp,         /* Interpreter being restored. */
00294     Tcl_SavedResult *statePtr)  /* State returned by Tcl_SaveResult. */
00295 {
00296     Interp *iPtr = (Interp *) interp;
00297 
00298     Tcl_ResetResult(interp);
00299 
00300     /*
00301      * Restore the string result.
00302      */
00303 
00304     iPtr->freeProc = statePtr->freeProc;
00305     if (statePtr->result == statePtr->resultSpace) {
00306         /*
00307          * Copy the static string data into the interp buffer.
00308          */
00309 
00310         iPtr->result = iPtr->resultSpace;
00311         strcpy(iPtr->result, statePtr->result);
00312     } else if (statePtr->result == statePtr->appendResult) {
00313         /*
00314          * Move the append buffer back into the interp.
00315          */
00316 
00317         if (iPtr->appendResult != NULL) {
00318             ckfree((char *) iPtr->appendResult);
00319         }
00320 
00321         iPtr->appendResult = statePtr->appendResult;
00322         iPtr->appendAvl = statePtr->appendAvl;
00323         iPtr->appendUsed = statePtr->appendUsed;
00324         iPtr->result = iPtr->appendResult;
00325     } else {
00326         /*
00327          * Move the dynamic or static string back into the interpreter.
00328          */
00329 
00330         iPtr->result = statePtr->result;
00331     }
00332 
00333     /*
00334      * Restore the object result.
00335      */
00336 
00337     Tcl_DecrRefCount(iPtr->objResultPtr);
00338     iPtr->objResultPtr = statePtr->objResultPtr;
00339 }
00340 
00341 /*
00342  *----------------------------------------------------------------------
00343  *
00344  * Tcl_DiscardResult --
00345  *
00346  *      Frees the memory associated with an interpreter snapshot taken by
00347  *      Tcl_SaveResult. If the snapshot is not restored, this function must be
00348  *      called to discard it, or the memory will be lost.
00349  *
00350  * Results:
00351  *      None.
00352  *
00353  * Side effects:
00354  *      None.
00355  *
00356  *----------------------------------------------------------------------
00357  */
00358 
00359 void
00360 Tcl_DiscardResult(
00361     Tcl_SavedResult *statePtr)  /* State returned by Tcl_SaveResult. */
00362 {
00363     TclDecrRefCount(statePtr->objResultPtr);
00364 
00365     if (statePtr->result == statePtr->appendResult) {
00366         ckfree(statePtr->appendResult);
00367     } else if (statePtr->freeProc) {
00368         if (statePtr->freeProc == TCL_DYNAMIC) {
00369             ckfree(statePtr->result);
00370         } else {
00371             (*statePtr->freeProc)(statePtr->result);
00372         }
00373     }
00374 }
00375 
00376 /*
00377  *----------------------------------------------------------------------
00378  *
00379  * Tcl_SetResult --
00380  *
00381  *      Arrange for "result" to be the Tcl return value.
00382  *
00383  * Results:
00384  *      None.
00385  *
00386  * Side effects:
00387  *      interp->result is left pointing either to "result" or to a copy of it.
00388  *      Also, the object result is reset.
00389  *
00390  *----------------------------------------------------------------------
00391  */
00392 
00393 void
00394 Tcl_SetResult(
00395     Tcl_Interp *interp,         /* Interpreter with which to associate the
00396                                  * return value. */
00397     register char *result,      /* Value to be returned. If NULL, the result
00398                                  * is set to an empty string. */
00399     Tcl_FreeProc *freeProc)     /* Gives information about the string:
00400                                  * TCL_STATIC, TCL_VOLATILE, or the address of
00401                                  * a Tcl_FreeProc such as free. */
00402 {
00403     Interp *iPtr = (Interp *) interp;
00404     int length;
00405     register Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
00406     char *oldResult = iPtr->result;
00407 
00408     if (result == NULL) {
00409         iPtr->resultSpace[0] = 0;
00410         iPtr->result = iPtr->resultSpace;
00411         iPtr->freeProc = 0;
00412     } else if (freeProc == TCL_VOLATILE) {
00413         length = strlen(result);
00414         if (length > TCL_RESULT_SIZE) {
00415             iPtr->result = (char *) ckalloc((unsigned) length+1);
00416             iPtr->freeProc = TCL_DYNAMIC;
00417         } else {
00418             iPtr->result = iPtr->resultSpace;
00419             iPtr->freeProc = 0;
00420         }
00421         strcpy(iPtr->result, result);
00422     } else {
00423         iPtr->result = result;
00424         iPtr->freeProc = freeProc;
00425     }
00426 
00427     /*
00428      * If the old result was dynamically-allocated, free it up. Do it here,
00429      * rather than at the beginning, in case the new result value was part of
00430      * the old result value.
00431      */
00432 
00433     if (oldFreeProc != 0) {
00434         if (oldFreeProc == TCL_DYNAMIC) {
00435             ckfree(oldResult);
00436         } else {
00437             (*oldFreeProc)(oldResult);
00438         }
00439     }
00440 
00441     /*
00442      * Reset the object result since we just set the string result.
00443      */
00444 
00445     ResetObjResult(iPtr);
00446 }
00447 
00448 /*
00449  *----------------------------------------------------------------------
00450  *
00451  * Tcl_GetStringResult --
00452  *
00453  *      Returns an interpreter's result value as a string.
00454  *
00455  * Results:
00456  *      The interpreter's result as a string.
00457  *
00458  * Side effects:
00459  *      If the string result is empty, the object result is moved to the
00460  *      string result, then the object result is reset.
00461  *
00462  *----------------------------------------------------------------------
00463  */
00464 
00465 CONST char *
00466 Tcl_GetStringResult(
00467     register Tcl_Interp *interp)/* Interpreter whose result to return. */
00468 {
00469     /*
00470      * If the string result is empty, move the object result to the string
00471      * result, then reset the object result.
00472      */
00473 
00474     if (*(interp->result) == 0) {
00475         Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
00476                 TCL_VOLATILE);
00477     }
00478     return interp->result;
00479 }
00480 
00481 /*
00482  *----------------------------------------------------------------------
00483  *
00484  * Tcl_SetObjResult --
00485  *
00486  *      Arrange for objPtr to be an interpreter's result value.
00487  *
00488  * Results:
00489  *      None.
00490  *
00491  * Side effects:
00492  *      interp->objResultPtr is left pointing to the object referenced by
00493  *      objPtr. The object's reference count is incremented since there is now
00494  *      a new reference to it. The reference count for any old objResultPtr
00495  *      value is decremented. Also, the string result is reset.
00496  *
00497  *----------------------------------------------------------------------
00498  */
00499 
00500 void
00501 Tcl_SetObjResult(
00502     Tcl_Interp *interp,         /* Interpreter with which to associate the
00503                                  * return object value. */
00504     register Tcl_Obj *objPtr)   /* Tcl object to be returned. If NULL, the obj
00505                                  * result is made an empty string object. */
00506 {
00507     register Interp *iPtr = (Interp *) interp;
00508     register Tcl_Obj *oldObjResult = iPtr->objResultPtr;
00509 
00510     iPtr->objResultPtr = objPtr;
00511     Tcl_IncrRefCount(objPtr);   /* since interp result is a reference */
00512 
00513     /*
00514      * We wait until the end to release the old object result, in case we are
00515      * setting the result to itself.
00516      */
00517 
00518     TclDecrRefCount(oldObjResult);
00519 
00520     /*
00521      * Reset the string result since we just set the result object.
00522      */
00523 
00524     if (iPtr->freeProc != NULL) {
00525         if (iPtr->freeProc == TCL_DYNAMIC) {
00526             ckfree(iPtr->result);
00527         } else {
00528             (*iPtr->freeProc)(iPtr->result);
00529         }
00530         iPtr->freeProc = 0;
00531     }
00532     iPtr->result = iPtr->resultSpace;
00533     iPtr->resultSpace[0] = 0;
00534 }
00535 
00536 /*
00537  *----------------------------------------------------------------------
00538  *
00539  * Tcl_GetObjResult --
00540  *
00541  *      Returns an interpreter's result value as a Tcl object. The object's
00542  *      reference count is not modified; the caller must do that if it needs
00543  *      to hold on to a long-term reference to it.
00544  *
00545  * Results:
00546  *      The interpreter's result as an object.
00547  *
00548  * Side effects:
00549  *      If the interpreter has a non-empty string result, the result object is
00550  *      either empty or stale because some function set interp->result
00551  *      directly. If so, the string result is moved to the result object then
00552  *      the string result is reset.
00553  *
00554  *----------------------------------------------------------------------
00555  */
00556 
00557 Tcl_Obj *
00558 Tcl_GetObjResult(
00559     Tcl_Interp *interp)         /* Interpreter whose result to return. */
00560 {
00561     register Interp *iPtr = (Interp *) interp;
00562     Tcl_Obj *objResultPtr;
00563     int length;
00564 
00565     /*
00566      * If the string result is non-empty, move the string result to the object
00567      * result, then reset the string result.
00568      */
00569 
00570     if (*(iPtr->result) != 0) {
00571         ResetObjResult(iPtr);
00572 
00573         objResultPtr = iPtr->objResultPtr;
00574         length = strlen(iPtr->result);
00575         TclInitStringRep(objResultPtr, iPtr->result, length);
00576 
00577         if (iPtr->freeProc != NULL) {
00578             if (iPtr->freeProc == TCL_DYNAMIC) {
00579                 ckfree(iPtr->result);
00580             } else {
00581                 (*iPtr->freeProc)(iPtr->result);
00582             }
00583             iPtr->freeProc = 0;
00584         }
00585         iPtr->result = iPtr->resultSpace;
00586         iPtr->resultSpace[0] = 0;
00587     }
00588     return iPtr->objResultPtr;
00589 }
00590 
00591 /*
00592  *----------------------------------------------------------------------
00593  *
00594  * Tcl_AppendResultVA --
00595  *
00596  *      Append a variable number of strings onto the interpreter's result.
00597  *
00598  * Results:
00599  *      None.
00600  *
00601  * Side effects:
00602  *      The result of the interpreter given by the first argument is extended
00603  *      by the strings in the va_list (up to a terminating NULL argument).
00604  *
00605  *      If the string result is non-empty, the object result forced to be a
00606  *      duplicate of it first. There will be a string result afterwards.
00607  *
00608  *----------------------------------------------------------------------
00609  */
00610 
00611 void
00612 Tcl_AppendResultVA(
00613     Tcl_Interp *interp,         /* Interpreter with which to associate the
00614                                  * return value. */
00615     va_list argList)            /* Variable argument list. */
00616 {
00617     Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
00618 
00619     if (Tcl_IsShared(objPtr)) {
00620         objPtr = Tcl_DuplicateObj(objPtr);
00621     }
00622     Tcl_AppendStringsToObjVA(objPtr, argList);
00623     Tcl_SetObjResult(interp, objPtr);
00624 
00625     /*
00626      * Strictly we should call Tcl_GetStringResult(interp) here to make sure
00627      * that interp->result is correct according to the old contract, but that
00628      * makes the performance of much code (e.g. in Tk) absolutely awful. So we
00629      * leave it out; code that really wants interp->result can just insert the
00630      * calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion]
00631      */
00632 
00633 #ifdef USE_DIRECT_INTERP_RESULT_ACCESS
00634     /*
00635      * Ensure that the interp->result is legal so old Tcl 7.* code still
00636      * works. There's still embarrasingly much of it about...
00637      */
00638 
00639     (void) Tcl_GetStringResult(interp);
00640 #endif /* USE_DIRECT_INTERP_RESULT_ACCESS */
00641 }
00642 
00643 /*
00644  *----------------------------------------------------------------------
00645  *
00646  * Tcl_AppendResult --
00647  *
00648  *      Append a variable number of strings onto the interpreter's result.
00649  *
00650  * Results:
00651  *      None.
00652  *
00653  * Side effects:
00654  *      The result of the interpreter given by the first argument is extended
00655  *      by the strings given by the second and following arguments (up to a
00656  *      terminating NULL argument).
00657  *
00658  *      If the string result is non-empty, the object result forced to be a
00659  *      duplicate of it first. There will be a string result afterwards.
00660  *
00661  *----------------------------------------------------------------------
00662  */
00663 
00664 void
00665 Tcl_AppendResult(
00666     Tcl_Interp *interp, ...)
00667 {
00668     va_list argList;
00669 
00670     va_start(argList, interp);
00671     Tcl_AppendResultVA(interp, argList);
00672     va_end(argList);
00673 }
00674 
00675 /*
00676  *----------------------------------------------------------------------
00677  *
00678  * Tcl_AppendElement --
00679  *
00680  *      Convert a string to a valid Tcl list element and append it to the
00681  *      result (which is ostensibly a list).
00682  *
00683  * Results:
00684  *      None.
00685  *
00686  * Side effects:
00687  *      The result in the interpreter given by the first argument is extended
00688  *      with a list element converted from string. A separator space is added
00689  *      before the converted list element unless the current result is empty,
00690  *      contains the single character "{", or ends in " {".
00691  *
00692  *      If the string result is empty, the object result is moved to the
00693  *      string result, then the object result is reset.
00694  *
00695  *----------------------------------------------------------------------
00696  */
00697 
00698 void
00699 Tcl_AppendElement(
00700     Tcl_Interp *interp,         /* Interpreter whose result is to be
00701                                  * extended. */
00702     CONST char *element)        /* String to convert to list element and add
00703                                  * to result. */
00704 {
00705     Interp *iPtr = (Interp *) interp;
00706     char *dst;
00707     int size;
00708     int flags;
00709 
00710     /*
00711      * If the string result is empty, move the object result to the string
00712      * result, then reset the object result.
00713      */
00714 
00715     (void) Tcl_GetStringResult(interp);
00716 
00717     /*
00718      * See how much space is needed, and grow the append buffer if needed to
00719      * accommodate the list element.
00720      */
00721 
00722     size = Tcl_ScanElement(element, &flags) + 1;
00723     if ((iPtr->result != iPtr->appendResult)
00724             || (iPtr->appendResult[iPtr->appendUsed] != 0)
00725             || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
00726         SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
00727     }
00728 
00729     /*
00730      * Convert the string into a list element and copy it to the buffer that's
00731      * forming, with a space separator if needed.
00732      */
00733 
00734     dst = iPtr->appendResult + iPtr->appendUsed;
00735     if (TclNeedSpace(iPtr->appendResult, dst)) {
00736         iPtr->appendUsed++;
00737         *dst = ' ';
00738         dst++;
00739 
00740         /*
00741          * If we need a space to separate this element from preceding stuff,
00742          * then this element will not lead a list, and need not have it's
00743          * leading '#' quoted.
00744          */
00745 
00746         flags |= TCL_DONT_QUOTE_HASH;
00747     }
00748     iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
00749 }
00750 
00751 /*
00752  *----------------------------------------------------------------------
00753  *
00754  * SetupAppendBuffer --
00755  *
00756  *      This function makes sure that there is an append buffer properly
00757  *      initialized, if necessary, from the interpreter's result, and that it
00758  *      has at least enough room to accommodate newSpace new bytes of
00759  *      information.
00760  *
00761  * Results:
00762  *      None.
00763  *
00764  * Side effects:
00765  *      None.
00766  *
00767  *----------------------------------------------------------------------
00768  */
00769 
00770 static void
00771 SetupAppendBuffer(
00772     Interp *iPtr,               /* Interpreter whose result is being set up. */
00773     int newSpace)               /* Make sure that at least this many bytes of
00774                                  * new information may be added. */
00775 {
00776     int totalSpace;
00777 
00778     /*
00779      * Make the append buffer larger, if that's necessary, then copy the
00780      * result into the append buffer and make the append buffer the official
00781      * Tcl result.
00782      */
00783 
00784     if (iPtr->result != iPtr->appendResult) {
00785         /*
00786          * If an oversized buffer was used recently, then free it up so we go
00787          * back to a smaller buffer. This avoids tying up memory forever after
00788          * a large operation.
00789          */
00790 
00791         if (iPtr->appendAvl > 500) {
00792             ckfree(iPtr->appendResult);
00793             iPtr->appendResult = NULL;
00794             iPtr->appendAvl = 0;
00795         }
00796         iPtr->appendUsed = strlen(iPtr->result);
00797     } else if (iPtr->result[iPtr->appendUsed] != 0) {
00798         /*
00799          * Most likely someone has modified a result created by
00800          * Tcl_AppendResult et al. so that it has a different size. Just
00801          * recompute the size.
00802          */
00803 
00804         iPtr->appendUsed = strlen(iPtr->result);
00805     }
00806 
00807     totalSpace = newSpace + iPtr->appendUsed;
00808     if (totalSpace >= iPtr->appendAvl) {
00809         char *new;
00810 
00811         if (totalSpace < 100) {
00812             totalSpace = 200;
00813         } else {
00814             totalSpace *= 2;
00815         }
00816         new = (char *) ckalloc((unsigned) totalSpace);
00817         strcpy(new, iPtr->result);
00818         if (iPtr->appendResult != NULL) {
00819             ckfree(iPtr->appendResult);
00820         }
00821         iPtr->appendResult = new;
00822         iPtr->appendAvl = totalSpace;
00823     } else if (iPtr->result != iPtr->appendResult) {
00824         strcpy(iPtr->appendResult, iPtr->result);
00825     }
00826 
00827     Tcl_FreeResult((Tcl_Interp *) iPtr);
00828     iPtr->result = iPtr->appendResult;
00829 }
00830 
00831 /*
00832  *----------------------------------------------------------------------
00833  *
00834  * Tcl_FreeResult --
00835  *
00836  *      This function frees up the memory associated with an interpreter's
00837  *      string result. It also resets the interpreter's result object.
00838  *      Tcl_FreeResult is most commonly used when a function is about to
00839  *      replace one result value with another.
00840  *
00841  * Results:
00842  *      None.
00843  *
00844  * Side effects:
00845  *      Frees the memory associated with interp's string result and sets
00846  *      interp->freeProc to zero, but does not change interp->result or clear
00847  *      error state. Resets interp's result object to an unshared empty
00848  *      object.
00849  *
00850  *----------------------------------------------------------------------
00851  */
00852 
00853 void
00854 Tcl_FreeResult(
00855     register Tcl_Interp *interp)/* Interpreter for which to free result. */
00856 {
00857     register Interp *iPtr = (Interp *) interp;
00858 
00859     if (iPtr->freeProc != NULL) {
00860         if (iPtr->freeProc == TCL_DYNAMIC) {
00861             ckfree(iPtr->result);
00862         } else {
00863             (*iPtr->freeProc)(iPtr->result);
00864         }
00865         iPtr->freeProc = 0;
00866     }
00867 
00868     ResetObjResult(iPtr);
00869 }
00870 
00871 /*
00872  *----------------------------------------------------------------------
00873  *
00874  * Tcl_ResetResult --
00875  *
00876  *      This function resets both the interpreter's string and object results.
00877  *
00878  * Results:
00879  *      None.
00880  *
00881  * Side effects:
00882  *      It resets the result object to an unshared empty object. It then
00883  *      restores the interpreter's string result area to its default
00884  *      initialized state, freeing up any memory that may have been allocated.
00885  *      It also clears any error information for the interpreter.
00886  *
00887  *----------------------------------------------------------------------
00888  */
00889 
00890 void
00891 Tcl_ResetResult(
00892     register Tcl_Interp *interp)/* Interpreter for which to clear result. */
00893 {
00894     register Interp *iPtr = (Interp *) interp;
00895 
00896     ResetObjResult(iPtr);
00897     if (iPtr->freeProc != NULL) {
00898         if (iPtr->freeProc == TCL_DYNAMIC) {
00899             ckfree(iPtr->result);
00900         } else {
00901             (*iPtr->freeProc)(iPtr->result);
00902         }
00903         iPtr->freeProc = 0;
00904     }
00905     iPtr->result = iPtr->resultSpace;
00906     iPtr->resultSpace[0] = 0;
00907     if (iPtr->errorCode) {
00908         /* Legacy support */
00909         if (iPtr->flags & ERR_LEGACY_COPY) {
00910             Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
00911                     iPtr->errorCode, TCL_GLOBAL_ONLY);
00912         }
00913         Tcl_DecrRefCount(iPtr->errorCode);
00914         iPtr->errorCode = NULL;
00915     }
00916     if (iPtr->errorInfo) {
00917         /* Legacy support */
00918         if (iPtr->flags & ERR_LEGACY_COPY) {
00919             Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
00920                     iPtr->errorInfo, TCL_GLOBAL_ONLY);
00921         }
00922         Tcl_DecrRefCount(iPtr->errorInfo);
00923         iPtr->errorInfo = NULL;
00924     }
00925     iPtr->returnLevel = 1;
00926     iPtr->returnCode = TCL_OK;
00927     if (iPtr->returnOpts) {
00928         Tcl_DecrRefCount(iPtr->returnOpts);
00929         iPtr->returnOpts = NULL;
00930     }
00931     iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_LEGACY_COPY);
00932 }
00933 
00934 /*
00935  *----------------------------------------------------------------------
00936  *
00937  * ResetObjResult --
00938  *
00939  *      Function used to reset an interpreter's Tcl result object.
00940  *
00941  * Results:
00942  *      None.
00943  *
00944  * Side effects:
00945  *      Resets the interpreter's result object to an unshared empty string
00946  *      object with ref count one. It does not clear any error information in
00947  *      the interpreter.
00948  *
00949  *----------------------------------------------------------------------
00950  */
00951 
00952 static void
00953 ResetObjResult(
00954     register Interp *iPtr)      /* Points to the interpreter whose result
00955                                  * object should be reset. */
00956 {
00957     register Tcl_Obj *objResultPtr = iPtr->objResultPtr;
00958 
00959     if (Tcl_IsShared(objResultPtr)) {
00960         TclDecrRefCount(objResultPtr);
00961         TclNewObj(objResultPtr);
00962         Tcl_IncrRefCount(objResultPtr);
00963         iPtr->objResultPtr = objResultPtr;
00964     } else if (objResultPtr->bytes != tclEmptyStringRep) {
00965         if (objResultPtr->bytes != NULL) {
00966             ckfree((char *) objResultPtr->bytes);
00967         }
00968         objResultPtr->bytes = tclEmptyStringRep;
00969         objResultPtr->length = 0;
00970         TclFreeIntRep(objResultPtr);
00971         objResultPtr->typePtr = NULL;
00972     }
00973 }
00974 
00975 /*
00976  *----------------------------------------------------------------------
00977  *
00978  * Tcl_SetErrorCodeVA --
00979  *
00980  *      This function is called to record machine-readable information about
00981  *      an error that is about to be returned.
00982  *
00983  * Results:
00984  *      None.
00985  *
00986  * Side effects:
00987  *      The errorCode field of the interp is modified to hold all of the
00988  *      arguments to this function, in a list form with each argument becoming
00989  *      one element of the list.
00990  *
00991  *----------------------------------------------------------------------
00992  */
00993 
00994 void
00995 Tcl_SetErrorCodeVA(
00996     Tcl_Interp *interp,         /* Interpreter in which to set errorCode */
00997     va_list argList)            /* Variable argument list. */
00998 {
00999     Tcl_Obj *errorObj = Tcl_NewObj();
01000 
01001     /*
01002      * Scan through the arguments one at a time, appending them to the
01003      * errorCode field as list elements.
01004      */
01005 
01006     while (1) {
01007         char *elem = va_arg(argList, char *);
01008         if (elem == NULL) {
01009             break;
01010         }
01011         Tcl_ListObjAppendElement(NULL, errorObj, Tcl_NewStringObj(elem, -1));
01012     }
01013     Tcl_SetObjErrorCode(interp, errorObj);
01014 }
01015 
01016 /*
01017  *----------------------------------------------------------------------
01018  *
01019  * Tcl_SetErrorCode --
01020  *
01021  *      This function is called to record machine-readable information about
01022  *      an error that is about to be returned.
01023  *
01024  * Results:
01025  *      None.
01026  *
01027  * Side effects:
01028  *      The errorCode field of the interp is modified to hold all of the
01029  *      arguments to this function, in a list form with each argument becoming
01030  *      one element of the list.
01031  *
01032  *----------------------------------------------------------------------
01033  */
01034 
01035 void
01036 Tcl_SetErrorCode(
01037     Tcl_Interp *interp, ...)
01038 {
01039     va_list argList;
01040 
01041     /*
01042      * Scan through the arguments one at a time, appending them to the
01043      * errorCode field as list elements.
01044      */
01045 
01046     va_start(argList, interp);
01047     Tcl_SetErrorCodeVA(interp, argList);
01048     va_end(argList);
01049 }
01050 
01051 /*
01052  *----------------------------------------------------------------------
01053  *
01054  * Tcl_SetObjErrorCode --
01055  *
01056  *      This function is called to record machine-readable information about
01057  *      an error that is about to be returned. The caller should build a list
01058  *      object up and pass it to this routine.
01059  *
01060  * Results:
01061  *      None.
01062  *
01063  * Side effects:
01064  *      The errorCode field of the interp is set to the new value.
01065  *
01066  *----------------------------------------------------------------------
01067  */
01068 
01069 void
01070 Tcl_SetObjErrorCode(
01071     Tcl_Interp *interp,
01072     Tcl_Obj *errorObjPtr)
01073 {
01074     Interp *iPtr = (Interp *) interp;
01075 
01076     if (iPtr->errorCode) {
01077         Tcl_DecrRefCount(iPtr->errorCode);
01078     }
01079     iPtr->errorCode = errorObjPtr;
01080     Tcl_IncrRefCount(iPtr->errorCode);
01081 }
01082 
01083 /*
01084  *----------------------------------------------------------------------
01085  *
01086  * GetKeys --
01087  *
01088  *      Returns a Tcl_Obj * array of the standard keys used in the return
01089  *      options dictionary.
01090  *
01091  *      Broadly sharing one copy of these key values helps with both memory
01092  *      efficiency and dictionary lookup times.
01093  *
01094  * Results:
01095  *      A Tcl_Obj * array.
01096  *
01097  * Side effects:
01098  *      First time called in a thread, creates the keys (allocating memory)
01099  *      and arranges for their cleanup at thread exit.
01100  *
01101  *----------------------------------------------------------------------
01102  */
01103 
01104 static Tcl_Obj **
01105 GetKeys(void)
01106 {
01107     static Tcl_ThreadDataKey returnKeysKey;
01108     Tcl_Obj **keys = Tcl_GetThreadData(&returnKeysKey,
01109             (int) (KEY_LAST * sizeof(Tcl_Obj *)));
01110 
01111     if (keys[0] == NULL) {
01112         /*
01113          * First call in this thread, create the keys...
01114          */
01115 
01116         int i;
01117 
01118         TclNewLiteralStringObj(keys[KEY_CODE],      "-code");
01119         TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode");
01120         TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo");
01121         TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline");
01122         TclNewLiteralStringObj(keys[KEY_LEVEL],     "-level");
01123         TclNewLiteralStringObj(keys[KEY_OPTIONS],   "-options");
01124 
01125         for (i = KEY_CODE; i < KEY_LAST; i++) {
01126             Tcl_IncrRefCount(keys[i]);
01127         }
01128 
01129         /*
01130          * ... and arrange for their clenaup.
01131          */
01132 
01133         Tcl_CreateThreadExitHandler(ReleaseKeys, (ClientData) keys);
01134     }
01135     return keys;
01136 }
01137 
01138 /*
01139  *----------------------------------------------------------------------
01140  *
01141  * ReleaseKeys --
01142  *
01143  *      Called as a thread exit handler to cleanup return options dictionary
01144  *      keys.
01145  *
01146  * Results:
01147  *      None.
01148  *
01149  * Side effects:
01150  *      Frees memory.
01151  *
01152  *----------------------------------------------------------------------
01153  */
01154 
01155 static void
01156 ReleaseKeys(
01157     ClientData clientData)
01158 {
01159     Tcl_Obj **keys = (Tcl_Obj **)clientData;
01160     int i;
01161 
01162     for (i = KEY_CODE; i < KEY_LAST; i++) {
01163         Tcl_DecrRefCount(keys[i]);
01164     }
01165 }
01166 
01167 /*
01168  *----------------------------------------------------------------------
01169  *
01170  * TclProcessReturn --
01171  *
01172  *      Does the work of the [return] command based on the code, level, and
01173  *      returnOpts arguments. Note that the code argument must agree with the
01174  *      -code entry in returnOpts and the level argument must agree with the
01175  *      -level entry in returnOpts, as is the case for values returned from
01176  *      TclMergeReturnOptions.
01177  *
01178  * Results:
01179  *      Returns the return code the [return] command should return.
01180  *
01181  * Side effects:
01182  *      None.
01183  *
01184  *----------------------------------------------------------------------
01185  */
01186 
01187 int
01188 TclProcessReturn(
01189     Tcl_Interp *interp,
01190     int code,
01191     int level,
01192     Tcl_Obj *returnOpts)
01193 {
01194     Interp *iPtr = (Interp *) interp;
01195     Tcl_Obj *valuePtr;
01196     Tcl_Obj **keys = GetKeys();
01197 
01198     /*
01199      * Store the merged return options.
01200      */
01201 
01202     if (iPtr->returnOpts != returnOpts) {
01203         if (iPtr->returnOpts) {
01204             Tcl_DecrRefCount(iPtr->returnOpts);
01205         }
01206         iPtr->returnOpts = returnOpts;
01207         Tcl_IncrRefCount(iPtr->returnOpts);
01208     }
01209 
01210     if (code == TCL_ERROR) {
01211         if (iPtr->errorInfo) {
01212             Tcl_DecrRefCount(iPtr->errorInfo);
01213             iPtr->errorInfo = NULL;
01214         }
01215         Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr);
01216         if (valuePtr != NULL) {
01217             int infoLen;
01218 
01219             (void) TclGetStringFromObj(valuePtr, &infoLen);
01220             if (infoLen) {
01221                 iPtr->errorInfo = valuePtr;
01222                 Tcl_IncrRefCount(iPtr->errorInfo);
01223                 iPtr->flags |= ERR_ALREADY_LOGGED;
01224             }
01225         }
01226         Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr);
01227         if (valuePtr != NULL) {
01228             Tcl_SetObjErrorCode(interp, valuePtr);
01229         } else {
01230             Tcl_SetErrorCode(interp, "NONE", NULL);
01231         }
01232 
01233         Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr);
01234         if (valuePtr != NULL) {
01235             TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
01236         }
01237     }
01238     if (level != 0) {
01239         iPtr->returnLevel = level;
01240         iPtr->returnCode = code;
01241         return TCL_RETURN;
01242     }
01243     if (code == TCL_ERROR) {
01244         iPtr->flags |= ERR_LEGACY_COPY;
01245     }
01246     return code;
01247 }
01248 
01249 /*
01250  *----------------------------------------------------------------------
01251  *
01252  * TclMergeReturnOptions --
01253  *
01254  *      Parses, checks, and stores the options to the [return] command.
01255  *
01256  * Results:
01257  *      Returns TCL_ERROR is any of the option values are invalid. Otherwise,
01258  *      returns TCL_OK, and writes the returnOpts, code, and level values to
01259  *      the pointers provided.
01260  *
01261  * Side effects:
01262  *      None.
01263  *
01264  *----------------------------------------------------------------------
01265  */
01266 
01267 int
01268 TclMergeReturnOptions(
01269     Tcl_Interp *interp,         /* Current interpreter. */
01270     int objc,                   /* Number of arguments. */
01271     Tcl_Obj *CONST objv[],      /* Argument objects. */
01272     Tcl_Obj **optionsPtrPtr,    /* If not NULL, points to space for a (Tcl_Obj
01273                                  * *) where the pointer to the merged return
01274                                  * options dictionary should be written */
01275     int *codePtr,               /* If not NULL, points to space where the
01276                                  * -code value should be written */
01277     int *levelPtr)              /* If not NULL, points to space where the
01278                                  * -level value should be written */
01279 {
01280     int code=TCL_OK;
01281     int level = 1;
01282     Tcl_Obj *valuePtr;
01283     Tcl_Obj *returnOpts = Tcl_NewObj();
01284     Tcl_Obj **keys = GetKeys();
01285 
01286     for (;  objc > 1;  objv += 2, objc -= 2) {
01287         int optLen;
01288         CONST char *opt = TclGetStringFromObj(objv[0], &optLen);
01289         int compareLen;
01290         CONST char *compare =
01291                 TclGetStringFromObj(keys[KEY_OPTIONS], &compareLen);
01292 
01293         if ((optLen == compareLen) && (strcmp(opt, compare) == 0)) {
01294             Tcl_DictSearch search;
01295             int done = 0;
01296             Tcl_Obj *keyPtr;
01297             Tcl_Obj *dict = objv[1];
01298 
01299         nestedOptions:
01300             if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search,
01301                     &keyPtr, &valuePtr, &done)) {
01302                 /*
01303                  * Value is not a legal dictionary.
01304                  */
01305 
01306                 Tcl_ResetResult(interp);
01307                 Tcl_AppendResult(interp, "bad ", compare,
01308                         " value: expected dictionary but got \"",
01309                         TclGetString(objv[1]), "\"", NULL);
01310                 goto error;
01311             }
01312 
01313             while (!done) {
01314                 Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
01315                 Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
01316             }
01317 
01318             Tcl_DictObjGet(NULL, returnOpts, keys[KEY_OPTIONS], &valuePtr);
01319             if (valuePtr != NULL) {
01320                 dict = valuePtr;
01321                 Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_OPTIONS]);
01322                 goto nestedOptions;
01323             }
01324 
01325         } else {
01326             Tcl_DictObjPut(NULL, returnOpts, objv[0], objv[1]);
01327         }
01328     }
01329 
01330     /*
01331      * Check for bogus -code value.
01332      */
01333 
01334     Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
01335     if ((valuePtr != NULL)
01336             && (TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &code))) {
01337         static CONST char *returnCodes[] = {
01338             "ok", "error", "return", "break", "continue", NULL
01339         };
01340 
01341         if (TCL_ERROR == Tcl_GetIndexFromObj(NULL, valuePtr, returnCodes,
01342                 NULL, TCL_EXACT, &code)) {
01343             /*
01344              * Value is not a legal return code.
01345              */
01346 
01347             Tcl_ResetResult(interp);
01348             Tcl_AppendResult(interp, "bad completion code \"",
01349                     TclGetString(valuePtr),
01350                     "\": must be ok, error, return, break, "
01351                     "continue, or an integer", NULL);
01352             goto error;
01353         }
01354     }
01355     if (valuePtr != NULL) {
01356         Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]);
01357     }
01358 
01359     /*
01360      * Check for bogus -level value.
01361      */
01362 
01363     Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr);
01364     if (valuePtr != NULL) {
01365         if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level))
01366                 || (level < 0)) {
01367             /*
01368              * Value is not a legal level.
01369              */
01370 
01371             Tcl_ResetResult(interp);
01372             Tcl_AppendResult(interp, "bad -level value: "
01373                     "expected non-negative integer but got \"",
01374                     TclGetString(valuePtr), "\"", NULL);
01375             goto error;
01376         }
01377         Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]);
01378     }
01379 
01380     /*
01381      * Convert [return -code return -level X] to [return -code ok -level X+1]
01382      */
01383 
01384     if (code == TCL_RETURN) {
01385         level++;
01386         code = TCL_OK;
01387     }
01388 
01389     if (codePtr != NULL) {
01390         *codePtr = code;
01391     }
01392     if (levelPtr != NULL) {
01393         *levelPtr = level;
01394     }
01395 
01396     if (optionsPtrPtr == NULL) {
01397         /*
01398          * Not passing back the options (?!), so clean them up.
01399          */
01400 
01401         Tcl_DecrRefCount(returnOpts);
01402     } else {
01403         *optionsPtrPtr = returnOpts;
01404     }
01405     return TCL_OK;
01406 
01407   error:
01408     Tcl_DecrRefCount(returnOpts);
01409     return TCL_ERROR;
01410 }
01411 
01412 /*
01413  *-------------------------------------------------------------------------
01414  *
01415  * Tcl_GetReturnOptions --
01416  *
01417  *      Packs up the interp state into a dictionary of return options.
01418  *
01419  * Results:
01420  *      A dictionary of return options.
01421  *
01422  * Side effects:
01423  *      None.
01424  *
01425  *-------------------------------------------------------------------------
01426  */
01427 
01428 Tcl_Obj *
01429 Tcl_GetReturnOptions(
01430     Tcl_Interp *interp,
01431     int result)
01432 {
01433     Interp *iPtr = (Interp *) interp;
01434     Tcl_Obj *options;
01435     Tcl_Obj **keys = GetKeys();
01436 
01437     if (iPtr->returnOpts) {
01438         options = Tcl_DuplicateObj(iPtr->returnOpts);
01439     } else {
01440         options = Tcl_NewObj();
01441     }
01442 
01443     if (result == TCL_RETURN) {
01444         Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
01445                 Tcl_NewIntObj(iPtr->returnCode));
01446         Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
01447                 Tcl_NewIntObj(iPtr->returnLevel));
01448     } else {
01449         Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
01450                 Tcl_NewIntObj(result));
01451         Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
01452                 Tcl_NewIntObj(0));
01453     }
01454 
01455     if (result == TCL_ERROR) {
01456         Tcl_AddObjErrorInfo(interp, "", -1);
01457     }
01458     if (iPtr->errorCode) {
01459         Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode);
01460     }
01461     if (iPtr->errorInfo) {
01462         Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo);
01463         Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
01464                 Tcl_NewIntObj(iPtr->errorLine));
01465     }
01466     return options;
01467 }
01468 
01469 /*
01470  *-------------------------------------------------------------------------
01471  *
01472  * Tcl_SetReturnOptions --
01473  *
01474  *      Accepts an interp and a dictionary of return options, and sets the
01475  *      return options of the interp to match the dictionary.
01476  *
01477  * Results:
01478  *      A standard status code. Usually TCL_OK, but TCL_ERROR if an invalid
01479  *      option value was found in the dictionary. If a -level value of 0 is in
01480  *      the dictionary, then the -code value in the dictionary will be
01481  *      returned (TCL_OK default).
01482  *
01483  * Side effects:
01484  *      Sets the state of the interp.
01485  *
01486  *-------------------------------------------------------------------------
01487  */
01488 
01489 int
01490 Tcl_SetReturnOptions(
01491     Tcl_Interp *interp,
01492     Tcl_Obj *options)
01493 {
01494     int objc, level, code;
01495     Tcl_Obj **objv, *mergedOpts;
01496 
01497     if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
01498             || (objc % 2)) {
01499         Tcl_ResetResult(interp);
01500         Tcl_AppendResult(interp, "expected dict but got \"",
01501                 TclGetString(options), "\"", NULL);
01502         code = TCL_ERROR;
01503     } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
01504             &mergedOpts, &code, &level)) {
01505         code = TCL_ERROR;
01506     } else {
01507         code = TclProcessReturn(interp, code, level, mergedOpts);
01508     }
01509 
01510     Tcl_DecrRefCount(options);
01511     return code;
01512 }
01513 
01514 /*
01515  *-------------------------------------------------------------------------
01516  *
01517  * TclTransferResult --
01518  *
01519  *      Copy the result (and error information) from one interp to another.
01520  *      Used when one interp has caused another interp to evaluate a script
01521  *      and then wants to transfer the results back to itself.
01522  *
01523  *      This routine copies the string reps of the result and error
01524  *      information. It does not simply increment the refcounts of the result
01525  *      and error information objects themselves. It is not legal to exchange
01526  *      objects between interps, because an object may be kept alive by one
01527  *      interp, but have an internal rep that is only valid while some other
01528  *      interp is alive.
01529  *
01530  * Results:
01531  *      The target interp's result is set to a copy of the source interp's
01532  *      result. The source's errorInfo field may be transferred to the
01533  *      target's errorInfo field, and the source's errorCode field may be
01534  *      transferred to the target's errorCode field.
01535  *
01536  * Side effects:
01537  *      None.
01538  *
01539  *-------------------------------------------------------------------------
01540  */
01541 
01542 void
01543 TclTransferResult(
01544     Tcl_Interp *sourceInterp,   /* Interp whose result and error information
01545                                  * should be moved to the target interp.
01546                                  * After moving result, this interp's result
01547                                  * is reset. */
01548     int result,                 /* TCL_OK if just the result should be copied,
01549                                  * TCL_ERROR if both the result and error
01550                                  * information should be copied. */
01551     Tcl_Interp *targetInterp)   /* Interp where result and error information
01552                                  * should be stored. If source and target are
01553                                  * the same, nothing is done. */
01554 {
01555     Interp *tiPtr = (Interp *) targetInterp;
01556     Interp *siPtr = (Interp *) sourceInterp;
01557 
01558     if (sourceInterp == targetInterp) {
01559         return;
01560     }
01561 
01562     if (result == TCL_OK && siPtr->returnOpts == NULL) {
01563         /*
01564          * Special optimization for the common case of normal command return
01565          * code and no explicit return options.
01566          */
01567 
01568         if (tiPtr->returnOpts) {
01569             Tcl_DecrRefCount(tiPtr->returnOpts);
01570             tiPtr->returnOpts = NULL;
01571         }
01572     } else {
01573         Tcl_SetReturnOptions(targetInterp,
01574                 Tcl_GetReturnOptions(sourceInterp, result));
01575         tiPtr->flags &= ~(ERR_ALREADY_LOGGED);
01576     }
01577     Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp));
01578     Tcl_ResetResult(sourceInterp);
01579 }
01580 
01581 /*
01582  * Local Variables:
01583  * mode: c
01584  * c-basic-offset: 4
01585  * fill-column: 78
01586  * End:
01587  */



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