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

Diff of /projs/ets/trunk/src/c_tcl_base_7_5_w_mods/tclresult.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.66  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25