summaryrefslogtreecommitdiffstats
path: root/generic/tclResult.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclResult.c')
-rw-r--r--generic/tclResult.c494
1 files changed, 166 insertions, 328 deletions
diff --git a/generic/tclResult.c b/generic/tclResult.c
index b35aee0..7b58d44 100644
--- a/generic/tclResult.c
+++ b/generic/tclResult.c
@@ -3,7 +3,7 @@
*
* This file contains code to manage the interpreter result.
*
- * Copyright © 1997 Sun Microsystems, Inc.
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -17,7 +17,7 @@
enum returnKeys {
KEY_CODE, KEY_ERRORCODE, KEY_ERRORINFO, KEY_ERRORLINE,
- KEY_LEVEL, KEY_OPTIONS, KEY_ERRORSTACK, KEY_LAST
+ KEY_LEVEL, KEY_OPTIONS, KEY_LAST
};
/*
@@ -27,9 +27,7 @@ enum returnKeys {
static Tcl_Obj ** GetKeys(void);
static void ReleaseKeys(ClientData clientData);
static void ResetObjResult(Interp *iPtr);
-#ifndef TCL_NO_DEPRECATED
static void SetupAppendBuffer(Interp *iPtr, int newSpace);
-#endif /* !TCL_NO_DEPRECATED */
/*
* This structure is used to take a snapshot of the interpreter state in
@@ -37,7 +35,7 @@ static void SetupAppendBuffer(Interp *iPtr, int newSpace);
* then back up to the result or the error that was previously in progress.
*/
-typedef struct {
+typedef struct InterpState {
int status; /* return code status */
int flags; /* Each remaining field saves the */
int returnLevel; /* corresponding field of the Interp */
@@ -46,8 +44,6 @@ typedef struct {
Tcl_Obj *errorCode;
Tcl_Obj *returnOpts;
Tcl_Obj *objResult;
- Tcl_Obj *errorStack;
- int resetErrorStack;
} InterpState;
/*
@@ -76,7 +72,7 @@ Tcl_SaveInterpState(
Tcl_Interp *interp, /* Interpreter's state to be saved */
int status) /* status code for current operation */
{
- Interp *iPtr = (Interp *) interp;
+ Interp *iPtr = (Interp *)interp;
InterpState *statePtr = (InterpState *)ckalloc(sizeof(InterpState));
statePtr->status = status;
@@ -84,8 +80,6 @@ Tcl_SaveInterpState(
statePtr->returnLevel = iPtr->returnLevel;
statePtr->returnCode = iPtr->returnCode;
statePtr->errorInfo = iPtr->errorInfo;
- statePtr->errorStack = iPtr->errorStack;
- statePtr->resetErrorStack = iPtr->resetErrorStack;
if (statePtr->errorInfo) {
Tcl_IncrRefCount(statePtr->errorInfo);
}
@@ -97,9 +91,6 @@ Tcl_SaveInterpState(
if (statePtr->returnOpts) {
Tcl_IncrRefCount(statePtr->returnOpts);
}
- if (statePtr->errorStack) {
- Tcl_IncrRefCount(statePtr->errorStack);
- }
statePtr->objResult = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(statePtr->objResult);
return (Tcl_InterpState) statePtr;
@@ -128,8 +119,8 @@ Tcl_RestoreInterpState(
Tcl_Interp *interp, /* Interpreter's state to be restored. */
Tcl_InterpState state) /* Saved interpreter state. */
{
- Interp *iPtr = (Interp *) interp;
- InterpState *statePtr = (InterpState *) state;
+ Interp *iPtr = (Interp *)interp;
+ InterpState *statePtr = (InterpState *)state;
int status = statePtr->status;
iPtr->flags &= ~ERR_ALREADY_LOGGED;
@@ -137,7 +128,6 @@ Tcl_RestoreInterpState(
iPtr->returnLevel = statePtr->returnLevel;
iPtr->returnCode = statePtr->returnCode;
- iPtr->resetErrorStack = statePtr->resetErrorStack;
if (iPtr->errorInfo) {
Tcl_DecrRefCount(iPtr->errorInfo);
}
@@ -152,13 +142,6 @@ Tcl_RestoreInterpState(
if (iPtr->errorCode) {
Tcl_IncrRefCount(iPtr->errorCode);
}
- if (iPtr->errorStack) {
- Tcl_DecrRefCount(iPtr->errorStack);
- }
- iPtr->errorStack = statePtr->errorStack;
- if (iPtr->errorStack) {
- Tcl_IncrRefCount(iPtr->errorStack);
- }
if (iPtr->returnOpts) {
Tcl_DecrRefCount(iPtr->returnOpts);
}
@@ -192,7 +175,7 @@ void
Tcl_DiscardInterpState(
Tcl_InterpState state) /* saved interpreter state */
{
- InterpState *statePtr = (InterpState *) state;
+ InterpState *statePtr = (InterpState *)state;
if (statePtr->errorInfo) {
Tcl_DecrRefCount(statePtr->errorInfo);
@@ -203,11 +186,8 @@ Tcl_DiscardInterpState(
if (statePtr->returnOpts) {
Tcl_DecrRefCount(statePtr->returnOpts);
}
- if (statePtr->errorStack) {
- Tcl_DecrRefCount(statePtr->errorStack);
- }
Tcl_DecrRefCount(statePtr->objResult);
- ckfree(statePtr);
+ ckfree((char *) statePtr);
}
/*
@@ -232,8 +212,6 @@ Tcl_DiscardInterpState(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
-#undef Tcl_SaveResult
void
Tcl_SaveResult(
Tcl_Interp *interp, /* Interpreter to save. */
@@ -248,7 +226,7 @@ Tcl_SaveResult(
*/
statePtr->objResultPtr = iPtr->objResultPtr;
- TclNewObj(iPtr->objResultPtr);
+ iPtr->objResultPtr = Tcl_NewObj();
Tcl_IncrRefCount(iPtr->objResultPtr);
/*
@@ -308,7 +286,6 @@ Tcl_SaveResult(
*----------------------------------------------------------------------
*/
-#undef Tcl_RestoreResult
void
Tcl_RestoreResult(
Tcl_Interp *interp, /* Interpreter being restored. */
@@ -336,7 +313,7 @@ Tcl_RestoreResult(
*/
if (iPtr->appendResult != NULL) {
- ckfree(iPtr->appendResult);
+ ckfree((char *) iPtr->appendResult);
}
iPtr->appendResult = statePtr->appendResult;
@@ -377,7 +354,6 @@ Tcl_RestoreResult(
*----------------------------------------------------------------------
*/
-#undef Tcl_DiscardResult
void
Tcl_DiscardResult(
Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */
@@ -386,10 +362,12 @@ Tcl_DiscardResult(
if (statePtr->result == statePtr->appendResult) {
ckfree(statePtr->appendResult);
- } else if (statePtr->freeProc == TCL_DYNAMIC) {
- ckfree(statePtr->result);
} else if (statePtr->freeProc) {
- statePtr->freeProc(statePtr->result);
+ if (statePtr->freeProc == TCL_DYNAMIC) {
+ ckfree(statePtr->result);
+ } else {
+ (*statePtr->freeProc)(statePtr->result);
+ }
}
}
@@ -414,14 +392,15 @@ void
Tcl_SetResult(
Tcl_Interp *interp, /* Interpreter with which to associate the
* return value. */
- char *result, /* Value to be returned. If NULL, the result
+ register char *result, /* Value to be returned. If NULL, the result
* is set to an empty string. */
Tcl_FreeProc *freeProc) /* Gives information about the string:
* TCL_STATIC, TCL_VOLATILE, or the address of
* a Tcl_FreeProc such as free. */
{
Interp *iPtr = (Interp *) interp;
- Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
+ int length;
+ register Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
char *oldResult = iPtr->result;
if (result == NULL) {
@@ -429,18 +408,17 @@ Tcl_SetResult(
iPtr->result = iPtr->resultSpace;
iPtr->freeProc = 0;
} else if (freeProc == TCL_VOLATILE) {
- int length = strlen(result);
-
+ length = strlen(result);
if (length > TCL_RESULT_SIZE) {
- iPtr->result = (char *)ckalloc(length + 1);
+ iPtr->result = (char *) ckalloc((unsigned) length+1);
iPtr->freeProc = TCL_DYNAMIC;
} else {
iPtr->result = iPtr->resultSpace;
iPtr->freeProc = 0;
}
- memcpy(iPtr->result, result, length+1);
+ strcpy(iPtr->result, result);
} else {
- iPtr->result = (char *) result;
+ iPtr->result = result;
iPtr->freeProc = freeProc;
}
@@ -454,7 +432,7 @@ Tcl_SetResult(
if (oldFreeProc == TCL_DYNAMIC) {
ckfree(oldResult);
} else {
- oldFreeProc(oldResult);
+ (*oldFreeProc)(oldResult);
}
}
@@ -464,7 +442,6 @@ Tcl_SetResult(
ResetObjResult(iPtr);
}
-#endif /* !TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
@@ -483,26 +460,20 @@ Tcl_SetResult(
*----------------------------------------------------------------------
*/
-#undef Tcl_GetStringResult
-const char *
+CONST char *
Tcl_GetStringResult(
- Tcl_Interp *interp)/* Interpreter whose result to return. */
+ register Tcl_Interp *interp)/* Interpreter whose result to return. */
{
-#ifndef TCL_NO_DEPRECATED
- Interp *iPtr = (Interp *) interp;
/*
* If the string result is empty, move the object result to the string
* result, then reset the object result.
*/
- if (*(iPtr->result) == 0) {
+ if (*(interp->result) == 0) {
Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
TCL_VOLATILE);
}
- return iPtr->result;
-#else
- return TclGetString(Tcl_GetObjResult(interp));
-#endif
+ return interp->result;
}
/*
@@ -528,11 +499,11 @@ void
Tcl_SetObjResult(
Tcl_Interp *interp, /* Interpreter with which to associate the
* return object value. */
- Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj
+ register Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj
* result is made an empty string object. */
{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *oldObjResult = iPtr->objResultPtr;
+ register Interp *iPtr = (Interp *) interp;
+ register Tcl_Obj *oldObjResult = iPtr->objResultPtr;
iPtr->objResultPtr = objPtr;
Tcl_IncrRefCount(objPtr); /* since interp result is a reference */
@@ -544,7 +515,6 @@ Tcl_SetObjResult(
TclDecrRefCount(oldObjResult);
-#ifndef TCL_NO_DEPRECATED
/*
* Reset the string result since we just set the result object.
*/
@@ -553,13 +523,12 @@ Tcl_SetObjResult(
if (iPtr->freeProc == TCL_DYNAMIC) {
ckfree(iPtr->result);
} else {
- iPtr->freeProc(iPtr->result);
+ (*iPtr->freeProc)(iPtr->result);
}
iPtr->freeProc = 0;
}
iPtr->result = iPtr->resultSpace;
iPtr->resultSpace[0] = 0;
-#endif
}
/*
@@ -587,8 +556,7 @@ Tcl_Obj *
Tcl_GetObjResult(
Tcl_Interp *interp) /* Interpreter whose result to return. */
{
- Interp *iPtr = (Interp *) interp;
-#ifndef TCL_NO_DEPRECATED
+ register Interp *iPtr = (Interp *) interp;
Tcl_Obj *objResultPtr;
int length;
@@ -597,7 +565,7 @@ Tcl_GetObjResult(
* result, then reset the string result.
*/
- if (iPtr->result[0] != 0) {
+ if (*(iPtr->result) != 0) {
ResetObjResult(iPtr);
objResultPtr = iPtr->objResultPtr;
@@ -608,14 +576,13 @@ Tcl_GetObjResult(
if (iPtr->freeProc == TCL_DYNAMIC) {
ckfree(iPtr->result);
} else {
- iPtr->freeProc(iPtr->result);
+ (*iPtr->freeProc)(iPtr->result);
}
iPtr->freeProc = 0;
}
iPtr->result = iPtr->resultSpace;
- iPtr->result[0] = 0;
+ iPtr->resultSpace[0] = 0;
}
-#endif /* !TCL_NO_DEPRECATED */
return iPtr->objResultPtr;
}
@@ -652,6 +619,23 @@ Tcl_AppendResultVA(
}
Tcl_AppendStringsToObjVA(objPtr, argList);
Tcl_SetObjResult(interp, objPtr);
+
+ /*
+ * Strictly we should call Tcl_GetStringResult(interp) here to make sure
+ * that interp->result is correct according to the old contract, but that
+ * makes the performance of much code (e.g. in Tk) absolutely awful. So we
+ * leave it out; code that really wants interp->result can just insert the
+ * calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion]
+ */
+
+#ifdef USE_DIRECT_INTERP_RESULT_ACCESS
+ /*
+ * Ensure that the interp->result is legal so old Tcl 7.* code still
+ * works. There's still embarrasingly much of it about...
+ */
+
+ (void) Tcl_GetStringResult(interp);
+#endif /* USE_DIRECT_INTERP_RESULT_ACCESS */
}
/*
@@ -713,29 +697,13 @@ void
Tcl_AppendElement(
Tcl_Interp *interp, /* Interpreter whose result is to be
* extended. */
- const char *element) /* String to convert to list element and add
+ CONST char *element) /* String to convert to list element and add
* to result. */
{
Interp *iPtr = (Interp *) interp;
-#ifdef TCL_NO_DEPRECATED
- Tcl_Obj *elementPtr = Tcl_NewStringObj(element, -1);
- Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr);
- const char *bytes;
-
- if (Tcl_IsShared(iPtr->objResultPtr)) {
- Tcl_SetObjResult(interp, Tcl_DuplicateObj(iPtr->objResultPtr));
- }
- bytes = TclGetString(iPtr->objResultPtr);
- if (TclNeedSpace(bytes, bytes+iPtr->objResultPtr->length)) {
- Tcl_AppendToObj(iPtr->objResultPtr, " ", 1);
- }
- Tcl_AppendObjToObj(iPtr->objResultPtr, listPtr);
- Tcl_DecrRefCount(listPtr);
-#else
char *dst;
int size;
int flags;
- int quoteHash = 1;
/*
* If the string result is empty, move the object result to the string
@@ -772,19 +740,10 @@ Tcl_AppendElement(
* then this element will not lead a list, and need not have it's
* leading '#' quoted.
*/
- quoteHash = 0;
- } else {
- while ((--dst >= iPtr->appendResult) && TclIsSpaceProcM(*dst)) {
- }
- quoteHash = !TclNeedSpace(iPtr->appendResult, dst+1);
- }
- dst = iPtr->appendResult + iPtr->appendUsed;
- if (!quoteHash) {
+
flags |= TCL_DONT_QUOTE_HASH;
}
-
iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
-#endif /* !TCL_NO_DEPRECATED */
}
/*
@@ -806,7 +765,6 @@ Tcl_AppendElement(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
static void
SetupAppendBuffer(
Interp *iPtr, /* Interpreter whose result is being set up. */
@@ -846,19 +804,19 @@ SetupAppendBuffer(
totalSpace = newSpace + iPtr->appendUsed;
if (totalSpace >= iPtr->appendAvl) {
- char *newSpacePtr;
+ char *new;
if (totalSpace < 100) {
totalSpace = 200;
} else {
totalSpace *= 2;
}
- newSpacePtr = (char *)ckalloc(totalSpace);
- strcpy(newSpacePtr, iPtr->result);
+ new = (char *) ckalloc((unsigned) totalSpace);
+ strcpy(new, iPtr->result);
if (iPtr->appendResult != NULL) {
ckfree(iPtr->appendResult);
}
- iPtr->appendResult = newSpacePtr;
+ iPtr->appendResult = new;
iPtr->appendAvl = totalSpace;
} else if (iPtr->result != iPtr->appendResult) {
strcpy(iPtr->appendResult, iPtr->result);
@@ -892,23 +850,22 @@ SetupAppendBuffer(
void
Tcl_FreeResult(
- Tcl_Interp *interp)/* Interpreter for which to free result. */
+ register Tcl_Interp *interp)/* Interpreter for which to free result. */
{
- Interp *iPtr = (Interp *) interp;
+ register Interp *iPtr = (Interp *) interp;
if (iPtr->freeProc != NULL) {
if (iPtr->freeProc == TCL_DYNAMIC) {
ckfree(iPtr->result);
} else {
- iPtr->freeProc(iPtr->result);
+ (*iPtr->freeProc)(iPtr->result);
}
iPtr->freeProc = 0;
}
ResetObjResult(iPtr);
}
-#endif /* !TCL_NO_DEPRECATED */
-
+
/*
*----------------------------------------------------------------------
*
@@ -930,23 +887,21 @@ Tcl_FreeResult(
void
Tcl_ResetResult(
- Tcl_Interp *interp)/* Interpreter for which to clear result. */
+ register Tcl_Interp *interp)/* Interpreter for which to clear result. */
{
- Interp *iPtr = (Interp *) interp;
+ register Interp *iPtr = (Interp *) interp;
ResetObjResult(iPtr);
-#ifndef TCL_NO_DEPRECATED
if (iPtr->freeProc != NULL) {
if (iPtr->freeProc == TCL_DYNAMIC) {
ckfree(iPtr->result);
} else {
- iPtr->freeProc(iPtr->result);
+ (*iPtr->freeProc)(iPtr->result);
}
iPtr->freeProc = 0;
}
iPtr->result = iPtr->resultSpace;
iPtr->resultSpace[0] = 0;
-#endif /* !TCL_NO_DEPRECATED */
if (iPtr->errorCode) {
/* Legacy support */
if (iPtr->flags & ERR_LEGACY_COPY) {
@@ -965,7 +920,6 @@ Tcl_ResetResult(
Tcl_DecrRefCount(iPtr->errorInfo);
iPtr->errorInfo = NULL;
}
- iPtr->resetErrorStack = 1;
iPtr->returnLevel = 1;
iPtr->returnCode = TCL_OK;
if (iPtr->returnOpts) {
@@ -995,10 +949,10 @@ Tcl_ResetResult(
static void
ResetObjResult(
- Interp *iPtr) /* Points to the interpreter whose result
+ register Interp *iPtr) /* Points to the interpreter whose result
* object should be reset. */
{
- Tcl_Obj *objResultPtr = iPtr->objResultPtr;
+ register Tcl_Obj *objResultPtr = iPtr->objResultPtr;
if (Tcl_IsShared(objResultPtr)) {
TclDecrRefCount(objResultPtr);
@@ -1006,14 +960,15 @@ ResetObjResult(
Tcl_IncrRefCount(objResultPtr);
iPtr->objResultPtr = objResultPtr;
} else {
- if (objResultPtr->bytes != &tclEmptyString) {
+ if (objResultPtr->bytes != tclEmptyStringRep) {
if (objResultPtr->bytes) {
- ckfree(objResultPtr->bytes);
+ ckfree((char *) objResultPtr->bytes);
}
- objResultPtr->bytes = &tclEmptyString;
+ objResultPtr->bytes = tclEmptyStringRep;
objResultPtr->length = 0;
}
- TclFreeInternalRep(objResultPtr);
+ TclFreeIntRep(objResultPtr);
+ objResultPtr->typePtr = NULL;
}
}
@@ -1041,17 +996,15 @@ Tcl_SetErrorCodeVA(
Tcl_Interp *interp, /* Interpreter in which to set errorCode */
va_list argList) /* Variable argument list. */
{
- Tcl_Obj *errorObj;
+ Tcl_Obj *errorObj = Tcl_NewObj();
/*
* Scan through the arguments one at a time, appending them to the
* errorCode field as list elements.
*/
- TclNewObj(errorObj);
while (1) {
char *elem = va_arg(argList, char *);
-
if (elem == NULL) {
break;
}
@@ -1130,43 +1083,6 @@ Tcl_SetObjErrorCode(
/*
*----------------------------------------------------------------------
*
- * Tcl_GetErrorLine --
- *
- * Returns the line number associated with the current error.
- *
- *----------------------------------------------------------------------
- */
-
-#undef Tcl_GetErrorLine
-int
-Tcl_GetErrorLine(
- Tcl_Interp *interp)
-{
- return ((Interp *) interp)->errorLine;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_SetErrorLine --
- *
- * Sets the line number associated with the current error.
- *
- *----------------------------------------------------------------------
- */
-
-#undef Tcl_SetErrorLine
-void
-Tcl_SetErrorLine(
- Tcl_Interp *interp,
- int value)
-{
- ((Interp *) interp)->errorLine = value;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* GetKeys --
*
* Returns a Tcl_Obj * array of the standard keys used in the return
@@ -1179,8 +1095,8 @@ Tcl_SetErrorLine(
* A Tcl_Obj * array.
*
* Side effects:
- * First time called in a thread, creates the keys (allocating memory)
- * and arranges for their cleanup at thread exit.
+ * First time called in a thread, creates the keys (allocating memory)
+ * and arranges for their cleanup at thread exit.
*
*----------------------------------------------------------------------
*/
@@ -1189,8 +1105,8 @@ static Tcl_Obj **
GetKeys(void)
{
static Tcl_ThreadDataKey returnKeysKey;
- Tcl_Obj **keys = (Tcl_Obj **)Tcl_GetThreadData(&returnKeysKey,
- KEY_LAST * sizeof(Tcl_Obj *));
+ Tcl_Obj **keys = Tcl_GetThreadData(&returnKeysKey,
+ (int) (KEY_LAST * sizeof(Tcl_Obj *)));
if (keys[0] == NULL) {
/*
@@ -1203,7 +1119,6 @@ GetKeys(void)
TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode");
TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo");
TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline");
- TclNewLiteralStringObj(keys[KEY_ERRORSTACK],"-errorstack");
TclNewLiteralStringObj(keys[KEY_LEVEL], "-level");
TclNewLiteralStringObj(keys[KEY_OPTIONS], "-options");
@@ -1215,7 +1130,7 @@ GetKeys(void)
* ... and arrange for their clenaup.
*/
- Tcl_CreateThreadExitHandler(ReleaseKeys, keys);
+ Tcl_CreateThreadExitHandler(ReleaseKeys, (ClientData) keys);
}
return keys;
}
@@ -1232,7 +1147,7 @@ GetKeys(void)
* None.
*
* Side effects:
- * Frees memory.
+ * Frees memory.
*
*----------------------------------------------------------------------
*/
@@ -1265,7 +1180,7 @@ ReleaseKeys(
* Returns the return code the [return] command should return.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -1298,60 +1213,25 @@ TclProcessReturn(
Tcl_DecrRefCount(iPtr->errorInfo);
iPtr->errorInfo = NULL;
}
- Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
- &valuePtr);
+ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr);
if (valuePtr != NULL) {
- (void) TclGetString(valuePtr);
- if (valuePtr->length) {
+ int infoLen;
+
+ (void) TclGetStringFromObj(valuePtr, &infoLen);
+ if (infoLen) {
iPtr->errorInfo = valuePtr;
Tcl_IncrRefCount(iPtr->errorInfo);
iPtr->flags |= ERR_ALREADY_LOGGED;
}
}
- Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORSTACK],
- &valuePtr);
- if (valuePtr != NULL) {
- int len, valueObjc;
- Tcl_Obj **valueObjv;
-
- if (Tcl_IsShared(iPtr->errorStack)) {
- Tcl_Obj *newObj;
-
- newObj = Tcl_DuplicateObj(iPtr->errorStack);
- Tcl_DecrRefCount(iPtr->errorStack);
- Tcl_IncrRefCount(newObj);
- iPtr->errorStack = newObj;
- }
-
- /*
- * List extraction done after duplication to avoid moving the rug
- * if someone does [return -errorstack [info errorstack]]
- */
-
- if (TclListObjGetElements(interp, valuePtr, &valueObjc,
- &valueObjv) == TCL_ERROR) {
- return TCL_ERROR;
- }
- iPtr->resetErrorStack = 0;
- TclListObjLength(interp, iPtr->errorStack, &len);
-
- /*
- * Reset while keeping the list internalrep as much as possible.
- */
-
- Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc,
- valueObjv);
- }
- Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE],
- &valuePtr);
+ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr);
if (valuePtr != NULL) {
Tcl_SetObjErrorCode(interp, valuePtr);
} else {
- Tcl_SetErrorCode(interp, "NONE", (void *)NULL);
+ Tcl_SetErrorCode(interp, "NONE", NULL);
}
- Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE],
- &valuePtr);
+ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr);
if (valuePtr != NULL) {
TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
}
@@ -1375,12 +1255,12 @@ TclProcessReturn(
* Parses, checks, and stores the options to the [return] command.
*
* Results:
- * Returns TCL_ERROR if any of the option values are invalid. Otherwise,
+ * Returns TCL_ERROR is any of the option values are invalid. Otherwise,
* returns TCL_OK, and writes the returnOpts, code, and level values to
* the pointers provided.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -1388,29 +1268,30 @@ TclProcessReturn(
int
TclMergeReturnOptions(
Tcl_Interp *interp, /* Current interpreter. */
- Tcl_Size objc, /* Number of arguments. */
- Tcl_Obj *const objv[], /* Argument objects. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[], /* Argument objects. */
Tcl_Obj **optionsPtrPtr, /* If not NULL, points to space for a (Tcl_Obj
* *) where the pointer to the merged return
- * options dictionary should be written. */
+ * options dictionary should be written */
int *codePtr, /* If not NULL, points to space where the
- * -code value should be written. */
+ * -code value should be written */
int *levelPtr) /* If not NULL, points to space where the
- * -level value should be written. */
+ * -level value should be written */
{
- int code = TCL_OK;
+ int code=TCL_OK;
int level = 1;
Tcl_Obj *valuePtr;
- Tcl_Obj *returnOpts;
+ Tcl_Obj *returnOpts = Tcl_NewObj();
Tcl_Obj **keys = GetKeys();
- TclNewObj(returnOpts);
for (; objc > 1; objv += 2, objc -= 2) {
- const char *opt = TclGetString(objv[0]);
- const char *compare = TclGetString(keys[KEY_OPTIONS]);
+ int optLen;
+ CONST char *opt = TclGetStringFromObj(objv[0], &optLen);
+ int compareLen;
+ CONST char *compare =
+ TclGetStringFromObj(keys[KEY_OPTIONS], &compareLen);
- if ((objv[0]->length == keys[KEY_OPTIONS]->length)
- && (memcmp(opt, compare, objv[0]->length) == 0)) {
+ if ((optLen == compareLen) && (strcmp(opt, compare) == 0)) {
Tcl_DictSearch search;
int done = 0;
Tcl_Obj *keyPtr;
@@ -1423,11 +1304,10 @@ TclMergeReturnOptions(
* Value is not a legal dictionary.
*/
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad %s value: expected dictionary but got \"%s\"",
- compare, TclGetString(objv[1])));
- Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS",
- (void *)NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad ", compare,
+ " value: expected dictionary but got \"",
+ TclGetString(objv[1]), "\"", NULL);
goto error;
}
@@ -1453,11 +1333,27 @@ TclMergeReturnOptions(
*/
Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
- if (valuePtr != NULL) {
- if (TclGetCompletionCodeFromObj(interp, valuePtr,
- &code) == TCL_ERROR) {
+ if ((valuePtr != NULL)
+ && (TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &code))) {
+ static CONST char *returnCodes[] = {
+ "ok", "error", "return", "break", "continue", NULL
+ };
+
+ if (TCL_ERROR == Tcl_GetIndexFromObj(NULL, valuePtr, returnCodes,
+ NULL, TCL_EXACT, &code)) {
+ /*
+ * Value is not a legal return code.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad completion code \"",
+ TclGetString(valuePtr),
+ "\": must be ok, error, return, break, "
+ "continue, or an integer", NULL);
goto error;
}
+ }
+ if (valuePtr != NULL) {
Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]);
}
@@ -1473,10 +1369,10 @@ TclMergeReturnOptions(
* Value is not a legal level.
*/
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad -level value: expected non-negative integer but got"
- " \"%s\"", TclGetString(valuePtr)));
- Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_LEVEL", (void *)NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad -level value: "
+ "expected non-negative integer but got \"",
+ TclGetString(valuePtr), "\"", NULL);
goto error;
}
Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]);
@@ -1490,52 +1386,16 @@ TclMergeReturnOptions(
if (valuePtr != NULL) {
int length;
- if (TCL_ERROR == TclListObjLength(NULL, valuePtr, &length )) {
+ if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) {
/*
* Value is not a list, which is illegal for -errorcode.
*/
-
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad -errorcode value: expected a list but got \"%s\"",
- TclGetString(valuePtr)));
- Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_ERRORCODE",
- (void *)NULL);
- goto error;
- }
- }
-
- /*
- * Check for bogus -errorstack value.
- */
-
- Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr);
- if (valuePtr != NULL) {
- int length;
-
- if (TCL_ERROR == TclListObjLength(NULL, valuePtr, &length )) {
- /*
- * Value is not a list, which is illegal for -errorstack.
- */
-
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "bad -errorstack value: expected a list but got \"%s\"",
- TclGetString(valuePtr)));
- Tcl_SetErrorCode(interp, "TCL", "RESULT", "NONLIST_ERRORSTACK",
- (void *)NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad -errorcode value: "
+ "expected a list but got \"",
+ TclGetString(valuePtr), "\"", NULL);
goto error;
}
- if (length % 2) {
- /*
- * Errorstack must always be an even-sized list
- */
-
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "forbidden odd-sized list for -errorstack: \"%s\"",
- TclGetString(valuePtr)));
- Tcl_SetErrorCode(interp, "TCL", "RESULT",
- "ODDSIZEDLIST_ERRORSTACK", (void *)NULL);
- goto error;
- }
}
/*
@@ -1598,24 +1458,23 @@ Tcl_GetReturnOptions(
if (iPtr->returnOpts) {
options = Tcl_DuplicateObj(iPtr->returnOpts);
} else {
- TclNewObj(options);
+ options = Tcl_NewObj();
}
if (result == TCL_RETURN) {
Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
- Tcl_NewWideIntObj(iPtr->returnCode));
+ Tcl_NewIntObj(iPtr->returnCode));
Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
- Tcl_NewWideIntObj(iPtr->returnLevel));
+ Tcl_NewIntObj(iPtr->returnLevel));
} else {
Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
- Tcl_NewWideIntObj(result));
+ Tcl_NewIntObj(result));
Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
- Tcl_NewWideIntObj(0));
+ Tcl_NewIntObj(0));
}
if (result == TCL_ERROR) {
- Tcl_AddErrorInfo(interp, "");
- Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack);
+ Tcl_AddObjErrorInfo(interp, "", -1);
}
if (iPtr->errorCode) {
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode);
@@ -1623,7 +1482,7 @@ Tcl_GetReturnOptions(
if (iPtr->errorInfo) {
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo);
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
- Tcl_NewWideIntObj(iPtr->errorLine));
+ Tcl_NewIntObj(iPtr->errorLine));
}
return options;
}
@@ -1631,31 +1490,6 @@ Tcl_GetReturnOptions(
/*
*-------------------------------------------------------------------------
*
- * TclNoErrorStack --
- *
- * Removes the -errorstack entry from an options dict to avoid reference
- * cycles.
- *
- * Results:
- * The (unshared) argument options dict, modified in -place.
- *
- *-------------------------------------------------------------------------
- */
-
-Tcl_Obj *
-TclNoErrorStack(
- Tcl_Interp *interp,
- Tcl_Obj *options)
-{
- Tcl_Obj **keys = GetKeys();
-
- Tcl_DictObjRemove(interp, options, keys[KEY_ERRORSTACK]);
- return options;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
* Tcl_SetReturnOptions --
*
* Accepts an interp and a dictionary of return options, and sets the
@@ -1684,9 +1518,9 @@ Tcl_SetReturnOptions(
Tcl_IncrRefCount(options);
if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
|| (objc % 2)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "expected dict but got \"%s\"", TclGetString(options)));
- Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS", (void *)NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "expected dict but got \"",
+ TclGetString(options), "\"", NULL);
code = TCL_ERROR;
} else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
&mergedOpts, &code, &level)) {
@@ -1702,16 +1536,24 @@ Tcl_SetReturnOptions(
/*
*-------------------------------------------------------------------------
*
- * Tcl_TransferResult --
+ * TclTransferResult --
*
- * Transfer the result (and error information) from one interp to another.
+ * Copy the result (and error information) from one interp to another.
* Used when one interp has caused another interp to evaluate a script
* and then wants to transfer the results back to itself.
*
+ * This routine copies the string reps of the result and error
+ * information. It does not simply increment the refcounts of the result
+ * and error information objects themselves. It is not legal to exchange
+ * objects between interps, because an object may be kept alive by one
+ * interp, but have an internal rep that is only valid while some other
+ * interp is alive.
+ *
* Results:
- * The result of targetInterp is set to the result read from sourceInterp.
- * The return options dictionary of sourceInterp is transferred to
- * targetInterp as appropriate for the return code value code.
+ * The target interp's result is set to a copy of the source interp's
+ * result. The source's errorInfo field may be transferred to the
+ * target's errorInfo field, and the source's errorCode field may be
+ * transferred to the target's errorCode field.
*
* Side effects:
* None.
@@ -1720,17 +1562,15 @@ Tcl_SetReturnOptions(
*/
void
-Tcl_TransferResult(
- Tcl_Interp *sourceInterp, /* Interp whose result and return options
+TclTransferResult(
+ Tcl_Interp *sourceInterp, /* Interp whose result and error information
* should be moved to the target interp.
* After moving result, this interp's result
* is reset. */
- int code, /* The return code value active in
- * sourceInterp. Controls how the return options
- * dictionary is retrieved from sourceInterp,
- * same as in Tcl_GetReturnOptions, to then be
- * transferred to targetInterp. */
- Tcl_Interp *targetInterp) /* Interp where result and return options
+ int result, /* TCL_OK if just the result should be copied,
+ * TCL_ERROR if both the result and error
+ * information should be copied. */
+ Tcl_Interp *targetInterp) /* Interp where result and error information
* should be stored. If source and target are
* the same, nothing is done. */
{
@@ -1741,7 +1581,7 @@ Tcl_TransferResult(
return;
}
- if (code == TCL_OK && siPtr->returnOpts == NULL) {
+ if (result == TCL_OK && siPtr->returnOpts == NULL) {
/*
* Special optimization for the common case of normal command return
* code and no explicit return options.
@@ -1753,7 +1593,7 @@ Tcl_TransferResult(
}
} else {
Tcl_SetReturnOptions(targetInterp,
- Tcl_GetReturnOptions(sourceInterp, code));
+ Tcl_GetReturnOptions(sourceInterp, result));
tiPtr->flags &= ~(ERR_ALREADY_LOGGED);
}
Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp));
@@ -1765,7 +1605,5 @@ Tcl_TransferResult(
* mode: c
* c-basic-offset: 4
* fill-column: 78
- * tab-width: 8
- * indent-tabs-mode: nil
* End:
*/