Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/generic/tclResult.c @ 64

Last change on this file since 64 was 25, checked in by landauf, 16 years ago

added tcl to libs

File size: 41.0 KB
Line 
1/*
2 * tclResult.c --
3 *
4 *      This file contains code to manage the interpreter result.
5 *
6 * Copyright (c) 1997 by Sun Microsystems, Inc.
7 *
8 * See the file "license.terms" for information on usage and redistribution of
9 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
10 *
11 * RCS: @(#) $Id: tclResult.c,v 1.47 2008/03/07 22:42:49 andreas_kupries Exp $
12 */
13
14#include "tclInt.h"
15
16/*
17 * Indices of the standard return options dictionary keys.
18 */
19
20enum returnKeys {
21    KEY_CODE,   KEY_ERRORCODE,  KEY_ERRORINFO,  KEY_ERRORLINE,
22    KEY_LEVEL,  KEY_OPTIONS,    KEY_LAST
23};
24
25/*
26 * Function prototypes for local functions in this file:
27 */
28
29static Tcl_Obj **       GetKeys(void);
30static void             ReleaseKeys(ClientData clientData);
31static void             ResetObjResult(Interp *iPtr);
32static void             SetupAppendBuffer(Interp *iPtr, int newSpace);
33
34/*
35 * This structure is used to take a snapshot of the interpreter state in
36 * Tcl_SaveInterpState. You can snapshot the state, execute a command, and
37 * then back up to the result or the error that was previously in progress.
38 */
39
40typedef struct InterpState {
41    int status;                 /* return code status */
42    int flags;                  /* Each remaining field saves the */
43    int returnLevel;            /* corresponding field of the Interp */
44    int returnCode;             /* struct. These fields taken together are */
45    Tcl_Obj *errorInfo;         /* the "state" of the interp. */
46    Tcl_Obj *errorCode;
47    Tcl_Obj *returnOpts;
48    Tcl_Obj *objResult;
49} InterpState;
50
51/*
52 *----------------------------------------------------------------------
53 *
54 * Tcl_SaveInterpState --
55 *
56 *      Fills a token with a snapshot of the current state of the interpreter.
57 *      The snapshot can be restored at any point by TclRestoreInterpState.
58 *
59 *      The token returned must be eventally passed to one of the routines
60 *      TclRestoreInterpState or TclDiscardInterpState, or there will be a
61 *      memory leak.
62 *
63 * Results:
64 *      Returns a token representing the interp state.
65 *
66 * Side effects:
67 *      None.
68 *
69 *----------------------------------------------------------------------
70 */
71
72Tcl_InterpState
73Tcl_SaveInterpState(
74    Tcl_Interp *interp,         /* Interpreter's state to be saved */
75    int status)                 /* status code for current operation */
76{
77    Interp *iPtr = (Interp *)interp;
78    InterpState *statePtr = (InterpState *)ckalloc(sizeof(InterpState));
79
80    statePtr->status = status;
81    statePtr->flags = iPtr->flags & ERR_ALREADY_LOGGED;
82    statePtr->returnLevel = iPtr->returnLevel;
83    statePtr->returnCode = iPtr->returnCode;
84    statePtr->errorInfo = iPtr->errorInfo;
85    if (statePtr->errorInfo) {
86        Tcl_IncrRefCount(statePtr->errorInfo);
87    }
88    statePtr->errorCode = iPtr->errorCode;
89    if (statePtr->errorCode) {
90        Tcl_IncrRefCount(statePtr->errorCode);
91    }
92    statePtr->returnOpts = iPtr->returnOpts;
93    if (statePtr->returnOpts) {
94        Tcl_IncrRefCount(statePtr->returnOpts);
95    }
96    statePtr->objResult = Tcl_GetObjResult(interp);
97    Tcl_IncrRefCount(statePtr->objResult);
98    return (Tcl_InterpState) statePtr;
99}
100
101/*
102 *----------------------------------------------------------------------
103 *
104 * Tcl_RestoreInterpState --
105 *
106 *      Accepts an interp and a token previously returned by
107 *      Tcl_SaveInterpState. Restore the state of the interp to what it was at
108 *      the time of the Tcl_SaveInterpState call.
109 *
110 * Results:
111 *      Returns the status value originally passed in to Tcl_SaveInterpState.
112 *
113 * Side effects:
114 *      Restores the interp state and frees memory held by token.
115 *
116 *----------------------------------------------------------------------
117 */
118
119int
120Tcl_RestoreInterpState(
121    Tcl_Interp *interp,         /* Interpreter's state to be restored. */
122    Tcl_InterpState state)      /* Saved interpreter state. */
123{
124    Interp *iPtr = (Interp *)interp;
125    InterpState *statePtr = (InterpState *)state;
126    int status = statePtr->status;
127
128    iPtr->flags &= ~ERR_ALREADY_LOGGED;
129    iPtr->flags |= (statePtr->flags & ERR_ALREADY_LOGGED);
130
131    iPtr->returnLevel = statePtr->returnLevel;
132    iPtr->returnCode = statePtr->returnCode;
133    if (iPtr->errorInfo) {
134        Tcl_DecrRefCount(iPtr->errorInfo);
135    }
136    iPtr->errorInfo = statePtr->errorInfo;
137    if (iPtr->errorInfo) {
138        Tcl_IncrRefCount(iPtr->errorInfo);
139    }
140    if (iPtr->errorCode) {
141        Tcl_DecrRefCount(iPtr->errorCode);
142    }
143    iPtr->errorCode = statePtr->errorCode;
144    if (iPtr->errorCode) {
145        Tcl_IncrRefCount(iPtr->errorCode);
146    }
147    if (iPtr->returnOpts) {
148        Tcl_DecrRefCount(iPtr->returnOpts);
149    }
150    iPtr->returnOpts = statePtr->returnOpts;
151    if (iPtr->returnOpts) {
152        Tcl_IncrRefCount(iPtr->returnOpts);
153    }
154    Tcl_SetObjResult(interp, statePtr->objResult);
155    Tcl_DiscardInterpState(state);
156    return status;
157}
158
159/*
160 *----------------------------------------------------------------------
161 *
162 * Tcl_DiscardInterpState --
163 *
164 *      Accepts a token previously returned by Tcl_SaveInterpState. Frees the
165 *      memory it uses.
166 *
167 * Results:
168 *      None.
169 *
170 * Side effects:
171 *      Frees memory.
172 *
173 *----------------------------------------------------------------------
174 */
175
176void
177Tcl_DiscardInterpState(
178    Tcl_InterpState state)      /* saved interpreter state */
179{
180    InterpState *statePtr = (InterpState *)state;
181
182    if (statePtr->errorInfo) {
183        Tcl_DecrRefCount(statePtr->errorInfo);
184    }
185    if (statePtr->errorCode) {
186        Tcl_DecrRefCount(statePtr->errorCode);
187    }
188    if (statePtr->returnOpts) {
189        Tcl_DecrRefCount(statePtr->returnOpts);
190    }
191    Tcl_DecrRefCount(statePtr->objResult);
192    ckfree((char *) statePtr);
193}
194
195/*
196 *----------------------------------------------------------------------
197 *
198 * Tcl_SaveResult --
199 *
200 *      Takes a snapshot of the current result state of the interpreter. The
201 *      snapshot can be restored at any point by Tcl_RestoreResult. Note that
202 *      this routine does not preserve the errorCode, errorInfo, or flags
203 *      fields so it should not be used if an error is in progress.
204 *
205 *      Once a snapshot is saved, it must be restored by calling
206 *      Tcl_RestoreResult, or discarded by calling Tcl_DiscardResult.
207 *
208 * Results:
209 *      None.
210 *
211 * Side effects:
212 *      Resets the interpreter result.
213 *
214 *----------------------------------------------------------------------
215 */
216
217void
218Tcl_SaveResult(
219    Tcl_Interp *interp,         /* Interpreter to save. */
220    Tcl_SavedResult *statePtr)  /* Pointer to state structure. */
221{
222    Interp *iPtr = (Interp *) interp;
223
224    /*
225     * Move the result object into the save state. Note that we don't need to
226     * change its refcount because we're moving it, not adding a new
227     * reference. Put an empty object into the interpreter.
228     */
229
230    statePtr->objResultPtr = iPtr->objResultPtr;
231    iPtr->objResultPtr = Tcl_NewObj();
232    Tcl_IncrRefCount(iPtr->objResultPtr);
233
234    /*
235     * Save the string result.
236     */
237
238    statePtr->freeProc = iPtr->freeProc;
239    if (iPtr->result == iPtr->resultSpace) {
240        /*
241         * Copy the static string data out of the interp buffer.
242         */
243
244        statePtr->result = statePtr->resultSpace;
245        strcpy(statePtr->result, iPtr->result);
246        statePtr->appendResult = NULL;
247    } else if (iPtr->result == iPtr->appendResult) {
248        /*
249         * Move the append buffer out of the interp.
250         */
251
252        statePtr->appendResult = iPtr->appendResult;
253        statePtr->appendAvl = iPtr->appendAvl;
254        statePtr->appendUsed = iPtr->appendUsed;
255        statePtr->result = statePtr->appendResult;
256        iPtr->appendResult = NULL;
257        iPtr->appendAvl = 0;
258        iPtr->appendUsed = 0;
259    } else {
260        /*
261         * Move the dynamic or static string out of the interpreter.
262         */
263
264        statePtr->result = iPtr->result;
265        statePtr->appendResult = NULL;
266    }
267
268    iPtr->result = iPtr->resultSpace;
269    iPtr->resultSpace[0] = 0;
270    iPtr->freeProc = 0;
271}
272
273/*
274 *----------------------------------------------------------------------
275 *
276 * Tcl_RestoreResult --
277 *
278 *      Restores the state of the interpreter to a snapshot taken by
279 *      Tcl_SaveResult. After this call, the token for the interpreter state
280 *      is no longer valid.
281 *
282 * Results:
283 *      None.
284 *
285 * Side effects:
286 *      Restores the interpreter result.
287 *
288 *----------------------------------------------------------------------
289 */
290
291void
292Tcl_RestoreResult(
293    Tcl_Interp *interp,         /* Interpreter being restored. */
294    Tcl_SavedResult *statePtr)  /* State returned by Tcl_SaveResult. */
295{
296    Interp *iPtr = (Interp *) interp;
297
298    Tcl_ResetResult(interp);
299
300    /*
301     * Restore the string result.
302     */
303
304    iPtr->freeProc = statePtr->freeProc;
305    if (statePtr->result == statePtr->resultSpace) {
306        /*
307         * Copy the static string data into the interp buffer.
308         */
309
310        iPtr->result = iPtr->resultSpace;
311        strcpy(iPtr->result, statePtr->result);
312    } else if (statePtr->result == statePtr->appendResult) {
313        /*
314         * Move the append buffer back into the interp.
315         */
316
317        if (iPtr->appendResult != NULL) {
318            ckfree((char *) iPtr->appendResult);
319        }
320
321        iPtr->appendResult = statePtr->appendResult;
322        iPtr->appendAvl = statePtr->appendAvl;
323        iPtr->appendUsed = statePtr->appendUsed;
324        iPtr->result = iPtr->appendResult;
325    } else {
326        /*
327         * Move the dynamic or static string back into the interpreter.
328         */
329
330        iPtr->result = statePtr->result;
331    }
332
333    /*
334     * Restore the object result.
335     */
336
337    Tcl_DecrRefCount(iPtr->objResultPtr);
338    iPtr->objResultPtr = statePtr->objResultPtr;
339}
340
341/*
342 *----------------------------------------------------------------------
343 *
344 * Tcl_DiscardResult --
345 *
346 *      Frees the memory associated with an interpreter snapshot taken by
347 *      Tcl_SaveResult. If the snapshot is not restored, this function must be
348 *      called to discard it, or the memory will be lost.
349 *
350 * Results:
351 *      None.
352 *
353 * Side effects:
354 *      None.
355 *
356 *----------------------------------------------------------------------
357 */
358
359void
360Tcl_DiscardResult(
361    Tcl_SavedResult *statePtr)  /* State returned by Tcl_SaveResult. */
362{
363    TclDecrRefCount(statePtr->objResultPtr);
364
365    if (statePtr->result == statePtr->appendResult) {
366        ckfree(statePtr->appendResult);
367    } else if (statePtr->freeProc) {
368        if (statePtr->freeProc == TCL_DYNAMIC) {
369            ckfree(statePtr->result);
370        } else {
371            (*statePtr->freeProc)(statePtr->result);
372        }
373    }
374}
375
376/*
377 *----------------------------------------------------------------------
378 *
379 * Tcl_SetResult --
380 *
381 *      Arrange for "result" to be the Tcl return value.
382 *
383 * Results:
384 *      None.
385 *
386 * Side effects:
387 *      interp->result is left pointing either to "result" or to a copy of it.
388 *      Also, the object result is reset.
389 *
390 *----------------------------------------------------------------------
391 */
392
393void
394Tcl_SetResult(
395    Tcl_Interp *interp,         /* Interpreter with which to associate the
396                                 * return value. */
397    register char *result,      /* Value to be returned. If NULL, the result
398                                 * is set to an empty string. */
399    Tcl_FreeProc *freeProc)     /* Gives information about the string:
400                                 * TCL_STATIC, TCL_VOLATILE, or the address of
401                                 * a Tcl_FreeProc such as free. */
402{
403    Interp *iPtr = (Interp *) interp;
404    int length;
405    register Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
406    char *oldResult = iPtr->result;
407
408    if (result == NULL) {
409        iPtr->resultSpace[0] = 0;
410        iPtr->result = iPtr->resultSpace;
411        iPtr->freeProc = 0;
412    } else if (freeProc == TCL_VOLATILE) {
413        length = strlen(result);
414        if (length > TCL_RESULT_SIZE) {
415            iPtr->result = (char *) ckalloc((unsigned) length+1);
416            iPtr->freeProc = TCL_DYNAMIC;
417        } else {
418            iPtr->result = iPtr->resultSpace;
419            iPtr->freeProc = 0;
420        }
421        strcpy(iPtr->result, result);
422    } else {
423        iPtr->result = result;
424        iPtr->freeProc = freeProc;
425    }
426
427    /*
428     * If the old result was dynamically-allocated, free it up. Do it here,
429     * rather than at the beginning, in case the new result value was part of
430     * the old result value.
431     */
432
433    if (oldFreeProc != 0) {
434        if (oldFreeProc == TCL_DYNAMIC) {
435            ckfree(oldResult);
436        } else {
437            (*oldFreeProc)(oldResult);
438        }
439    }
440
441    /*
442     * Reset the object result since we just set the string result.
443     */
444
445    ResetObjResult(iPtr);
446}
447
448/*
449 *----------------------------------------------------------------------
450 *
451 * Tcl_GetStringResult --
452 *
453 *      Returns an interpreter's result value as a string.
454 *
455 * Results:
456 *      The interpreter's result as a string.
457 *
458 * Side effects:
459 *      If the string result is empty, the object result is moved to the
460 *      string result, then the object result is reset.
461 *
462 *----------------------------------------------------------------------
463 */
464
465CONST char *
466Tcl_GetStringResult(
467    register Tcl_Interp *interp)/* Interpreter whose result to return. */
468{
469    /*
470     * If the string result is empty, move the object result to the string
471     * result, then reset the object result.
472     */
473
474    if (*(interp->result) == 0) {
475        Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
476                TCL_VOLATILE);
477    }
478    return interp->result;
479}
480
481/*
482 *----------------------------------------------------------------------
483 *
484 * Tcl_SetObjResult --
485 *
486 *      Arrange for objPtr to be an interpreter's result value.
487 *
488 * Results:
489 *      None.
490 *
491 * Side effects:
492 *      interp->objResultPtr is left pointing to the object referenced by
493 *      objPtr. The object's reference count is incremented since there is now
494 *      a new reference to it. The reference count for any old objResultPtr
495 *      value is decremented. Also, the string result is reset.
496 *
497 *----------------------------------------------------------------------
498 */
499
500void
501Tcl_SetObjResult(
502    Tcl_Interp *interp,         /* Interpreter with which to associate the
503                                 * return object value. */
504    register Tcl_Obj *objPtr)   /* Tcl object to be returned. If NULL, the obj
505                                 * result is made an empty string object. */
506{
507    register Interp *iPtr = (Interp *) interp;
508    register Tcl_Obj *oldObjResult = iPtr->objResultPtr;
509
510    iPtr->objResultPtr = objPtr;
511    Tcl_IncrRefCount(objPtr);   /* since interp result is a reference */
512
513    /*
514     * We wait until the end to release the old object result, in case we are
515     * setting the result to itself.
516     */
517
518    TclDecrRefCount(oldObjResult);
519
520    /*
521     * Reset the string result since we just set the result object.
522     */
523
524    if (iPtr->freeProc != NULL) {
525        if (iPtr->freeProc == TCL_DYNAMIC) {
526            ckfree(iPtr->result);
527        } else {
528            (*iPtr->freeProc)(iPtr->result);
529        }
530        iPtr->freeProc = 0;
531    }
532    iPtr->result = iPtr->resultSpace;
533    iPtr->resultSpace[0] = 0;
534}
535
536/*
537 *----------------------------------------------------------------------
538 *
539 * Tcl_GetObjResult --
540 *
541 *      Returns an interpreter's result value as a Tcl object. The object's
542 *      reference count is not modified; the caller must do that if it needs
543 *      to hold on to a long-term reference to it.
544 *
545 * Results:
546 *      The interpreter's result as an object.
547 *
548 * Side effects:
549 *      If the interpreter has a non-empty string result, the result object is
550 *      either empty or stale because some function set interp->result
551 *      directly. If so, the string result is moved to the result object then
552 *      the string result is reset.
553 *
554 *----------------------------------------------------------------------
555 */
556
557Tcl_Obj *
558Tcl_GetObjResult(
559    Tcl_Interp *interp)         /* Interpreter whose result to return. */
560{
561    register Interp *iPtr = (Interp *) interp;
562    Tcl_Obj *objResultPtr;
563    int length;
564
565    /*
566     * If the string result is non-empty, move the string result to the object
567     * result, then reset the string result.
568     */
569
570    if (*(iPtr->result) != 0) {
571        ResetObjResult(iPtr);
572
573        objResultPtr = iPtr->objResultPtr;
574        length = strlen(iPtr->result);
575        TclInitStringRep(objResultPtr, iPtr->result, length);
576
577        if (iPtr->freeProc != NULL) {
578            if (iPtr->freeProc == TCL_DYNAMIC) {
579                ckfree(iPtr->result);
580            } else {
581                (*iPtr->freeProc)(iPtr->result);
582            }
583            iPtr->freeProc = 0;
584        }
585        iPtr->result = iPtr->resultSpace;
586        iPtr->resultSpace[0] = 0;
587    }
588    return iPtr->objResultPtr;
589}
590
591/*
592 *----------------------------------------------------------------------
593 *
594 * Tcl_AppendResultVA --
595 *
596 *      Append a variable number of strings onto the interpreter's result.
597 *
598 * Results:
599 *      None.
600 *
601 * Side effects:
602 *      The result of the interpreter given by the first argument is extended
603 *      by the strings in the va_list (up to a terminating NULL argument).
604 *
605 *      If the string result is non-empty, the object result forced to be a
606 *      duplicate of it first. There will be a string result afterwards.
607 *
608 *----------------------------------------------------------------------
609 */
610
611void
612Tcl_AppendResultVA(
613    Tcl_Interp *interp,         /* Interpreter with which to associate the
614                                 * return value. */
615    va_list argList)            /* Variable argument list. */
616{
617    Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
618
619    if (Tcl_IsShared(objPtr)) {
620        objPtr = Tcl_DuplicateObj(objPtr);
621    }
622    Tcl_AppendStringsToObjVA(objPtr, argList);
623    Tcl_SetObjResult(interp, objPtr);
624
625    /*
626     * Strictly we should call Tcl_GetStringResult(interp) here to make sure
627     * that interp->result is correct according to the old contract, but that
628     * makes the performance of much code (e.g. in Tk) absolutely awful. So we
629     * leave it out; code that really wants interp->result can just insert the
630     * calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion]
631     */
632
633#ifdef USE_DIRECT_INTERP_RESULT_ACCESS
634    /*
635     * Ensure that the interp->result is legal so old Tcl 7.* code still
636     * works. There's still embarrasingly much of it about...
637     */
638
639    (void) Tcl_GetStringResult(interp);
640#endif /* USE_DIRECT_INTERP_RESULT_ACCESS */
641}
642
643/*
644 *----------------------------------------------------------------------
645 *
646 * Tcl_AppendResult --
647 *
648 *      Append a variable number of strings onto the interpreter's result.
649 *
650 * Results:
651 *      None.
652 *
653 * Side effects:
654 *      The result of the interpreter given by the first argument is extended
655 *      by the strings given by the second and following arguments (up to a
656 *      terminating NULL argument).
657 *
658 *      If the string result is non-empty, the object result forced to be a
659 *      duplicate of it first. There will be a string result afterwards.
660 *
661 *----------------------------------------------------------------------
662 */
663
664void
665Tcl_AppendResult(
666    Tcl_Interp *interp, ...)
667{
668    va_list argList;
669
670    va_start(argList, interp);
671    Tcl_AppendResultVA(interp, argList);
672    va_end(argList);
673}
674
675/*
676 *----------------------------------------------------------------------
677 *
678 * Tcl_AppendElement --
679 *
680 *      Convert a string to a valid Tcl list element and append it to the
681 *      result (which is ostensibly a list).
682 *
683 * Results:
684 *      None.
685 *
686 * Side effects:
687 *      The result in the interpreter given by the first argument is extended
688 *      with a list element converted from string. A separator space is added
689 *      before the converted list element unless the current result is empty,
690 *      contains the single character "{", or ends in " {".
691 *
692 *      If the string result is empty, the object result is moved to the
693 *      string result, then the object result is reset.
694 *
695 *----------------------------------------------------------------------
696 */
697
698void
699Tcl_AppendElement(
700    Tcl_Interp *interp,         /* Interpreter whose result is to be
701                                 * extended. */
702    CONST char *element)        /* String to convert to list element and add
703                                 * to result. */
704{
705    Interp *iPtr = (Interp *) interp;
706    char *dst;
707    int size;
708    int flags;
709
710    /*
711     * If the string result is empty, move the object result to the string
712     * result, then reset the object result.
713     */
714
715    (void) Tcl_GetStringResult(interp);
716
717    /*
718     * See how much space is needed, and grow the append buffer if needed to
719     * accommodate the list element.
720     */
721
722    size = Tcl_ScanElement(element, &flags) + 1;
723    if ((iPtr->result != iPtr->appendResult)
724            || (iPtr->appendResult[iPtr->appendUsed] != 0)
725            || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
726        SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
727    }
728
729    /*
730     * Convert the string into a list element and copy it to the buffer that's
731     * forming, with a space separator if needed.
732     */
733
734    dst = iPtr->appendResult + iPtr->appendUsed;
735    if (TclNeedSpace(iPtr->appendResult, dst)) {
736        iPtr->appendUsed++;
737        *dst = ' ';
738        dst++;
739
740        /*
741         * If we need a space to separate this element from preceding stuff,
742         * then this element will not lead a list, and need not have it's
743         * leading '#' quoted.
744         */
745
746        flags |= TCL_DONT_QUOTE_HASH;
747    }
748    iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
749}
750
751/*
752 *----------------------------------------------------------------------
753 *
754 * SetupAppendBuffer --
755 *
756 *      This function makes sure that there is an append buffer properly
757 *      initialized, if necessary, from the interpreter's result, and that it
758 *      has at least enough room to accommodate newSpace new bytes of
759 *      information.
760 *
761 * Results:
762 *      None.
763 *
764 * Side effects:
765 *      None.
766 *
767 *----------------------------------------------------------------------
768 */
769
770static void
771SetupAppendBuffer(
772    Interp *iPtr,               /* Interpreter whose result is being set up. */
773    int newSpace)               /* Make sure that at least this many bytes of
774                                 * new information may be added. */
775{
776    int totalSpace;
777
778    /*
779     * Make the append buffer larger, if that's necessary, then copy the
780     * result into the append buffer and make the append buffer the official
781     * Tcl result.
782     */
783
784    if (iPtr->result != iPtr->appendResult) {
785        /*
786         * If an oversized buffer was used recently, then free it up so we go
787         * back to a smaller buffer. This avoids tying up memory forever after
788         * a large operation.
789         */
790
791        if (iPtr->appendAvl > 500) {
792            ckfree(iPtr->appendResult);
793            iPtr->appendResult = NULL;
794            iPtr->appendAvl = 0;
795        }
796        iPtr->appendUsed = strlen(iPtr->result);
797    } else if (iPtr->result[iPtr->appendUsed] != 0) {
798        /*
799         * Most likely someone has modified a result created by
800         * Tcl_AppendResult et al. so that it has a different size. Just
801         * recompute the size.
802         */
803
804        iPtr->appendUsed = strlen(iPtr->result);
805    }
806
807    totalSpace = newSpace + iPtr->appendUsed;
808    if (totalSpace >= iPtr->appendAvl) {
809        char *new;
810
811        if (totalSpace < 100) {
812            totalSpace = 200;
813        } else {
814            totalSpace *= 2;
815        }
816        new = (char *) ckalloc((unsigned) totalSpace);
817        strcpy(new, iPtr->result);
818        if (iPtr->appendResult != NULL) {
819            ckfree(iPtr->appendResult);
820        }
821        iPtr->appendResult = new;
822        iPtr->appendAvl = totalSpace;
823    } else if (iPtr->result != iPtr->appendResult) {
824        strcpy(iPtr->appendResult, iPtr->result);
825    }
826
827    Tcl_FreeResult((Tcl_Interp *) iPtr);
828    iPtr->result = iPtr->appendResult;
829}
830
831/*
832 *----------------------------------------------------------------------
833 *
834 * Tcl_FreeResult --
835 *
836 *      This function frees up the memory associated with an interpreter's
837 *      string result. It also resets the interpreter's result object.
838 *      Tcl_FreeResult is most commonly used when a function is about to
839 *      replace one result value with another.
840 *
841 * Results:
842 *      None.
843 *
844 * Side effects:
845 *      Frees the memory associated with interp's string result and sets
846 *      interp->freeProc to zero, but does not change interp->result or clear
847 *      error state. Resets interp's result object to an unshared empty
848 *      object.
849 *
850 *----------------------------------------------------------------------
851 */
852
853void
854Tcl_FreeResult(
855    register Tcl_Interp *interp)/* Interpreter for which to free result. */
856{
857    register Interp *iPtr = (Interp *) interp;
858
859    if (iPtr->freeProc != NULL) {
860        if (iPtr->freeProc == TCL_DYNAMIC) {
861            ckfree(iPtr->result);
862        } else {
863            (*iPtr->freeProc)(iPtr->result);
864        }
865        iPtr->freeProc = 0;
866    }
867
868    ResetObjResult(iPtr);
869}
870
871/*
872 *----------------------------------------------------------------------
873 *
874 * Tcl_ResetResult --
875 *
876 *      This function resets both the interpreter's string and object results.
877 *
878 * Results:
879 *      None.
880 *
881 * Side effects:
882 *      It resets the result object to an unshared empty object. It then
883 *      restores the interpreter's string result area to its default
884 *      initialized state, freeing up any memory that may have been allocated.
885 *      It also clears any error information for the interpreter.
886 *
887 *----------------------------------------------------------------------
888 */
889
890void
891Tcl_ResetResult(
892    register Tcl_Interp *interp)/* Interpreter for which to clear result. */
893{
894    register Interp *iPtr = (Interp *) interp;
895
896    ResetObjResult(iPtr);
897    if (iPtr->freeProc != NULL) {
898        if (iPtr->freeProc == TCL_DYNAMIC) {
899            ckfree(iPtr->result);
900        } else {
901            (*iPtr->freeProc)(iPtr->result);
902        }
903        iPtr->freeProc = 0;
904    }
905    iPtr->result = iPtr->resultSpace;
906    iPtr->resultSpace[0] = 0;
907    if (iPtr->errorCode) {
908        /* Legacy support */
909        if (iPtr->flags & ERR_LEGACY_COPY) {
910            Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
911                    iPtr->errorCode, TCL_GLOBAL_ONLY);
912        }
913        Tcl_DecrRefCount(iPtr->errorCode);
914        iPtr->errorCode = NULL;
915    }
916    if (iPtr->errorInfo) {
917        /* Legacy support */
918        if (iPtr->flags & ERR_LEGACY_COPY) {
919            Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
920                    iPtr->errorInfo, TCL_GLOBAL_ONLY);
921        }
922        Tcl_DecrRefCount(iPtr->errorInfo);
923        iPtr->errorInfo = NULL;
924    }
925    iPtr->returnLevel = 1;
926    iPtr->returnCode = TCL_OK;
927    if (iPtr->returnOpts) {
928        Tcl_DecrRefCount(iPtr->returnOpts);
929        iPtr->returnOpts = NULL;
930    }
931    iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_LEGACY_COPY);
932}
933
934/*
935 *----------------------------------------------------------------------
936 *
937 * ResetObjResult --
938 *
939 *      Function used to reset an interpreter's Tcl result object.
940 *
941 * Results:
942 *      None.
943 *
944 * Side effects:
945 *      Resets the interpreter's result object to an unshared empty string
946 *      object with ref count one. It does not clear any error information in
947 *      the interpreter.
948 *
949 *----------------------------------------------------------------------
950 */
951
952static void
953ResetObjResult(
954    register Interp *iPtr)      /* Points to the interpreter whose result
955                                 * object should be reset. */
956{
957    register Tcl_Obj *objResultPtr = iPtr->objResultPtr;
958
959    if (Tcl_IsShared(objResultPtr)) {
960        TclDecrRefCount(objResultPtr);
961        TclNewObj(objResultPtr);
962        Tcl_IncrRefCount(objResultPtr);
963        iPtr->objResultPtr = objResultPtr;
964    } else if (objResultPtr->bytes != tclEmptyStringRep) {
965        if (objResultPtr->bytes != NULL) {
966            ckfree((char *) objResultPtr->bytes);
967        }
968        objResultPtr->bytes = tclEmptyStringRep;
969        objResultPtr->length = 0;
970        TclFreeIntRep(objResultPtr);
971        objResultPtr->typePtr = NULL;
972    }
973}
974
975/*
976 *----------------------------------------------------------------------
977 *
978 * Tcl_SetErrorCodeVA --
979 *
980 *      This function is called to record machine-readable information about
981 *      an error that is about to be returned.
982 *
983 * Results:
984 *      None.
985 *
986 * Side effects:
987 *      The errorCode field of the interp is modified to hold all of the
988 *      arguments to this function, in a list form with each argument becoming
989 *      one element of the list.
990 *
991 *----------------------------------------------------------------------
992 */
993
994void
995Tcl_SetErrorCodeVA(
996    Tcl_Interp *interp,         /* Interpreter in which to set errorCode */
997    va_list argList)            /* Variable argument list. */
998{
999    Tcl_Obj *errorObj = Tcl_NewObj();
1000
1001    /*
1002     * Scan through the arguments one at a time, appending them to the
1003     * errorCode field as list elements.
1004     */
1005
1006    while (1) {
1007        char *elem = va_arg(argList, char *);
1008        if (elem == NULL) {
1009            break;
1010        }
1011        Tcl_ListObjAppendElement(NULL, errorObj, Tcl_NewStringObj(elem, -1));
1012    }
1013    Tcl_SetObjErrorCode(interp, errorObj);
1014}
1015
1016/*
1017 *----------------------------------------------------------------------
1018 *
1019 * Tcl_SetErrorCode --
1020 *
1021 *      This function is called to record machine-readable information about
1022 *      an error that is about to be returned.
1023 *
1024 * Results:
1025 *      None.
1026 *
1027 * Side effects:
1028 *      The errorCode field of the interp is modified to hold all of the
1029 *      arguments to this function, in a list form with each argument becoming
1030 *      one element of the list.
1031 *
1032 *----------------------------------------------------------------------
1033 */
1034
1035void
1036Tcl_SetErrorCode(
1037    Tcl_Interp *interp, ...)
1038{
1039    va_list argList;
1040
1041    /*
1042     * Scan through the arguments one at a time, appending them to the
1043     * errorCode field as list elements.
1044     */
1045
1046    va_start(argList, interp);
1047    Tcl_SetErrorCodeVA(interp, argList);
1048    va_end(argList);
1049}
1050
1051/*
1052 *----------------------------------------------------------------------
1053 *
1054 * Tcl_SetObjErrorCode --
1055 *
1056 *      This function is called to record machine-readable information about
1057 *      an error that is about to be returned. The caller should build a list
1058 *      object up and pass it to this routine.
1059 *
1060 * Results:
1061 *      None.
1062 *
1063 * Side effects:
1064 *      The errorCode field of the interp is set to the new value.
1065 *
1066 *----------------------------------------------------------------------
1067 */
1068
1069void
1070Tcl_SetObjErrorCode(
1071    Tcl_Interp *interp,
1072    Tcl_Obj *errorObjPtr)
1073{
1074    Interp *iPtr = (Interp *) interp;
1075
1076    if (iPtr->errorCode) {
1077        Tcl_DecrRefCount(iPtr->errorCode);
1078    }
1079    iPtr->errorCode = errorObjPtr;
1080    Tcl_IncrRefCount(iPtr->errorCode);
1081}
1082
1083/*
1084 *----------------------------------------------------------------------
1085 *
1086 * GetKeys --
1087 *
1088 *      Returns a Tcl_Obj * array of the standard keys used in the return
1089 *      options dictionary.
1090 *
1091 *      Broadly sharing one copy of these key values helps with both memory
1092 *      efficiency and dictionary lookup times.
1093 *
1094 * Results:
1095 *      A Tcl_Obj * array.
1096 *
1097 * Side effects:
1098 *      First time called in a thread, creates the keys (allocating memory)
1099 *      and arranges for their cleanup at thread exit.
1100 *
1101 *----------------------------------------------------------------------
1102 */
1103
1104static Tcl_Obj **
1105GetKeys(void)
1106{
1107    static Tcl_ThreadDataKey returnKeysKey;
1108    Tcl_Obj **keys = Tcl_GetThreadData(&returnKeysKey,
1109            (int) (KEY_LAST * sizeof(Tcl_Obj *)));
1110
1111    if (keys[0] == NULL) {
1112        /*
1113         * First call in this thread, create the keys...
1114         */
1115
1116        int i;
1117
1118        TclNewLiteralStringObj(keys[KEY_CODE],      "-code");
1119        TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode");
1120        TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo");
1121        TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline");
1122        TclNewLiteralStringObj(keys[KEY_LEVEL],     "-level");
1123        TclNewLiteralStringObj(keys[KEY_OPTIONS],   "-options");
1124
1125        for (i = KEY_CODE; i < KEY_LAST; i++) {
1126            Tcl_IncrRefCount(keys[i]);
1127        }
1128
1129        /*
1130         * ... and arrange for their clenaup.
1131         */
1132
1133        Tcl_CreateThreadExitHandler(ReleaseKeys, (ClientData) keys);
1134    }
1135    return keys;
1136}
1137
1138/*
1139 *----------------------------------------------------------------------
1140 *
1141 * ReleaseKeys --
1142 *
1143 *      Called as a thread exit handler to cleanup return options dictionary
1144 *      keys.
1145 *
1146 * Results:
1147 *      None.
1148 *
1149 * Side effects:
1150 *      Frees memory.
1151 *
1152 *----------------------------------------------------------------------
1153 */
1154
1155static void
1156ReleaseKeys(
1157    ClientData clientData)
1158{
1159    Tcl_Obj **keys = (Tcl_Obj **)clientData;
1160    int i;
1161
1162    for (i = KEY_CODE; i < KEY_LAST; i++) {
1163        Tcl_DecrRefCount(keys[i]);
1164        keys[i] = NULL;
1165    }
1166}
1167
1168/*
1169 *----------------------------------------------------------------------
1170 *
1171 * TclProcessReturn --
1172 *
1173 *      Does the work of the [return] command based on the code, level, and
1174 *      returnOpts arguments. Note that the code argument must agree with the
1175 *      -code entry in returnOpts and the level argument must agree with the
1176 *      -level entry in returnOpts, as is the case for values returned from
1177 *      TclMergeReturnOptions.
1178 *
1179 * Results:
1180 *      Returns the return code the [return] command should return.
1181 *
1182 * Side effects:
1183 *      None.
1184 *
1185 *----------------------------------------------------------------------
1186 */
1187
1188int
1189TclProcessReturn(
1190    Tcl_Interp *interp,
1191    int code,
1192    int level,
1193    Tcl_Obj *returnOpts)
1194{
1195    Interp *iPtr = (Interp *) interp;
1196    Tcl_Obj *valuePtr;
1197    Tcl_Obj **keys = GetKeys();
1198
1199    /*
1200     * Store the merged return options.
1201     */
1202
1203    if (iPtr->returnOpts != returnOpts) {
1204        if (iPtr->returnOpts) {
1205            Tcl_DecrRefCount(iPtr->returnOpts);
1206        }
1207        iPtr->returnOpts = returnOpts;
1208        Tcl_IncrRefCount(iPtr->returnOpts);
1209    }
1210
1211    if (code == TCL_ERROR) {
1212        if (iPtr->errorInfo) {
1213            Tcl_DecrRefCount(iPtr->errorInfo);
1214            iPtr->errorInfo = NULL;
1215        }
1216        Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr);
1217        if (valuePtr != NULL) {
1218            int infoLen;
1219
1220            (void) TclGetStringFromObj(valuePtr, &infoLen);
1221            if (infoLen) {
1222                iPtr->errorInfo = valuePtr;
1223                Tcl_IncrRefCount(iPtr->errorInfo);
1224                iPtr->flags |= ERR_ALREADY_LOGGED;
1225            }
1226        }
1227        Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr);
1228        if (valuePtr != NULL) {
1229            Tcl_SetObjErrorCode(interp, valuePtr);
1230        } else {
1231            Tcl_SetErrorCode(interp, "NONE", NULL);
1232        }
1233
1234        Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr);
1235        if (valuePtr != NULL) {
1236            TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
1237        }
1238    }
1239    if (level != 0) {
1240        iPtr->returnLevel = level;
1241        iPtr->returnCode = code;
1242        return TCL_RETURN;
1243    }
1244    if (code == TCL_ERROR) {
1245        iPtr->flags |= ERR_LEGACY_COPY;
1246    }
1247    return code;
1248}
1249
1250/*
1251 *----------------------------------------------------------------------
1252 *
1253 * TclMergeReturnOptions --
1254 *
1255 *      Parses, checks, and stores the options to the [return] command.
1256 *
1257 * Results:
1258 *      Returns TCL_ERROR is any of the option values are invalid. Otherwise,
1259 *      returns TCL_OK, and writes the returnOpts, code, and level values to
1260 *      the pointers provided.
1261 *
1262 * Side effects:
1263 *      None.
1264 *
1265 *----------------------------------------------------------------------
1266 */
1267
1268int
1269TclMergeReturnOptions(
1270    Tcl_Interp *interp,         /* Current interpreter. */
1271    int objc,                   /* Number of arguments. */
1272    Tcl_Obj *CONST objv[],      /* Argument objects. */
1273    Tcl_Obj **optionsPtrPtr,    /* If not NULL, points to space for a (Tcl_Obj
1274                                 * *) where the pointer to the merged return
1275                                 * options dictionary should be written */
1276    int *codePtr,               /* If not NULL, points to space where the
1277                                 * -code value should be written */
1278    int *levelPtr)              /* If not NULL, points to space where the
1279                                 * -level value should be written */
1280{
1281    int code=TCL_OK;
1282    int level = 1;
1283    Tcl_Obj *valuePtr;
1284    Tcl_Obj *returnOpts = Tcl_NewObj();
1285    Tcl_Obj **keys = GetKeys();
1286
1287    for (;  objc > 1;  objv += 2, objc -= 2) {
1288        int optLen;
1289        CONST char *opt = TclGetStringFromObj(objv[0], &optLen);
1290        int compareLen;
1291        CONST char *compare =
1292                TclGetStringFromObj(keys[KEY_OPTIONS], &compareLen);
1293
1294        if ((optLen == compareLen) && (strcmp(opt, compare) == 0)) {
1295            Tcl_DictSearch search;
1296            int done = 0;
1297            Tcl_Obj *keyPtr;
1298            Tcl_Obj *dict = objv[1];
1299
1300        nestedOptions:
1301            if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search,
1302                    &keyPtr, &valuePtr, &done)) {
1303                /*
1304                 * Value is not a legal dictionary.
1305                 */
1306
1307                Tcl_ResetResult(interp);
1308                Tcl_AppendResult(interp, "bad ", compare,
1309                        " value: expected dictionary but got \"",
1310                        TclGetString(objv[1]), "\"", NULL);
1311                goto error;
1312            }
1313
1314            while (!done) {
1315                Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
1316                Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
1317            }
1318
1319            Tcl_DictObjGet(NULL, returnOpts, keys[KEY_OPTIONS], &valuePtr);
1320            if (valuePtr != NULL) {
1321                dict = valuePtr;
1322                Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_OPTIONS]);
1323                goto nestedOptions;
1324            }
1325
1326        } else {
1327            Tcl_DictObjPut(NULL, returnOpts, objv[0], objv[1]);
1328        }
1329    }
1330
1331    /*
1332     * Check for bogus -code value.
1333     */
1334
1335    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
1336    if ((valuePtr != NULL)
1337            && (TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &code))) {
1338        static CONST char *returnCodes[] = {
1339            "ok", "error", "return", "break", "continue", NULL
1340        };
1341
1342        if (TCL_ERROR == Tcl_GetIndexFromObj(NULL, valuePtr, returnCodes,
1343                NULL, TCL_EXACT, &code)) {
1344            /*
1345             * Value is not a legal return code.
1346             */
1347
1348            Tcl_ResetResult(interp);
1349            Tcl_AppendResult(interp, "bad completion code \"",
1350                    TclGetString(valuePtr),
1351                    "\": must be ok, error, return, break, "
1352                    "continue, or an integer", NULL);
1353            goto error;
1354        }
1355    }
1356    if (valuePtr != NULL) {
1357        Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]);
1358    }
1359
1360    /*
1361     * Check for bogus -level value.
1362     */
1363
1364    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr);
1365    if (valuePtr != NULL) {
1366        if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level))
1367                || (level < 0)) {
1368            /*
1369             * Value is not a legal level.
1370             */
1371
1372            Tcl_ResetResult(interp);
1373            Tcl_AppendResult(interp, "bad -level value: "
1374                    "expected non-negative integer but got \"",
1375                    TclGetString(valuePtr), "\"", NULL);
1376            goto error;
1377        }
1378        Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]);
1379    }
1380
1381    /*
1382     * Convert [return -code return -level X] to [return -code ok -level X+1]
1383     */
1384
1385    if (code == TCL_RETURN) {
1386        level++;
1387        code = TCL_OK;
1388    }
1389
1390    if (codePtr != NULL) {
1391        *codePtr = code;
1392    }
1393    if (levelPtr != NULL) {
1394        *levelPtr = level;
1395    }
1396
1397    if (optionsPtrPtr == NULL) {
1398        /*
1399         * Not passing back the options (?!), so clean them up.
1400         */
1401
1402        Tcl_DecrRefCount(returnOpts);
1403    } else {
1404        *optionsPtrPtr = returnOpts;
1405    }
1406    return TCL_OK;
1407
1408  error:
1409    Tcl_DecrRefCount(returnOpts);
1410    return TCL_ERROR;
1411}
1412
1413/*
1414 *-------------------------------------------------------------------------
1415 *
1416 * Tcl_GetReturnOptions --
1417 *
1418 *      Packs up the interp state into a dictionary of return options.
1419 *
1420 * Results:
1421 *      A dictionary of return options.
1422 *
1423 * Side effects:
1424 *      None.
1425 *
1426 *-------------------------------------------------------------------------
1427 */
1428
1429Tcl_Obj *
1430Tcl_GetReturnOptions(
1431    Tcl_Interp *interp,
1432    int result)
1433{
1434    Interp *iPtr = (Interp *) interp;
1435    Tcl_Obj *options;
1436    Tcl_Obj **keys = GetKeys();
1437
1438    if (iPtr->returnOpts) {
1439        options = Tcl_DuplicateObj(iPtr->returnOpts);
1440    } else {
1441        options = Tcl_NewObj();
1442    }
1443
1444    if (result == TCL_RETURN) {
1445        Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
1446                Tcl_NewIntObj(iPtr->returnCode));
1447        Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
1448                Tcl_NewIntObj(iPtr->returnLevel));
1449    } else {
1450        Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
1451                Tcl_NewIntObj(result));
1452        Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
1453                Tcl_NewIntObj(0));
1454    }
1455
1456    if (result == TCL_ERROR) {
1457        Tcl_AddObjErrorInfo(interp, "", -1);
1458    }
1459    if (iPtr->errorCode) {
1460        Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode);
1461    }
1462    if (iPtr->errorInfo) {
1463        Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo);
1464        Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
1465                Tcl_NewIntObj(iPtr->errorLine));
1466    }
1467    return options;
1468}
1469
1470/*
1471 *-------------------------------------------------------------------------
1472 *
1473 * Tcl_SetReturnOptions --
1474 *
1475 *      Accepts an interp and a dictionary of return options, and sets the
1476 *      return options of the interp to match the dictionary.
1477 *
1478 * Results:
1479 *      A standard status code. Usually TCL_OK, but TCL_ERROR if an invalid
1480 *      option value was found in the dictionary. If a -level value of 0 is in
1481 *      the dictionary, then the -code value in the dictionary will be
1482 *      returned (TCL_OK default).
1483 *
1484 * Side effects:
1485 *      Sets the state of the interp.
1486 *
1487 *-------------------------------------------------------------------------
1488 */
1489
1490int
1491Tcl_SetReturnOptions(
1492    Tcl_Interp *interp,
1493    Tcl_Obj *options)
1494{
1495    int objc, level, code;
1496    Tcl_Obj **objv, *mergedOpts;
1497
1498    Tcl_IncrRefCount(options);
1499    if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
1500            || (objc % 2)) {
1501        Tcl_ResetResult(interp);
1502        Tcl_AppendResult(interp, "expected dict but got \"",
1503                TclGetString(options), "\"", NULL);
1504        code = TCL_ERROR;
1505    } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
1506            &mergedOpts, &code, &level)) {
1507        code = TCL_ERROR;
1508    } else {
1509        code = TclProcessReturn(interp, code, level, mergedOpts);
1510    }
1511
1512    Tcl_DecrRefCount(options);
1513    return code;
1514}
1515
1516/*
1517 *-------------------------------------------------------------------------
1518 *
1519 * TclTransferResult --
1520 *
1521 *      Copy the result (and error information) from one interp to another.
1522 *      Used when one interp has caused another interp to evaluate a script
1523 *      and then wants to transfer the results back to itself.
1524 *
1525 *      This routine copies the string reps of the result and error
1526 *      information. It does not simply increment the refcounts of the result
1527 *      and error information objects themselves. It is not legal to exchange
1528 *      objects between interps, because an object may be kept alive by one
1529 *      interp, but have an internal rep that is only valid while some other
1530 *      interp is alive.
1531 *
1532 * Results:
1533 *      The target interp's result is set to a copy of the source interp's
1534 *      result. The source's errorInfo field may be transferred to the
1535 *      target's errorInfo field, and the source's errorCode field may be
1536 *      transferred to the target's errorCode field.
1537 *
1538 * Side effects:
1539 *      None.
1540 *
1541 *-------------------------------------------------------------------------
1542 */
1543
1544void
1545TclTransferResult(
1546    Tcl_Interp *sourceInterp,   /* Interp whose result and error information
1547                                 * should be moved to the target interp.
1548                                 * After moving result, this interp's result
1549                                 * is reset. */
1550    int result,                 /* TCL_OK if just the result should be copied,
1551                                 * TCL_ERROR if both the result and error
1552                                 * information should be copied. */
1553    Tcl_Interp *targetInterp)   /* Interp where result and error information
1554                                 * should be stored. If source and target are
1555                                 * the same, nothing is done. */
1556{
1557    Interp *tiPtr = (Interp *) targetInterp;
1558    Interp *siPtr = (Interp *) sourceInterp;
1559
1560    if (sourceInterp == targetInterp) {
1561        return;
1562    }
1563
1564    if (result == TCL_OK && siPtr->returnOpts == NULL) {
1565        /*
1566         * Special optimization for the common case of normal command return
1567         * code and no explicit return options.
1568         */
1569
1570        if (tiPtr->returnOpts) {
1571            Tcl_DecrRefCount(tiPtr->returnOpts);
1572            tiPtr->returnOpts = NULL;
1573        }
1574    } else {
1575        Tcl_SetReturnOptions(targetInterp,
1576                Tcl_GetReturnOptions(sourceInterp, result));
1577        tiPtr->flags &= ~(ERR_ALREADY_LOGGED);
1578    }
1579    Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp));
1580    Tcl_ResetResult(sourceInterp);
1581}
1582
1583/*
1584 * Local Variables:
1585 * mode: c
1586 * c-basic-offset: 4
1587 * fill-column: 78
1588 * End:
1589 */
Note: See TracBrowser for help on using the repository browser.