tclResult.cGo to the documentation of this file.00001 /* 00002 * tclResult.c -- 00003 * 00004 * This file contains code to manage the interpreter result. 00005 * 00006 * Copyright (c) 1997 by Sun Microsystems, Inc. 00007 * 00008 * See the file "license.terms" for information on usage and redistribution of 00009 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 00010 * 00011 * RCS: @(#) $Id: tclResult.c,v 1.45 2007/12/13 15:23:20 dgp Exp $ 00012 */ 00013 00014 #include "tclInt.h" 00015 00016 /* 00017 * Indices of the standard return options dictionary keys. 00018 */ 00019 00020 enum returnKeys { 00021 KEY_CODE, KEY_ERRORCODE, KEY_ERRORINFO, KEY_ERRORLINE, 00022 KEY_LEVEL, KEY_OPTIONS, KEY_LAST 00023 }; 00024 00025 /* 00026 * Function prototypes for local functions in this file: 00027 */ 00028 00029 static Tcl_Obj ** GetKeys(void); 00030 static void ReleaseKeys(ClientData clientData); 00031 static void ResetObjResult(Interp *iPtr); 00032 static void SetupAppendBuffer(Interp *iPtr, int newSpace); 00033 00034 /* 00035 * This structure is used to take a snapshot of the interpreter state in 00036 * Tcl_SaveInterpState. You can snapshot the state, execute a command, and 00037 * then back up to the result or the error that was previously in progress. 00038 */ 00039 00040 typedef struct InterpState { 00041 int status; /* return code status */ 00042 int flags; /* Each remaining field saves the */ 00043 int returnLevel; /* corresponding field of the Interp */ 00044 int returnCode; /* struct. These fields taken together are */ 00045 Tcl_Obj *errorInfo; /* the "state" of the interp. */ 00046 Tcl_Obj *errorCode; 00047 Tcl_Obj *returnOpts; 00048 Tcl_Obj *objResult; 00049 } InterpState; 00050 00051 /* 00052 *---------------------------------------------------------------------- 00053 * 00054 * Tcl_SaveInterpState -- 00055 * 00056 * Fills a token with a snapshot of the current state of the interpreter. 00057 * The snapshot can be restored at any point by TclRestoreInterpState. 00058 * 00059 * The token returned must be eventally passed to one of the routines 00060 * TclRestoreInterpState or TclDiscardInterpState, or there will be a 00061 * memory leak. 00062 * 00063 * Results: 00064 * Returns a token representing the interp state. 00065 * 00066 * Side effects: 00067 * None. 00068 * 00069 *---------------------------------------------------------------------- 00070 */ 00071 00072 Tcl_InterpState 00073 Tcl_SaveInterpState( 00074 Tcl_Interp *interp, /* Interpreter's state to be saved */ 00075 int status) /* status code for current operation */ 00076 { 00077 Interp *iPtr = (Interp *)interp; 00078 InterpState *statePtr = (InterpState *)ckalloc(sizeof(InterpState)); 00079 00080 statePtr->status = status; 00081 statePtr->flags = iPtr->flags & ERR_ALREADY_LOGGED; 00082 statePtr->returnLevel = iPtr->returnLevel; 00083 statePtr->returnCode = iPtr->returnCode; 00084 statePtr->errorInfo = iPtr->errorInfo; 00085 if (statePtr->errorInfo) { 00086 Tcl_IncrRefCount(statePtr->errorInfo); 00087 } 00088 statePtr->errorCode = iPtr->errorCode; 00089 if (statePtr->errorCode) { 00090 Tcl_IncrRefCount(statePtr->errorCode); 00091 } 00092 statePtr->returnOpts = iPtr->returnOpts; 00093 if (statePtr->returnOpts) { 00094 Tcl_IncrRefCount(statePtr->returnOpts); 00095 } 00096 statePtr->objResult = Tcl_GetObjResult(interp); 00097 Tcl_IncrRefCount(statePtr->objResult); 00098 return (Tcl_InterpState) statePtr; 00099 } 00100 00101 /* 00102 *---------------------------------------------------------------------- 00103 * 00104 * Tcl_RestoreInterpState -- 00105 * 00106 * Accepts an interp and a token previously returned by 00107 * Tcl_SaveInterpState. Restore the state of the interp to what it was at 00108 * the time of the Tcl_SaveInterpState call. 00109 * 00110 * Results: 00111 * Returns the status value originally passed in to Tcl_SaveInterpState. 00112 * 00113 * Side effects: 00114 * Restores the interp state and frees memory held by token. 00115 * 00116 *---------------------------------------------------------------------- 00117 */ 00118 00119 int 00120 Tcl_RestoreInterpState( 00121 Tcl_Interp *interp, /* Interpreter's state to be restored. */ 00122 Tcl_InterpState state) /* Saved interpreter state. */ 00123 { 00124 Interp *iPtr = (Interp *)interp; 00125 InterpState *statePtr = (InterpState *)state; 00126 int status = statePtr->status; 00127 00128 iPtr->flags &= ~ERR_ALREADY_LOGGED; 00129 iPtr->flags |= (statePtr->flags & ERR_ALREADY_LOGGED); 00130 00131 iPtr->returnLevel = statePtr->returnLevel; 00132 iPtr->returnCode = statePtr->returnCode; 00133 if (iPtr->errorInfo) { 00134 Tcl_DecrRefCount(iPtr->errorInfo); 00135 } 00136 iPtr->errorInfo = statePtr->errorInfo; 00137 if (iPtr->errorInfo) { 00138 Tcl_IncrRefCount(iPtr->errorInfo); 00139 } 00140 if (iPtr->errorCode) { 00141 Tcl_DecrRefCount(iPtr->errorCode); 00142 } 00143 iPtr->errorCode = statePtr->errorCode; 00144 if (iPtr->errorCode) { 00145 Tcl_IncrRefCount(iPtr->errorCode); 00146 } 00147 if (iPtr->returnOpts) { 00148 Tcl_DecrRefCount(iPtr->returnOpts); 00149 } 00150 iPtr->returnOpts = statePtr->returnOpts; 00151 if (iPtr->returnOpts) { 00152 Tcl_IncrRefCount(iPtr->returnOpts); 00153 } 00154 Tcl_SetObjResult(interp, statePtr->objResult); 00155 Tcl_DiscardInterpState(state); 00156 return status; 00157 } 00158 00159 /* 00160 *---------------------------------------------------------------------- 00161 * 00162 * Tcl_DiscardInterpState -- 00163 * 00164 * Accepts a token previously returned by Tcl_SaveInterpState. Frees the 00165 * memory it uses. 00166 * 00167 * Results: 00168 * None. 00169 * 00170 * Side effects: 00171 * Frees memory. 00172 * 00173 *---------------------------------------------------------------------- 00174 */ 00175 00176 void 00177 Tcl_DiscardInterpState( 00178 Tcl_InterpState state) /* saved interpreter state */ 00179 { 00180 InterpState *statePtr = (InterpState *)state; 00181 00182 if (statePtr->errorInfo) { 00183 Tcl_DecrRefCount(statePtr->errorInfo); 00184 } 00185 if (statePtr->errorCode) { 00186 Tcl_DecrRefCount(statePtr->errorCode); 00187 } 00188 if (statePtr->returnOpts) { 00189 Tcl_DecrRefCount(statePtr->returnOpts); 00190 } 00191 Tcl_DecrRefCount(statePtr->objResult); 00192 ckfree((char *) statePtr); 00193 } 00194 00195 /* 00196 *---------------------------------------------------------------------- 00197 * 00198 * Tcl_SaveResult -- 00199 * 00200 * Takes a snapshot of the current result state of the interpreter. The 00201 * snapshot can be restored at any point by Tcl_RestoreResult. Note that 00202 * this routine does not preserve the errorCode, errorInfo, or flags 00203 * fields so it should not be used if an error is in progress. 00204 * 00205 * Once a snapshot is saved, it must be restored by calling 00206 * Tcl_RestoreResult, or discarded by calling Tcl_DiscardResult. 00207 * 00208 * Results: 00209 * None. 00210 * 00211 * Side effects: 00212 * Resets the interpreter result. 00213 * 00214 *---------------------------------------------------------------------- 00215 */ 00216 00217 void 00218 Tcl_SaveResult( 00219 Tcl_Interp *interp, /* Interpreter to save. */ 00220 Tcl_SavedResult *statePtr) /* Pointer to state structure. */ 00221 { 00222 Interp *iPtr = (Interp *) interp; 00223 00224 /* 00225 * Move the result object into the save state. Note that we don't need to 00226 * change its refcount because we're moving it, not adding a new 00227 * reference. Put an empty object into the interpreter. 00228 */ 00229 00230 statePtr->objResultPtr = iPtr->objResultPtr; 00231 iPtr->objResultPtr = Tcl_NewObj(); 00232 Tcl_IncrRefCount(iPtr->objResultPtr); 00233 00234 /* 00235 * Save the string result. 00236 */ 00237 00238 statePtr->freeProc = iPtr->freeProc; 00239 if (iPtr->result == iPtr->resultSpace) { 00240 /* 00241 * Copy the static string data out of the interp buffer. 00242 */ 00243 00244 statePtr->result = statePtr->resultSpace; 00245 strcpy(statePtr->result, iPtr->result); 00246 statePtr->appendResult = NULL; 00247 } else if (iPtr->result == iPtr->appendResult) { 00248 /* 00249 * Move the append buffer out of the interp. 00250 */ 00251 00252 statePtr->appendResult = iPtr->appendResult; 00253 statePtr->appendAvl = iPtr->appendAvl; 00254 statePtr->appendUsed = iPtr->appendUsed; 00255 statePtr->result = statePtr->appendResult; 00256 iPtr->appendResult = NULL; 00257 iPtr->appendAvl = 0; 00258 iPtr->appendUsed = 0; 00259 } else { 00260 /* 00261 * Move the dynamic or static string out of the interpreter. 00262 */ 00263 00264 statePtr->result = iPtr->result; 00265 statePtr->appendResult = NULL; 00266 } 00267 00268 iPtr->result = iPtr->resultSpace; 00269 iPtr->resultSpace[0] = 0; 00270 iPtr->freeProc = 0; 00271 } 00272 00273 /* 00274 *---------------------------------------------------------------------- 00275 * 00276 * Tcl_RestoreResult -- 00277 * 00278 * Restores the state of the interpreter to a snapshot taken by 00279 * Tcl_SaveResult. After this call, the token for the interpreter state 00280 * is no longer valid. 00281 * 00282 * Results: 00283 * None. 00284 * 00285 * Side effects: 00286 * Restores the interpreter result. 00287 * 00288 *---------------------------------------------------------------------- 00289 */ 00290 00291 void 00292 Tcl_RestoreResult( 00293 Tcl_Interp *interp, /* Interpreter being restored. */ 00294 Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */ 00295 { 00296 Interp *iPtr = (Interp *) interp; 00297 00298 Tcl_ResetResult(interp); 00299 00300 /* 00301 * Restore the string result. 00302 */ 00303 00304 iPtr->freeProc = statePtr->freeProc; 00305 if (statePtr->result == statePtr->resultSpace) { 00306 /* 00307 * Copy the static string data into the interp buffer. 00308 */ 00309 00310 iPtr->result = iPtr->resultSpace; 00311 strcpy(iPtr->result, statePtr->result); 00312 } else if (statePtr->result == statePtr->appendResult) { 00313 /* 00314 * Move the append buffer back into the interp. 00315 */ 00316 00317 if (iPtr->appendResult != NULL) { 00318 ckfree((char *) iPtr->appendResult); 00319 } 00320 00321 iPtr->appendResult = statePtr->appendResult; 00322 iPtr->appendAvl = statePtr->appendAvl; 00323 iPtr->appendUsed = statePtr->appendUsed; 00324 iPtr->result = iPtr->appendResult; 00325 } else { 00326 /* 00327 * Move the dynamic or static string back into the interpreter. 00328 */ 00329 00330 iPtr->result = statePtr->result; 00331 } 00332 00333 /* 00334 * Restore the object result. 00335 */ 00336 00337 Tcl_DecrRefCount(iPtr->objResultPtr); 00338 iPtr->objResultPtr = statePtr->objResultPtr; 00339 } 00340 00341 /* 00342 *---------------------------------------------------------------------- 00343 * 00344 * Tcl_DiscardResult -- 00345 * 00346 * Frees the memory associated with an interpreter snapshot taken by 00347 * Tcl_SaveResult. If the snapshot is not restored, this function must be 00348 * called to discard it, or the memory will be lost. 00349 * 00350 * Results: 00351 * None. 00352 * 00353 * Side effects: 00354 * None. 00355 * 00356 *---------------------------------------------------------------------- 00357 */ 00358 00359 void 00360 Tcl_DiscardResult( 00361 Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */ 00362 { 00363 TclDecrRefCount(statePtr->objResultPtr); 00364 00365 if (statePtr->result == statePtr->appendResult) { 00366 ckfree(statePtr->appendResult); 00367 } else if (statePtr->freeProc) { 00368 if (statePtr->freeProc == TCL_DYNAMIC) { 00369 ckfree(statePtr->result); 00370 } else { 00371 (*statePtr->freeProc)(statePtr->result); 00372 } 00373 } 00374 } 00375 00376 /* 00377 *---------------------------------------------------------------------- 00378 * 00379 * Tcl_SetResult -- 00380 * 00381 * Arrange for "result" to be the Tcl return value. 00382 * 00383 * Results: 00384 * None. 00385 * 00386 * Side effects: 00387 * interp->result is left pointing either to "result" or to a copy of it. 00388 * Also, the object result is reset. 00389 * 00390 *---------------------------------------------------------------------- 00391 */ 00392 00393 void 00394 Tcl_SetResult( 00395 Tcl_Interp *interp, /* Interpreter with which to associate the 00396 * return value. */ 00397 register char *result, /* Value to be returned. If NULL, the result 00398 * is set to an empty string. */ 00399 Tcl_FreeProc *freeProc) /* Gives information about the string: 00400 * TCL_STATIC, TCL_VOLATILE, or the address of 00401 * a Tcl_FreeProc such as free. */ 00402 { 00403 Interp *iPtr = (Interp *) interp; 00404 int length; 00405 register Tcl_FreeProc *oldFreeProc = iPtr->freeProc; 00406 char *oldResult = iPtr->result; 00407 00408 if (result == NULL) { 00409 iPtr->resultSpace[0] = 0; 00410 iPtr->result = iPtr->resultSpace; 00411 iPtr->freeProc = 0; 00412 } else if (freeProc == TCL_VOLATILE) { 00413 length = strlen(result); 00414 if (length > TCL_RESULT_SIZE) { 00415 iPtr->result = (char *) ckalloc((unsigned) length+1); 00416 iPtr->freeProc = TCL_DYNAMIC; 00417 } else { 00418 iPtr->result = iPtr->resultSpace; 00419 iPtr->freeProc = 0; 00420 } 00421 strcpy(iPtr->result, result); 00422 } else { 00423 iPtr->result = result; 00424 iPtr->freeProc = freeProc; 00425 } 00426 00427 /* 00428 * If the old result was dynamically-allocated, free it up. Do it here, 00429 * rather than at the beginning, in case the new result value was part of 00430 * the old result value. 00431 */ 00432 00433 if (oldFreeProc != 0) { 00434 if (oldFreeProc == TCL_DYNAMIC) { 00435 ckfree(oldResult); 00436 } else { 00437 (*oldFreeProc)(oldResult); 00438 } 00439 } 00440 00441 /* 00442 * Reset the object result since we just set the string result. 00443 */ 00444 00445 ResetObjResult(iPtr); 00446 } 00447 00448 /* 00449 *---------------------------------------------------------------------- 00450 * 00451 * Tcl_GetStringResult -- 00452 * 00453 * Returns an interpreter's result value as a string. 00454 * 00455 * Results: 00456 * The interpreter's result as a string. 00457 * 00458 * Side effects: 00459 * If the string result is empty, the object result is moved to the 00460 * string result, then the object result is reset. 00461 * 00462 *---------------------------------------------------------------------- 00463 */ 00464 00465 CONST char * 00466 Tcl_GetStringResult( 00467 register Tcl_Interp *interp)/* Interpreter whose result to return. */ 00468 { 00469 /* 00470 * If the string result is empty, move the object result to the string 00471 * result, then reset the object result. 00472 */ 00473 00474 if (*(interp->result) == 0) { 00475 Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), 00476 TCL_VOLATILE); 00477 } 00478 return interp->result; 00479 } 00480 00481 /* 00482 *---------------------------------------------------------------------- 00483 * 00484 * Tcl_SetObjResult -- 00485 * 00486 * Arrange for objPtr to be an interpreter's result value. 00487 * 00488 * Results: 00489 * None. 00490 * 00491 * Side effects: 00492 * interp->objResultPtr is left pointing to the object referenced by 00493 * objPtr. The object's reference count is incremented since there is now 00494 * a new reference to it. The reference count for any old objResultPtr 00495 * value is decremented. Also, the string result is reset. 00496 * 00497 *---------------------------------------------------------------------- 00498 */ 00499 00500 void 00501 Tcl_SetObjResult( 00502 Tcl_Interp *interp, /* Interpreter with which to associate the 00503 * return object value. */ 00504 register Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj 00505 * result is made an empty string object. */ 00506 { 00507 register Interp *iPtr = (Interp *) interp; 00508 register Tcl_Obj *oldObjResult = iPtr->objResultPtr; 00509 00510 iPtr->objResultPtr = objPtr; 00511 Tcl_IncrRefCount(objPtr); /* since interp result is a reference */ 00512 00513 /* 00514 * We wait until the end to release the old object result, in case we are 00515 * setting the result to itself. 00516 */ 00517 00518 TclDecrRefCount(oldObjResult); 00519 00520 /* 00521 * Reset the string result since we just set the result object. 00522 */ 00523 00524 if (iPtr->freeProc != NULL) { 00525 if (iPtr->freeProc == TCL_DYNAMIC) { 00526 ckfree(iPtr->result); 00527 } else { 00528 (*iPtr->freeProc)(iPtr->result); 00529 } 00530 iPtr->freeProc = 0; 00531 } 00532 iPtr->result = iPtr->resultSpace; 00533 iPtr->resultSpace[0] = 0; 00534 } 00535 00536 /* 00537 *---------------------------------------------------------------------- 00538 * 00539 * Tcl_GetObjResult -- 00540 * 00541 * Returns an interpreter's result value as a Tcl object. The object's 00542 * reference count is not modified; the caller must do that if it needs 00543 * to hold on to a long-term reference to it. 00544 * 00545 * Results: 00546 * The interpreter's result as an object. 00547 * 00548 * Side effects: 00549 * If the interpreter has a non-empty string result, the result object is 00550 * either empty or stale because some function set interp->result 00551 * directly. If so, the string result is moved to the result object then 00552 * the string result is reset. 00553 * 00554 *---------------------------------------------------------------------- 00555 */ 00556 00557 Tcl_Obj * 00558 Tcl_GetObjResult( 00559 Tcl_Interp *interp) /* Interpreter whose result to return. */ 00560 { 00561 register Interp *iPtr = (Interp *) interp; 00562 Tcl_Obj *objResultPtr; 00563 int length; 00564 00565 /* 00566 * If the string result is non-empty, move the string result to the object 00567 * result, then reset the string result. 00568 */ 00569 00570 if (*(iPtr->result) != 0) { 00571 ResetObjResult(iPtr); 00572 00573 objResultPtr = iPtr->objResultPtr; 00574 length = strlen(iPtr->result); 00575 TclInitStringRep(objResultPtr, iPtr->result, length); 00576 00577 if (iPtr->freeProc != NULL) { 00578 if (iPtr->freeProc == TCL_DYNAMIC) { 00579 ckfree(iPtr->result); 00580 } else { 00581 (*iPtr->freeProc)(iPtr->result); 00582 } 00583 iPtr->freeProc = 0; 00584 } 00585 iPtr->result = iPtr->resultSpace; 00586 iPtr->resultSpace[0] = 0; 00587 } 00588 return iPtr->objResultPtr; 00589 } 00590 00591 /* 00592 *---------------------------------------------------------------------- 00593 * 00594 * Tcl_AppendResultVA -- 00595 * 00596 * Append a variable number of strings onto the interpreter's result. 00597 * 00598 * Results: 00599 * None. 00600 * 00601 * Side effects: 00602 * The result of the interpreter given by the first argument is extended 00603 * by the strings in the va_list (up to a terminating NULL argument). 00604 * 00605 * If the string result is non-empty, the object result forced to be a 00606 * duplicate of it first. There will be a string result afterwards. 00607 * 00608 *---------------------------------------------------------------------- 00609 */ 00610 00611 void 00612 Tcl_AppendResultVA( 00613 Tcl_Interp *interp, /* Interpreter with which to associate the 00614 * return value. */ 00615 va_list argList) /* Variable argument list. */ 00616 { 00617 Tcl_Obj *objPtr = Tcl_GetObjResult(interp); 00618 00619 if (Tcl_IsShared(objPtr)) { 00620 objPtr = Tcl_DuplicateObj(objPtr); 00621 } 00622 Tcl_AppendStringsToObjVA(objPtr, argList); 00623 Tcl_SetObjResult(interp, objPtr); 00624 00625 /* 00626 * Strictly we should call Tcl_GetStringResult(interp) here to make sure 00627 * that interp->result is correct according to the old contract, but that 00628 * makes the performance of much code (e.g. in Tk) absolutely awful. So we 00629 * leave it out; code that really wants interp->result can just insert the 00630 * calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion] 00631 */ 00632 00633 #ifdef USE_DIRECT_INTERP_RESULT_ACCESS 00634 /* 00635 * Ensure that the interp->result is legal so old Tcl 7.* code still 00636 * works. There's still embarrasingly much of it about... 00637 */ 00638 00639 (void) Tcl_GetStringResult(interp); 00640 #endif /* USE_DIRECT_INTERP_RESULT_ACCESS */ 00641 } 00642 00643 /* 00644 *---------------------------------------------------------------------- 00645 * 00646 * Tcl_AppendResult -- 00647 * 00648 * Append a variable number of strings onto the interpreter's result. 00649 * 00650 * Results: 00651 * None. 00652 * 00653 * Side effects: 00654 * The result of the interpreter given by the first argument is extended 00655 * by the strings given by the second and following arguments (up to a 00656 * terminating NULL argument). 00657 * 00658 * If the string result is non-empty, the object result forced to be a 00659 * duplicate of it first. There will be a string result afterwards. 00660 * 00661 *---------------------------------------------------------------------- 00662 */ 00663 00664 void 00665 Tcl_AppendResult( 00666 Tcl_Interp *interp, ...) 00667 { 00668 va_list argList; 00669 00670 va_start(argList, interp); 00671 Tcl_AppendResultVA(interp, argList); 00672 va_end(argList); 00673 } 00674 00675 /* 00676 *---------------------------------------------------------------------- 00677 * 00678 * Tcl_AppendElement -- 00679 * 00680 * Convert a string to a valid Tcl list element and append it to the 00681 * result (which is ostensibly a list). 00682 * 00683 * Results: 00684 * None. 00685 * 00686 * Side effects: 00687 * The result in the interpreter given by the first argument is extended 00688 * with a list element converted from string. A separator space is added 00689 * before the converted list element unless the current result is empty, 00690 * contains the single character "{", or ends in " {". 00691 * 00692 * If the string result is empty, the object result is moved to the 00693 * string result, then the object result is reset. 00694 * 00695 *---------------------------------------------------------------------- 00696 */ 00697 00698 void 00699 Tcl_AppendElement( 00700 Tcl_Interp *interp, /* Interpreter whose result is to be 00701 * extended. */ 00702 CONST char *element) /* String to convert to list element and add 00703 * to result. */ 00704 { 00705 Interp *iPtr = (Interp *) interp; 00706 char *dst; 00707 int size; 00708 int flags; 00709 00710 /* 00711 * If the string result is empty, move the object result to the string 00712 * result, then reset the object result. 00713 */ 00714 00715 (void) Tcl_GetStringResult(interp); 00716 00717 /* 00718 * See how much space is needed, and grow the append buffer if needed to 00719 * accommodate the list element. 00720 */ 00721 00722 size = Tcl_ScanElement(element, &flags) + 1; 00723 if ((iPtr->result != iPtr->appendResult) 00724 || (iPtr->appendResult[iPtr->appendUsed] != 0) 00725 || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) { 00726 SetupAppendBuffer(iPtr, size+iPtr->appendUsed); 00727 } 00728 00729 /* 00730 * Convert the string into a list element and copy it to the buffer that's 00731 * forming, with a space separator if needed. 00732 */ 00733 00734 dst = iPtr->appendResult + iPtr->appendUsed; 00735 if (TclNeedSpace(iPtr->appendResult, dst)) { 00736 iPtr->appendUsed++; 00737 *dst = ' '; 00738 dst++; 00739 00740 /* 00741 * If we need a space to separate this element from preceding stuff, 00742 * then this element will not lead a list, and need not have it's 00743 * leading '#' quoted. 00744 */ 00745 00746 flags |= TCL_DONT_QUOTE_HASH; 00747 } 00748 iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags); 00749 } 00750 00751 /* 00752 *---------------------------------------------------------------------- 00753 * 00754 * SetupAppendBuffer -- 00755 * 00756 * This function makes sure that there is an append buffer properly 00757 * initialized, if necessary, from the interpreter's result, and that it 00758 * has at least enough room to accommodate newSpace new bytes of 00759 * information. 00760 * 00761 * Results: 00762 * None. 00763 * 00764 * Side effects: 00765 * None. 00766 * 00767 *---------------------------------------------------------------------- 00768 */ 00769 00770 static void 00771 SetupAppendBuffer( 00772 Interp *iPtr, /* Interpreter whose result is being set up. */ 00773 int newSpace) /* Make sure that at least this many bytes of 00774 * new information may be added. */ 00775 { 00776 int totalSpace; 00777 00778 /* 00779 * Make the append buffer larger, if that's necessary, then copy the 00780 * result into the append buffer and make the append buffer the official 00781 * Tcl result. 00782 */ 00783 00784 if (iPtr->result != iPtr->appendResult) { 00785 /* 00786 * If an oversized buffer was used recently, then free it up so we go 00787 * back to a smaller buffer. This avoids tying up memory forever after 00788 * a large operation. 00789 */ 00790 00791 if (iPtr->appendAvl > 500) { 00792 ckfree(iPtr->appendResult); 00793 iPtr->appendResult = NULL; 00794 iPtr->appendAvl = 0; 00795 } 00796 iPtr->appendUsed = strlen(iPtr->result); 00797 } else if (iPtr->result[iPtr->appendUsed] != 0) { 00798 /* 00799 * Most likely someone has modified a result created by 00800 * Tcl_AppendResult et al. so that it has a different size. Just 00801 * recompute the size. 00802 */ 00803 00804 iPtr->appendUsed = strlen(iPtr->result); 00805 } 00806 00807 totalSpace = newSpace + iPtr->appendUsed; 00808 if (totalSpace >= iPtr->appendAvl) { 00809 char *new; 00810 00811 if (totalSpace < 100) { 00812 totalSpace = 200; 00813 } else { 00814 totalSpace *= 2; 00815 } 00816 new = (char *) ckalloc((unsigned) totalSpace); 00817 strcpy(new, iPtr->result); 00818 if (iPtr->appendResult != NULL) { 00819 ckfree(iPtr->appendResult); 00820 } 00821 iPtr->appendResult = new; 00822 iPtr->appendAvl = totalSpace; 00823 } else if (iPtr->result != iPtr->appendResult) { 00824 strcpy(iPtr->appendResult, iPtr->result); 00825 } 00826 00827 Tcl_FreeResult((Tcl_Interp *) iPtr); 00828 iPtr->result = iPtr->appendResult; 00829 } 00830 00831 /* 00832 *---------------------------------------------------------------------- 00833 * 00834 * Tcl_FreeResult -- 00835 * 00836 * This function frees up the memory associated with an interpreter's 00837 * string result. It also resets the interpreter's result object. 00838 * Tcl_FreeResult is most commonly used when a function is about to 00839 * replace one result value with another. 00840 * 00841 * Results: 00842 * None. 00843 * 00844 * Side effects: 00845 * Frees the memory associated with interp's string result and sets 00846 * interp->freeProc to zero, but does not change interp->result or clear 00847 * error state. Resets interp's result object to an unshared empty 00848 * object. 00849 * 00850 *---------------------------------------------------------------------- 00851 */ 00852 00853 void 00854 Tcl_FreeResult( 00855 register Tcl_Interp *interp)/* Interpreter for which to free result. */ 00856 { 00857 register Interp *iPtr = (Interp *) interp; 00858 00859 if (iPtr->freeProc != NULL) { 00860 if (iPtr->freeProc == TCL_DYNAMIC) { 00861 ckfree(iPtr->result); 00862 } else { 00863 (*iPtr->freeProc)(iPtr->result); 00864 } 00865 iPtr->freeProc = 0; 00866 } 00867 00868 ResetObjResult(iPtr); 00869 } 00870 00871 /* 00872 *---------------------------------------------------------------------- 00873 * 00874 * Tcl_ResetResult -- 00875 * 00876 * This function resets both the interpreter's string and object results. 00877 * 00878 * Results: 00879 * None. 00880 * 00881 * Side effects: 00882 * It resets the result object to an unshared empty object. It then 00883 * restores the interpreter's string result area to its default 00884 * initialized state, freeing up any memory that may have been allocated. 00885 * It also clears any error information for the interpreter. 00886 * 00887 *---------------------------------------------------------------------- 00888 */ 00889 00890 void 00891 Tcl_ResetResult( 00892 register Tcl_Interp *interp)/* Interpreter for which to clear result. */ 00893 { 00894 register Interp *iPtr = (Interp *) interp; 00895 00896 ResetObjResult(iPtr); 00897 if (iPtr->freeProc != NULL) { 00898 if (iPtr->freeProc == TCL_DYNAMIC) { 00899 ckfree(iPtr->result); 00900 } else { 00901 (*iPtr->freeProc)(iPtr->result); 00902 } 00903 iPtr->freeProc = 0; 00904 } 00905 iPtr->result = iPtr->resultSpace; 00906 iPtr->resultSpace[0] = 0; 00907 if (iPtr->errorCode) { 00908 /* Legacy support */ 00909 if (iPtr->flags & ERR_LEGACY_COPY) { 00910 Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL, 00911 iPtr->errorCode, TCL_GLOBAL_ONLY); 00912 } 00913 Tcl_DecrRefCount(iPtr->errorCode); 00914 iPtr->errorCode = NULL; 00915 } 00916 if (iPtr->errorInfo) { 00917 /* Legacy support */ 00918 if (iPtr->flags & ERR_LEGACY_COPY) { 00919 Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, 00920 iPtr->errorInfo, TCL_GLOBAL_ONLY); 00921 } 00922 Tcl_DecrRefCount(iPtr->errorInfo); 00923 iPtr->errorInfo = NULL; 00924 } 00925 iPtr->returnLevel = 1; 00926 iPtr->returnCode = TCL_OK; 00927 if (iPtr->returnOpts) { 00928 Tcl_DecrRefCount(iPtr->returnOpts); 00929 iPtr->returnOpts = NULL; 00930 } 00931 iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_LEGACY_COPY); 00932 } 00933 00934 /* 00935 *---------------------------------------------------------------------- 00936 * 00937 * ResetObjResult -- 00938 * 00939 * Function used to reset an interpreter's Tcl result object. 00940 * 00941 * Results: 00942 * None. 00943 * 00944 * Side effects: 00945 * Resets the interpreter's result object to an unshared empty string 00946 * object with ref count one. It does not clear any error information in 00947 * the interpreter. 00948 * 00949 *---------------------------------------------------------------------- 00950 */ 00951 00952 static void 00953 ResetObjResult( 00954 register Interp *iPtr) /* Points to the interpreter whose result 00955 * object should be reset. */ 00956 { 00957 register Tcl_Obj *objResultPtr = iPtr->objResultPtr; 00958 00959 if (Tcl_IsShared(objResultPtr)) { 00960 TclDecrRefCount(objResultPtr); 00961 TclNewObj(objResultPtr); 00962 Tcl_IncrRefCount(objResultPtr); 00963 iPtr->objResultPtr = objResultPtr; 00964 } else if (objResultPtr->bytes != tclEmptyStringRep) { 00965 if (objResultPtr->bytes != NULL) { 00966 ckfree((char *) objResultPtr->bytes); 00967 } 00968 objResultPtr->bytes = tclEmptyStringRep; 00969 objResultPtr->length = 0; 00970 TclFreeIntRep(objResultPtr); 00971 objResultPtr->typePtr = NULL; 00972 } 00973 } 00974 00975 /* 00976 *---------------------------------------------------------------------- 00977 * 00978 * Tcl_SetErrorCodeVA -- 00979 * 00980 * This function is called to record machine-readable information about 00981 * an error that is about to be returned. 00982 * 00983 * Results: 00984 * None. 00985 * 00986 * Side effects: 00987 * The errorCode field of the interp is modified to hold all of the 00988 * arguments to this function, in a list form with each argument becoming 00989 * one element of the list. 00990 * 00991 *---------------------------------------------------------------------- 00992 */ 00993 00994 void 00995 Tcl_SetErrorCodeVA( 00996 Tcl_Interp *interp, /* Interpreter in which to set errorCode */ 00997 va_list argList) /* Variable argument list. */ 00998 { 00999 Tcl_Obj *errorObj = Tcl_NewObj(); 01000 01001 /* 01002 * Scan through the arguments one at a time, appending them to the 01003 * errorCode field as list elements. 01004 */ 01005 01006 while (1) { 01007 char *elem = va_arg(argList, char *); 01008 if (elem == NULL) { 01009 break; 01010 } 01011 Tcl_ListObjAppendElement(NULL, errorObj, Tcl_NewStringObj(elem, -1)); 01012 } 01013 Tcl_SetObjErrorCode(interp, errorObj); 01014 } 01015 01016 /* 01017 *---------------------------------------------------------------------- 01018 * 01019 * Tcl_SetErrorCode -- 01020 * 01021 * This function is called to record machine-readable information about 01022 * an error that is about to be returned. 01023 * 01024 * Results: 01025 * None. 01026 * 01027 * Side effects: 01028 * The errorCode field of the interp is modified to hold all of the 01029 * arguments to this function, in a list form with each argument becoming 01030 * one element of the list. 01031 * 01032 *---------------------------------------------------------------------- 01033 */ 01034 01035 void 01036 Tcl_SetErrorCode( 01037 Tcl_Interp *interp, ...) 01038 { 01039 va_list argList; 01040 01041 /* 01042 * Scan through the arguments one at a time, appending them to the 01043 * errorCode field as list elements. 01044 */ 01045 01046 va_start(argList, interp); 01047 Tcl_SetErrorCodeVA(interp, argList); 01048 va_end(argList); 01049 } 01050 01051 /* 01052 *---------------------------------------------------------------------- 01053 * 01054 * Tcl_SetObjErrorCode -- 01055 * 01056 * This function is called to record machine-readable information about 01057 * an error that is about to be returned. The caller should build a list 01058 * object up and pass it to this routine. 01059 * 01060 * Results: 01061 * None. 01062 * 01063 * Side effects: 01064 * The errorCode field of the interp is set to the new value. 01065 * 01066 *---------------------------------------------------------------------- 01067 */ 01068 01069 void 01070 Tcl_SetObjErrorCode( 01071 Tcl_Interp *interp, 01072 Tcl_Obj *errorObjPtr) 01073 { 01074 Interp *iPtr = (Interp *) interp; 01075 01076 if (iPtr->errorCode) { 01077 Tcl_DecrRefCount(iPtr->errorCode); 01078 } 01079 iPtr->errorCode = errorObjPtr; 01080 Tcl_IncrRefCount(iPtr->errorCode); 01081 } 01082 01083 /* 01084 *---------------------------------------------------------------------- 01085 * 01086 * GetKeys -- 01087 * 01088 * Returns a Tcl_Obj * array of the standard keys used in the return 01089 * options dictionary. 01090 * 01091 * Broadly sharing one copy of these key values helps with both memory 01092 * efficiency and dictionary lookup times. 01093 * 01094 * Results: 01095 * A Tcl_Obj * array. 01096 * 01097 * Side effects: 01098 * First time called in a thread, creates the keys (allocating memory) 01099 * and arranges for their cleanup at thread exit. 01100 * 01101 *---------------------------------------------------------------------- 01102 */ 01103 01104 static Tcl_Obj ** 01105 GetKeys(void) 01106 { 01107 static Tcl_ThreadDataKey returnKeysKey; 01108 Tcl_Obj **keys = Tcl_GetThreadData(&returnKeysKey, 01109 (int) (KEY_LAST * sizeof(Tcl_Obj *))); 01110 01111 if (keys[0] == NULL) { 01112 /* 01113 * First call in this thread, create the keys... 01114 */ 01115 01116 int i; 01117 01118 TclNewLiteralStringObj(keys[KEY_CODE], "-code"); 01119 TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode"); 01120 TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo"); 01121 TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline"); 01122 TclNewLiteralStringObj(keys[KEY_LEVEL], "-level"); 01123 TclNewLiteralStringObj(keys[KEY_OPTIONS], "-options"); 01124 01125 for (i = KEY_CODE; i < KEY_LAST; i++) { 01126 Tcl_IncrRefCount(keys[i]); 01127 } 01128 01129 /* 01130 * ... and arrange for their clenaup. 01131 */ 01132 01133 Tcl_CreateThreadExitHandler(ReleaseKeys, (ClientData) keys); 01134 } 01135 return keys; 01136 } 01137 01138 /* 01139 *---------------------------------------------------------------------- 01140 * 01141 * ReleaseKeys -- 01142 * 01143 * Called as a thread exit handler to cleanup return options dictionary 01144 * keys. 01145 * 01146 * Results: 01147 * None. 01148 * 01149 * Side effects: 01150 * Frees memory. 01151 * 01152 *---------------------------------------------------------------------- 01153 */ 01154 01155 static void 01156 ReleaseKeys( 01157 ClientData clientData) 01158 { 01159 Tcl_Obj **keys = (Tcl_Obj **)clientData; 01160 int i; 01161 01162 for (i = KEY_CODE; i < KEY_LAST; i++) { 01163 Tcl_DecrRefCount(keys[i]); 01164 } 01165 } 01166 01167 /* 01168 *---------------------------------------------------------------------- 01169 * 01170 * TclProcessReturn -- 01171 * 01172 * Does the work of the [return] command based on the code, level, and 01173 * returnOpts arguments. Note that the code argument must agree with the 01174 * -code entry in returnOpts and the level argument must agree with the 01175 * -level entry in returnOpts, as is the case for values returned from 01176 * TclMergeReturnOptions. 01177 * 01178 * Results: 01179 * Returns the return code the [return] command should return. 01180 * 01181 * Side effects: 01182 * None. 01183 * 01184 *---------------------------------------------------------------------- 01185 */ 01186 01187 int 01188 TclProcessReturn( 01189 Tcl_Interp *interp, 01190 int code, 01191 int level, 01192 Tcl_Obj *returnOpts) 01193 { 01194 Interp *iPtr = (Interp *) interp; 01195 Tcl_Obj *valuePtr; 01196 Tcl_Obj **keys = GetKeys(); 01197 01198 /* 01199 * Store the merged return options. 01200 */ 01201 01202 if (iPtr->returnOpts != returnOpts) { 01203 if (iPtr->returnOpts) { 01204 Tcl_DecrRefCount(iPtr->returnOpts); 01205 } 01206 iPtr->returnOpts = returnOpts; 01207 Tcl_IncrRefCount(iPtr->returnOpts); 01208 } 01209 01210 if (code == TCL_ERROR) { 01211 if (iPtr->errorInfo) { 01212 Tcl_DecrRefCount(iPtr->errorInfo); 01213 iPtr->errorInfo = NULL; 01214 } 01215 Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr); 01216 if (valuePtr != NULL) { 01217 int infoLen; 01218 01219 (void) TclGetStringFromObj(valuePtr, &infoLen); 01220 if (infoLen) { 01221 iPtr->errorInfo = valuePtr; 01222 Tcl_IncrRefCount(iPtr->errorInfo); 01223 iPtr->flags |= ERR_ALREADY_LOGGED; 01224 } 01225 } 01226 Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr); 01227 if (valuePtr != NULL) { 01228 Tcl_SetObjErrorCode(interp, valuePtr); 01229 } else { 01230 Tcl_SetErrorCode(interp, "NONE", NULL); 01231 } 01232 01233 Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr); 01234 if (valuePtr != NULL) { 01235 TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine); 01236 } 01237 } 01238 if (level != 0) { 01239 iPtr->returnLevel = level; 01240 iPtr->returnCode = code; 01241 return TCL_RETURN; 01242 } 01243 if (code == TCL_ERROR) { 01244 iPtr->flags |= ERR_LEGACY_COPY; 01245 } 01246 return code; 01247 } 01248 01249 /* 01250 *---------------------------------------------------------------------- 01251 * 01252 * TclMergeReturnOptions -- 01253 * 01254 * Parses, checks, and stores the options to the [return] command. 01255 * 01256 * Results: 01257 * Returns TCL_ERROR is any of the option values are invalid. Otherwise, 01258 * returns TCL_OK, and writes the returnOpts, code, and level values to 01259 * the pointers provided. 01260 * 01261 * Side effects: 01262 * None. 01263 * 01264 *---------------------------------------------------------------------- 01265 */ 01266 01267 int 01268 TclMergeReturnOptions( 01269 Tcl_Interp *interp, /* Current interpreter. */ 01270 int objc, /* Number of arguments. */ 01271 Tcl_Obj *CONST objv[], /* Argument objects. */ 01272 Tcl_Obj **optionsPtrPtr, /* If not NULL, points to space for a (Tcl_Obj 01273 * *) where the pointer to the merged return 01274 * options dictionary should be written */ 01275 int *codePtr, /* If not NULL, points to space where the 01276 * -code value should be written */ 01277 int *levelPtr) /* If not NULL, points to space where the 01278 * -level value should be written */ 01279 { 01280 int code=TCL_OK; 01281 int level = 1; 01282 Tcl_Obj *valuePtr; 01283 Tcl_Obj *returnOpts = Tcl_NewObj(); 01284 Tcl_Obj **keys = GetKeys(); 01285 01286 for (; objc > 1; objv += 2, objc -= 2) { 01287 int optLen; 01288 CONST char *opt = TclGetStringFromObj(objv[0], &optLen); 01289 int compareLen; 01290 CONST char *compare = 01291 TclGetStringFromObj(keys[KEY_OPTIONS], &compareLen); 01292 01293 if ((optLen == compareLen) && (strcmp(opt, compare) == 0)) { 01294 Tcl_DictSearch search; 01295 int done = 0; 01296 Tcl_Obj *keyPtr; 01297 Tcl_Obj *dict = objv[1]; 01298 01299 nestedOptions: 01300 if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search, 01301 &keyPtr, &valuePtr, &done)) { 01302 /* 01303 * Value is not a legal dictionary. 01304 */ 01305 01306 Tcl_ResetResult(interp); 01307 Tcl_AppendResult(interp, "bad ", compare, 01308 " value: expected dictionary but got \"", 01309 TclGetString(objv[1]), "\"", NULL); 01310 goto error; 01311 } 01312 01313 while (!done) { 01314 Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr); 01315 Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done); 01316 } 01317 01318 Tcl_DictObjGet(NULL, returnOpts, keys[KEY_OPTIONS], &valuePtr); 01319 if (valuePtr != NULL) { 01320 dict = valuePtr; 01321 Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_OPTIONS]); 01322 goto nestedOptions; 01323 } 01324 01325 } else { 01326 Tcl_DictObjPut(NULL, returnOpts, objv[0], objv[1]); 01327 } 01328 } 01329 01330 /* 01331 * Check for bogus -code value. 01332 */ 01333 01334 Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr); 01335 if ((valuePtr != NULL) 01336 && (TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &code))) { 01337 static CONST char *returnCodes[] = { 01338 "ok", "error", "return", "break", "continue", NULL 01339 }; 01340 01341 if (TCL_ERROR == Tcl_GetIndexFromObj(NULL, valuePtr, returnCodes, 01342 NULL, TCL_EXACT, &code)) { 01343 /* 01344 * Value is not a legal return code. 01345 */ 01346 01347 Tcl_ResetResult(interp); 01348 Tcl_AppendResult(interp, "bad completion code \"", 01349 TclGetString(valuePtr), 01350 "\": must be ok, error, return, break, " 01351 "continue, or an integer", NULL); 01352 goto error; 01353 } 01354 } 01355 if (valuePtr != NULL) { 01356 Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]); 01357 } 01358 01359 /* 01360 * Check for bogus -level value. 01361 */ 01362 01363 Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr); 01364 if (valuePtr != NULL) { 01365 if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level)) 01366 || (level < 0)) { 01367 /* 01368 * Value is not a legal level. 01369 */ 01370 01371 Tcl_ResetResult(interp); 01372 Tcl_AppendResult(interp, "bad -level value: " 01373 "expected non-negative integer but got \"", 01374 TclGetString(valuePtr), "\"", NULL); 01375 goto error; 01376 } 01377 Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]); 01378 } 01379 01380 /* 01381 * Convert [return -code return -level X] to [return -code ok -level X+1] 01382 */ 01383 01384 if (code == TCL_RETURN) { 01385 level++; 01386 code = TCL_OK; 01387 } 01388 01389 if (codePtr != NULL) { 01390 *codePtr = code; 01391 } 01392 if (levelPtr != NULL) { 01393 *levelPtr = level; 01394 } 01395 01396 if (optionsPtrPtr == NULL) { 01397 /* 01398 * Not passing back the options (?!), so clean them up. 01399 */ 01400 01401 Tcl_DecrRefCount(returnOpts); 01402 } else { 01403 *optionsPtrPtr = returnOpts; 01404 } 01405 return TCL_OK; 01406 01407 error: 01408 Tcl_DecrRefCount(returnOpts); 01409 return TCL_ERROR; 01410 } 01411 01412 /* 01413 *------------------------------------------------------------------------- 01414 * 01415 * Tcl_GetReturnOptions -- 01416 * 01417 * Packs up the interp state into a dictionary of return options. 01418 * 01419 * Results: 01420 * A dictionary of return options. 01421 * 01422 * Side effects: 01423 * None. 01424 * 01425 *------------------------------------------------------------------------- 01426 */ 01427 01428 Tcl_Obj * 01429 Tcl_GetReturnOptions( 01430 Tcl_Interp *interp, 01431 int result) 01432 { 01433 Interp *iPtr = (Interp *) interp; 01434 Tcl_Obj *options; 01435 Tcl_Obj **keys = GetKeys(); 01436 01437 if (iPtr->returnOpts) { 01438 options = Tcl_DuplicateObj(iPtr->returnOpts); 01439 } else { 01440 options = Tcl_NewObj(); 01441 } 01442 01443 if (result == TCL_RETURN) { 01444 Tcl_DictObjPut(NULL, options, keys[KEY_CODE], 01445 Tcl_NewIntObj(iPtr->returnCode)); 01446 Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL], 01447 Tcl_NewIntObj(iPtr->returnLevel)); 01448 } else { 01449 Tcl_DictObjPut(NULL, options, keys[KEY_CODE], 01450 Tcl_NewIntObj(result)); 01451 Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL], 01452 Tcl_NewIntObj(0)); 01453 } 01454 01455 if (result == TCL_ERROR) { 01456 Tcl_AddObjErrorInfo(interp, "", -1); 01457 } 01458 if (iPtr->errorCode) { 01459 Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode); 01460 } 01461 if (iPtr->errorInfo) { 01462 Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo); 01463 Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE], 01464 Tcl_NewIntObj(iPtr->errorLine)); 01465 } 01466 return options; 01467 } 01468 01469 /* 01470 *------------------------------------------------------------------------- 01471 * 01472 * Tcl_SetReturnOptions -- 01473 * 01474 * Accepts an interp and a dictionary of return options, and sets the 01475 * return options of the interp to match the dictionary. 01476 * 01477 * Results: 01478 * A standard status code. Usually TCL_OK, but TCL_ERROR if an invalid 01479 * option value was found in the dictionary. If a -level value of 0 is in 01480 * the dictionary, then the -code value in the dictionary will be 01481 * returned (TCL_OK default). 01482 * 01483 * Side effects: 01484 * Sets the state of the interp. 01485 * 01486 *------------------------------------------------------------------------- 01487 */ 01488 01489 int 01490 Tcl_SetReturnOptions( 01491 Tcl_Interp *interp, 01492 Tcl_Obj *options) 01493 { 01494 int objc, level, code; 01495 Tcl_Obj **objv, *mergedOpts; 01496 01497 if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv) 01498 || (objc % 2)) { 01499 Tcl_ResetResult(interp); 01500 Tcl_AppendResult(interp, "expected dict but got \"", 01501 TclGetString(options), "\"", NULL); 01502 code = TCL_ERROR; 01503 } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv, 01504 &mergedOpts, &code, &level)) { 01505 code = TCL_ERROR; 01506 } else { 01507 code = TclProcessReturn(interp, code, level, mergedOpts); 01508 } 01509 01510 Tcl_DecrRefCount(options); 01511 return code; 01512 } 01513 01514 /* 01515 *------------------------------------------------------------------------- 01516 * 01517 * TclTransferResult -- 01518 * 01519 * Copy the result (and error information) from one interp to another. 01520 * Used when one interp has caused another interp to evaluate a script 01521 * and then wants to transfer the results back to itself. 01522 * 01523 * This routine copies the string reps of the result and error 01524 * information. It does not simply increment the refcounts of the result 01525 * and error information objects themselves. It is not legal to exchange 01526 * objects between interps, because an object may be kept alive by one 01527 * interp, but have an internal rep that is only valid while some other 01528 * interp is alive. 01529 * 01530 * Results: 01531 * The target interp's result is set to a copy of the source interp's 01532 * result. The source's errorInfo field may be transferred to the 01533 * target's errorInfo field, and the source's errorCode field may be 01534 * transferred to the target's errorCode field. 01535 * 01536 * Side effects: 01537 * None. 01538 * 01539 *------------------------------------------------------------------------- 01540 */ 01541 01542 void 01543 TclTransferResult( 01544 Tcl_Interp *sourceInterp, /* Interp whose result and error information 01545 * should be moved to the target interp. 01546 * After moving result, this interp's result 01547 * is reset. */ 01548 int result, /* TCL_OK if just the result should be copied, 01549 * TCL_ERROR if both the result and error 01550 * information should be copied. */ 01551 Tcl_Interp *targetInterp) /* Interp where result and error information 01552 * should be stored. If source and target are 01553 * the same, nothing is done. */ 01554 { 01555 Interp *tiPtr = (Interp *) targetInterp; 01556 Interp *siPtr = (Interp *) sourceInterp; 01557 01558 if (sourceInterp == targetInterp) { 01559 return; 01560 } 01561 01562 if (result == TCL_OK && siPtr->returnOpts == NULL) { 01563 /* 01564 * Special optimization for the common case of normal command return 01565 * code and no explicit return options. 01566 */ 01567 01568 if (tiPtr->returnOpts) { 01569 Tcl_DecrRefCount(tiPtr->returnOpts); 01570 tiPtr->returnOpts = NULL; 01571 } 01572 } else { 01573 Tcl_SetReturnOptions(targetInterp, 01574 Tcl_GetReturnOptions(sourceInterp, result)); 01575 tiPtr->flags &= ~(ERR_ALREADY_LOGGED); 01576 } 01577 Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp)); 01578 Tcl_ResetResult(sourceInterp); 01579 } 01580 01581 /* 01582 * Local Variables: 01583 * mode: c 01584 * c-basic-offset: 4 01585 * fill-column: 78 01586 * End: 01587 */
Generated on Wed Mar 12 12:18:21 2008 by 1.5.1 |