/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclresult.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclresult.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25