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