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