From 88574b7bc539d00b6477f8d9bbe7f25158b57662 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 18 Apr 2012 18:42:54 +0000 Subject: Experimental branch where the interp->result field and related are removed and all simplifications that makes possible are done. Seems this can at best be a Tcl 9 reform. --- generic/tcl.h | 16 +++++++++------- generic/tclBasic.c | 42 +++++++++++++++++++++++++++++++++++------- generic/tclHistory.c | 2 ++ generic/tclInt.h | 15 +++++++++++++++ generic/tclResult.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ generic/tclStubLib.c | 8 +++++++- generic/tclTest.c | 13 +++++++++++++ generic/tclUtil.c | 13 +++++++++++++ 8 files changed, 146 insertions(+), 15 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 729e521..46266d2 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -499,7 +499,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt; * Instead, they set a Tcl_Obj member in the "real" structure that can be * accessed with Tcl_GetObjResult() and Tcl_SetObjResult(). */ - +#if 0 typedef struct Tcl_Interp { /* TIP #330: Strongly discourage extensions from using the string * result. */ @@ -529,6 +529,8 @@ typedef struct Tcl_Interp { int unused5 TCL_DEPRECATED_API("bad field access"); #endif } Tcl_Interp; +#endif +typedef struct Tcl_Interp Tcl_Interp; typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler; typedef struct Tcl_Channel_ *Tcl_Channel; @@ -870,13 +872,13 @@ int Tcl_IsShared(Tcl_Obj *objPtr); */ typedef struct Tcl_SavedResult { - char *result; - Tcl_FreeProc *freeProc; + char *unused1; + Tcl_FreeProc *unused2; Tcl_Obj *objResultPtr; - char *appendResult; - int appendAvl; - int appendUsed; - char resultSpace[TCL_RESULT_SIZE+1]; + char *unused3; + int unused4; + int unused5; + char unused6[TCL_RESULT_SIZE+1]; } Tcl_SavedResult; /* diff --git a/generic/tclBasic.c b/generic/tclBasic.c index e09ea1e..d55faeb 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -503,8 +503,10 @@ Tcl_CreateInterp(void) iPtr = ckalloc(sizeof(Interp)); interp = (Tcl_Interp *) iPtr; +#if 0 iPtr->result = iPtr->resultSpace; iPtr->freeProc = NULL; +#endif iPtr->errorLine = 0; iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); @@ -560,9 +562,11 @@ Tcl_CreateInterp(void) iPtr->rootFramePtr = NULL; /* Initialise as soon as :: is available */ iPtr->lookupNsPtr = NULL; +#if 0 iPtr->appendResult = NULL; iPtr->appendAvl = 0; iPtr->appendUsed = 0; +#endif Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS); iPtr->packageUnknown = NULL; @@ -591,7 +595,9 @@ Tcl_CreateInterp(void) iPtr->emptyObjPtr = Tcl_NewObj(); /* Another empty object. */ Tcl_IncrRefCount(iPtr->emptyObjPtr); +#if 0 iPtr->resultSpace[0] = 0; +#endif iPtr->threadId = Tcl_GetCurrentThread(); /* TIP #378 */ @@ -1493,7 +1499,9 @@ DeleteInterpProc( */ Tcl_FreeResult(interp); +#if 0 iPtr->result = NULL; +#endif Tcl_DecrRefCount(iPtr->objResultPtr); iPtr->objResultPtr = NULL; Tcl_DecrRefCount(iPtr->ecVar); @@ -1515,10 +1523,12 @@ DeleteInterpProc( if (iPtr->returnOpts) { Tcl_DecrRefCount(iPtr->returnOpts); } +#if 0 if (iPtr->appendResult != NULL) { ckfree(iPtr->appendResult); iPtr->appendResult = NULL; } +#endif TclFreePackageInfo(iPtr); while (iPtr->tracePtr != NULL) { Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr); @@ -2385,7 +2395,7 @@ TclInvokeStringCommand( * in the Command structure. * * Results: - * A standard Tcl string result value. + * A standard Tcl result value. * * Side effects: * Besides those side effects of the called Tcl_CmdProc, @@ -2425,12 +2435,14 @@ TclInvokeObjectCommand( cmdPtr->objClientData, argc, objv); } +#if 0 /* * Move the interpreter's object result to the string result, then reset * the object result. */ (void) Tcl_GetStringResult(interp); +#endif /* * Decrement the ref counts for the argument objects created above, then @@ -3800,7 +3812,7 @@ Tcl_ListMathFuncs( * otherwise. * * Side effects: - * The interpreters object and string results are cleared. + * The interpreter's result is cleared. * *---------------------------------------------------------------------- */ @@ -3812,8 +3824,8 @@ TclInterpReady( register Interp *iPtr = (Interp *) interp; /* - * Reset both the interpreter's string and object results and clear out - * any previous error information. + * Reset the interpreter's result and clear out any previous error + * information. */ Tcl_ResetResult(interp); @@ -4333,10 +4345,11 @@ TclNRRunCallbacks( /* All callbacks down to rootPtr not inclusive * are to be run. */ { - Interp *iPtr = (Interp *) interp; +/* Interp *iPtr = (Interp *) interp;*/ NRE_callback *callbackPtr; Tcl_NRPostProc *procPtr; +#if 0 /* * If the interpreter has a non-empty string result, the result object is * either empty or stale because some function set interp->result @@ -4350,6 +4363,7 @@ TclNRRunCallbacks( if (*(iPtr->result) != 0) { (void) Tcl_GetObjResult(interp); } +#endif while (TOP_CB(interp) != rootPtr) { callbackPtr = TOP_CB(interp); @@ -5828,6 +5842,7 @@ Tcl_Eval( * previous call to Tcl_CreateInterp). */ const char *script) /* Pointer to TCL command to execute. */ { +#if 0 int code = Tcl_EvalEx(interp, script, -1, 0); /* @@ -5838,6 +5853,8 @@ Tcl_Eval( (void) Tcl_GetStringResult(interp); return code; +#endif + return Tcl_EvalEx(interp, script, -1, 0); } /* @@ -6335,9 +6352,11 @@ Tcl_ExprLong( Tcl_IncrRefCount(exprPtr); result = Tcl_ExprLongObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); +#if 0 if (result != TCL_OK) { (void) Tcl_GetStringResult(interp); } +#endif } return result; } @@ -6364,9 +6383,11 @@ Tcl_ExprDouble( result = Tcl_ExprDoubleObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); /* Discard the expression object. */ +#if 0 if (result != TCL_OK) { (void) Tcl_GetStringResult(interp); } +#endif } return result; } @@ -6392,6 +6413,7 @@ Tcl_ExprBoolean( Tcl_IncrRefCount(exprPtr); result = Tcl_ExprBooleanObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); +#if 0 if (result != TCL_OK) { /* * Move the interpreter's object result to the string result, then @@ -6400,6 +6422,7 @@ Tcl_ExprBoolean( (void) Tcl_GetStringResult(interp); } +#endif return result; } } @@ -6724,12 +6747,13 @@ Tcl_ExprString( Tcl_DecrRefCount(resultPtr); } } - +#if 0 /* * Force the string rep of the interp result. */ (void) Tcl_GetStringResult(interp); +#endif return code; } @@ -6833,6 +6857,7 @@ Tcl_AddObjErrorInfo( iPtr->flags |= ERR_LEGACY_COPY; if (iPtr->errorInfo == NULL) { +#if 0 if (iPtr->result[0] != 0) { /* * The interp's string result is set, apparently by some extension @@ -6844,8 +6869,11 @@ Tcl_AddObjErrorInfo( iPtr->errorInfo = Tcl_NewStringObj(iPtr->result, -1); } else { +#endif iPtr->errorInfo = iPtr->objResultPtr; +#if 0 } +#endif Tcl_IncrRefCount(iPtr->errorInfo); if (!iPtr->errorCode) { Tcl_SetErrorCode(interp, "NONE", NULL); @@ -6923,7 +6951,7 @@ Tcl_VarEvalVA( * * Results: * A standard Tcl return result. An error message or other result may be - * left in interp->result. + * left in the interp. * * Side effects: * Depends on what was done by the command. diff --git a/generic/tclHistory.c b/generic/tclHistory.c index b10d423..5448365 100644 --- a/generic/tclHistory.c +++ b/generic/tclHistory.c @@ -74,12 +74,14 @@ Tcl_RecordAndEval( Tcl_IncrRefCount(cmdPtr); result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags); +#if 0 /* * Move the interpreter's object result to the string result, then * reset the object result. */ (void) Tcl_GetStringResult(interp); +#endif /* * Discard the Tcl object created to hold the command. diff --git a/generic/tclInt.h b/generic/tclInt.h index 08b3f70..0d541a8 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -1811,6 +1811,7 @@ typedef struct Interp { * Tcl_GetStringResult. See the SetResult man page for details. */ +#if 0 char *result; /* If the last command returned a string * result, this points to it. Should not be * accessed directly; see comment above. */ @@ -1821,6 +1822,10 @@ typedef struct Interp { * address of procedure to invoke to free the * string result. Tcl_Eval must free it before * executing next command. */ +#else + char *unused3; + Tcl_FreeProc *unused4; +#endif int errorLine; /* When TCL_ERROR is returned, this gives the * line number in the command where the error * occurred (1 means first line). */ @@ -1878,6 +1883,7 @@ typedef struct Interp { * See Tcl_AppendResult code for details. */ +#if 0 char *appendResult; /* Storage space for results generated by * Tcl_AppendResult. Ckalloc-ed. NULL means * not yet allocated. */ @@ -1885,6 +1891,11 @@ typedef struct Interp { * partialResult. */ int appendUsed; /* Number of non-null bytes currently stored * at partialResult. */ +#else + char *unused5; + int unused6; + int unused7; +#endif /* * Information about packages. Used only in tclPkg.c. @@ -1946,8 +1957,12 @@ typedef struct Interp { * string. Returned by Tcl_ObjSetVar2 when * variable traces change a variable in a * gross way. */ +#if 0 char resultSpace[TCL_RESULT_SIZE+1]; /* Static space holding small results. */ +#else + char unused8[TCL_RESULT_SIZE+1]; +#endif Tcl_Obj *objResultPtr; /* If the last command returned an object * result, this points to it. Should not be * accessed directly; see comment above. */ diff --git a/generic/tclResult.c b/generic/tclResult.c index 4443cc1..cbaefcb 100644 --- a/generic/tclResult.c +++ b/generic/tclResult.c @@ -27,7 +27,9 @@ enum returnKeys { static Tcl_Obj ** GetKeys(void); static void ReleaseKeys(ClientData clientData); static void ResetObjResult(Interp *iPtr); +#if 0 static void SetupAppendBuffer(Interp *iPtr, int newSpace); +#endif /* * This structure is used to take a snapshot of the interpreter state in @@ -247,6 +249,7 @@ Tcl_SaveResult( iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); +#if 0 /* * Save the string result. */ @@ -284,6 +287,7 @@ Tcl_SaveResult( iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; iPtr->freeProc = 0; +#endif } /* @@ -313,6 +317,7 @@ Tcl_RestoreResult( Tcl_ResetResult(interp); +#if 0 /* * Restore the string result. */ @@ -345,6 +350,7 @@ Tcl_RestoreResult( iPtr->result = statePtr->result; } +#endif /* * Restore the object result. @@ -378,6 +384,7 @@ Tcl_DiscardResult( { TclDecrRefCount(statePtr->objResultPtr); +#if 0 if (statePtr->result == statePtr->appendResult) { ckfree(statePtr->appendResult); } else if (statePtr->freeProc) { @@ -387,6 +394,7 @@ Tcl_DiscardResult( statePtr->freeProc(statePtr->result); } } +#endif } /* @@ -416,6 +424,7 @@ Tcl_SetResult( * TCL_STATIC, TCL_VOLATILE, or the address of * a Tcl_FreeProc such as free. */ { +#if 0 Interp *iPtr = (Interp *) interp; register Tcl_FreeProc *oldFreeProc = iPtr->freeProc; char *oldResult = iPtr->result; @@ -459,6 +468,17 @@ Tcl_SetResult( */ ResetObjResult(iPtr); +#else + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); + if (result == NULL || freeProc == NULL || freeProc == TCL_VOLATILE) { + return; + } + if (freeProc == TCL_DYNAMIC) { + ckfree(result); + } else { + (*freeProc)(result); + } +#endif } /* @@ -482,6 +502,7 @@ const char * Tcl_GetStringResult( register Tcl_Interp *interp)/* Interpreter whose result to return. */ { +#if 0 /* * If the string result is empty, move the object result to the string * result, then reset the object result. @@ -494,6 +515,10 @@ Tcl_GetStringResult( TCL_VOLATILE); } return iPtr->result; +#else + Interp *iPtr = (Interp *)interp; + return Tcl_GetString(iPtr->objResultPtr); +#endif } /* @@ -535,6 +560,7 @@ Tcl_SetObjResult( TclDecrRefCount(oldObjResult); +#if 0 /* * Reset the string result since we just set the result object. */ @@ -549,6 +575,7 @@ Tcl_SetObjResult( } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; +#endif } /* @@ -577,6 +604,7 @@ Tcl_GetObjResult( Tcl_Interp *interp) /* Interpreter whose result to return. */ { register Interp *iPtr = (Interp *) interp; +#if 0 Tcl_Obj *objResultPtr; int length; @@ -603,6 +631,7 @@ Tcl_GetObjResult( iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; } +#endif return iPtr->objResultPtr; } @@ -721,6 +750,7 @@ Tcl_AppendElement( * to result. */ { Interp *iPtr = (Interp *) interp; +#if 0 char *dst; int size; int flags; @@ -764,7 +794,24 @@ Tcl_AppendElement( flags |= TCL_DONT_QUOTE_HASH; } iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags); +#else + Tcl_Obj *elementPtr = Tcl_NewStringObj(element, -1); + Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr); + int length; + const char *bytes; + + if (Tcl_IsShared(iPtr->objResultPtr)) { + Tcl_SetObjResult(interp, Tcl_DuplicateObj(iPtr->objResultPtr)); + } + bytes = Tcl_GetStringFromObj(iPtr->objResultPtr, &length); + if (TclNeedSpace(bytes, bytes+length)) { + Tcl_AppendToObj(iPtr->objResultPtr, " ", 1); + } + Tcl_AppendObjToObj(iPtr->objResultPtr, listPtr); + Tcl_DecrRefCount(listPtr); +#endif } +#if 0 /* *---------------------------------------------------------------------- @@ -845,6 +892,7 @@ SetupAppendBuffer( Tcl_FreeResult((Tcl_Interp *) iPtr); iPtr->result = iPtr->appendResult; } +#endif /* *---------------------------------------------------------------------- @@ -874,6 +922,7 @@ Tcl_FreeResult( { register Interp *iPtr = (Interp *) interp; +#if 0 if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { ckfree(iPtr->result); @@ -882,6 +931,7 @@ Tcl_FreeResult( } iPtr->freeProc = 0; } +#endif ResetObjResult(iPtr); } @@ -912,6 +962,7 @@ Tcl_ResetResult( register Interp *iPtr = (Interp *) interp; ResetObjResult(iPtr); +#if 0 if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { ckfree(iPtr->result); @@ -922,6 +973,7 @@ Tcl_ResetResult( } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; +#endif if (iPtr->errorCode) { /* Legacy support */ if (iPtr->flags & ERR_LEGACY_COPY) { diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index f569820..71933a0 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -41,10 +41,16 @@ HasStubSupport( if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) { return iPtr->stubTable; } - +#if 0 iPtr->result = (char *)"This interpreter does not support stubs-enabled extensions."; iPtr->freeProc = TCL_STATIC; +#else + Tcl_Obj errorMsg = {2, + "This interpreter does not support stubs-enabled extensions.", + 59, NULL, {0}}; + iPtr->objResultPtr = &errorMsg; +#endif return NULL; } diff --git a/generic/tclTest.c b/generic/tclTest.c index 37ec751..1a189c7 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -120,12 +120,14 @@ typedef struct TclEncoding { char *fromUtfCmd; } TclEncoding; +#if 0 /* * The counter below is used to determine if the TestsaveresultFree routine * was called for a result. */ static int freeCount; +#endif /* * Boolean flag used by the "testsetmainloop" and "testexitmainloop" commands. @@ -5063,7 +5065,9 @@ TestsaveresultCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { +#if 0 Interp* iPtr = (Interp*) interp; +#endif int discard, result, index; Tcl_SavedResult state; Tcl_Obj *objPtr; @@ -5114,7 +5118,9 @@ TestsaveresultCmd( break; } +#if 0 freeCount = 0; +#endif Tcl_SaveResult(interp, &state); if (((enum options) index) == RESULT_OBJECT) { @@ -5132,11 +5138,16 @@ TestsaveresultCmd( switch ((enum options) index) { case RESULT_DYNAMIC: { +#if 0 int present = iPtr->freeProc == TestsaveresultFree; int called = freeCount; Tcl_AppendElement(interp, called ? "called" : "notCalled"); Tcl_AppendElement(interp, present ? "present" : "missing"); +#else + Tcl_AppendElement(interp, discard ? "called" : "notCalled"); + Tcl_AppendElement(interp, !discard ? "present" : "missing"); +#endif break; } case RESULT_OBJECT: @@ -5169,7 +5180,9 @@ static void TestsaveresultFree( char *blockPtr) { +#if 0 freeCount++; +#endif } /* diff --git a/generic/tclUtil.c b/generic/tclUtil.c index a1c1996..32b1bfe 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -2626,6 +2626,7 @@ Tcl_DStringResult( Tcl_DString *dsPtr) /* Dynamic string that is to become the * result of interp. */ { +#if 0 Interp *iPtr = (Interp *) interp; Tcl_ResetResult(interp); @@ -2637,8 +2638,11 @@ Tcl_DStringResult( iPtr->result = iPtr->resultSpace; memcpy(iPtr->result, dsPtr->string, dsPtr->length + 1); } else { +#endif Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE); +#if 0 } +#endif dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; @@ -2672,6 +2676,7 @@ Tcl_DStringGetResult( Tcl_DString *dsPtr) /* Dynamic string that is to become the result * of interp. */ { +#if 0 Interp *iPtr = (Interp *) interp; if (dsPtr->string != dsPtr->staticSpace) { @@ -2710,6 +2715,14 @@ Tcl_DStringGetResult( iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; +#else + int length; + char *bytes = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); + + Tcl_DStringFree(dsPtr); + Tcl_DStringAppend(dsPtr, bytes, length); + Tcl_ResetResult(interp); +#endif } /* -- cgit v0.12 From e76fa60cb994bd0ad5fce8614a682f88e65c2e8a Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 19 Apr 2012 12:41:06 +0000 Subject: Clean version of changes; ifdef-free --- generic/tcl.h | 32 +---- generic/tclBasic.c | 105 +-------------- generic/tclHistory.c | 9 -- generic/tclInt.h | 43 +------ generic/tclResult.c | 358 +-------------------------------------------------- generic/tclStubLib.c | 14 +- generic/tclTest.c | 30 +---- generic/tclUtil.c | 59 +-------- 8 files changed, 22 insertions(+), 628 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 46266d2..a7d3917 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -499,37 +499,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt; * Instead, they set a Tcl_Obj member in the "real" structure that can be * accessed with Tcl_GetObjResult() and Tcl_SetObjResult(). */ -#if 0 -typedef struct Tcl_Interp { - /* TIP #330: Strongly discourage extensions from using the string - * result. */ -#ifdef USE_INTERP_RESULT - char *result TCL_DEPRECATED_API("use Tcl_GetResult/Tcl_SetResult"); - /* If the last command returned a string - * result, this points to it. */ - void (*freeProc) (char *blockPtr) - TCL_DEPRECATED_API("use Tcl_GetResult/Tcl_SetResult"); - /* Zero means the string result is statically - * allocated. TCL_DYNAMIC means it was - * allocated with ckalloc and should be freed - * with ckfree. Other values give the address - * of function to invoke to free the result. - * Tcl_Eval must free it before executing next - * command. */ -#else - char *unused3 TCL_DEPRECATED_API("bad field access"); - void (*unused4) (char *) TCL_DEPRECATED_API("bad field access"); -#endif -#ifdef USE_INTERP_ERRORLINE - int errorLine TCL_DEPRECATED_API("use Tcl_GetErrorLine/Tcl_SetErrorLine"); - /* When TCL_ERROR is returned, this gives the - * line number within the command where the - * error occurred (1 if first line). */ -#else - int unused5 TCL_DEPRECATED_API("bad field access"); -#endif -} Tcl_Interp; -#endif + typedef struct Tcl_Interp Tcl_Interp; typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler; diff --git a/generic/tclBasic.c b/generic/tclBasic.c index d55faeb..a66b8b2 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -503,10 +503,6 @@ Tcl_CreateInterp(void) iPtr = ckalloc(sizeof(Interp)); interp = (Tcl_Interp *) iPtr; -#if 0 - iPtr->result = iPtr->resultSpace; - iPtr->freeProc = NULL; -#endif iPtr->errorLine = 0; iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); @@ -562,12 +558,6 @@ Tcl_CreateInterp(void) iPtr->rootFramePtr = NULL; /* Initialise as soon as :: is available */ iPtr->lookupNsPtr = NULL; -#if 0 - iPtr->appendResult = NULL; - iPtr->appendAvl = 0; - iPtr->appendUsed = 0; -#endif - Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS); iPtr->packageUnknown = NULL; @@ -595,9 +585,6 @@ Tcl_CreateInterp(void) iPtr->emptyObjPtr = Tcl_NewObj(); /* Another empty object. */ Tcl_IncrRefCount(iPtr->emptyObjPtr); -#if 0 - iPtr->resultSpace[0] = 0; -#endif iPtr->threadId = Tcl_GetCurrentThread(); /* TIP #378 */ @@ -1499,9 +1486,6 @@ DeleteInterpProc( */ Tcl_FreeResult(interp); -#if 0 - iPtr->result = NULL; -#endif Tcl_DecrRefCount(iPtr->objResultPtr); iPtr->objResultPtr = NULL; Tcl_DecrRefCount(iPtr->ecVar); @@ -1523,12 +1507,6 @@ DeleteInterpProc( if (iPtr->returnOpts) { Tcl_DecrRefCount(iPtr->returnOpts); } -#if 0 - if (iPtr->appendResult != NULL) { - ckfree(iPtr->appendResult); - iPtr->appendResult = NULL; - } -#endif TclFreePackageInfo(iPtr); while (iPtr->tracePtr != NULL) { Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr); @@ -2435,15 +2413,6 @@ TclInvokeObjectCommand( cmdPtr->objClientData, argc, objv); } -#if 0 - /* - * Move the interpreter's object result to the string result, then reset - * the object result. - */ - - (void) Tcl_GetStringResult(interp); -#endif - /* * Decrement the ref counts for the argument objects created above, then * free the objv array if malloc'ed storage was used. @@ -4345,26 +4314,9 @@ TclNRRunCallbacks( /* All callbacks down to rootPtr not inclusive * are to be run. */ { -/* Interp *iPtr = (Interp *) interp;*/ NRE_callback *callbackPtr; Tcl_NRPostProc *procPtr; -#if 0 - /* - * If the interpreter has a non-empty string result, the result object is - * either empty or stale because some function set interp->result - * directly. If so, move the string result to the result object, then - * reset the string result. - * - * This only needs to be done for the first item in the list: all other - * are for NR function calls, and those are Tcl_Obj based. - */ - - if (*(iPtr->result) != 0) { - (void) Tcl_GetObjResult(interp); - } -#endif - while (TOP_CB(interp) != rootPtr) { callbackPtr = TOP_CB(interp); procPtr = callbackPtr->procPtr; @@ -5842,18 +5794,6 @@ Tcl_Eval( * previous call to Tcl_CreateInterp). */ const char *script) /* Pointer to TCL command to execute. */ { -#if 0 - int code = Tcl_EvalEx(interp, script, -1, 0); - - /* - * For backwards compatibility with old C code that predates the object - * system in Tcl 8.0, we have to mirror the object result back into the - * string result (some callers may expect it there). - */ - - (void) Tcl_GetStringResult(interp); - return code; -#endif return Tcl_EvalEx(interp, script, -1, 0); } @@ -6352,11 +6292,6 @@ Tcl_ExprLong( Tcl_IncrRefCount(exprPtr); result = Tcl_ExprLongObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); -#if 0 - if (result != TCL_OK) { - (void) Tcl_GetStringResult(interp); - } -#endif } return result; } @@ -6383,11 +6318,6 @@ Tcl_ExprDouble( result = Tcl_ExprDoubleObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); /* Discard the expression object. */ -#if 0 - if (result != TCL_OK) { - (void) Tcl_GetStringResult(interp); - } -#endif } return result; } @@ -6413,16 +6343,6 @@ Tcl_ExprBoolean( Tcl_IncrRefCount(exprPtr); result = Tcl_ExprBooleanObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); -#if 0 - if (result != TCL_OK) { - /* - * Move the interpreter's object result to the string result, then - * reset the object result. - */ - - (void) Tcl_GetStringResult(interp); - } -#endif return result; } } @@ -6747,13 +6667,6 @@ Tcl_ExprString( Tcl_DecrRefCount(resultPtr); } } -#if 0 - /* - * Force the string rep of the interp result. - */ - - (void) Tcl_GetStringResult(interp); -#endif return code; } @@ -6857,23 +6770,7 @@ Tcl_AddObjErrorInfo( iPtr->flags |= ERR_LEGACY_COPY; if (iPtr->errorInfo == NULL) { -#if 0 - if (iPtr->result[0] != 0) { - /* - * The interp's string result is set, apparently by some extension - * making a deprecated direct write to it. That extension may - * expect interp->result to continue to be set, so we'll take - * special pains to avoid clearing it, until we drop support for - * interp->result completely. - */ - - iPtr->errorInfo = Tcl_NewStringObj(iPtr->result, -1); - } else { -#endif - iPtr->errorInfo = iPtr->objResultPtr; -#if 0 - } -#endif + iPtr->errorInfo = iPtr->objResultPtr; Tcl_IncrRefCount(iPtr->errorInfo); if (!iPtr->errorCode) { Tcl_SetErrorCode(interp, "NONE", NULL); diff --git a/generic/tclHistory.c b/generic/tclHistory.c index 5448365..c44ba4c 100644 --- a/generic/tclHistory.c +++ b/generic/tclHistory.c @@ -74,15 +74,6 @@ Tcl_RecordAndEval( Tcl_IncrRefCount(cmdPtr); result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags); -#if 0 - /* - * Move the interpreter's object result to the string result, then - * reset the object result. - */ - - (void) Tcl_GetStringResult(interp); -#endif - /* * Discard the Tcl object created to hold the command. */ diff --git a/generic/tclInt.h b/generic/tclInt.h index 0d541a8..fa7c03c 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -1800,32 +1800,16 @@ typedef struct Interp { * Tcl_Interp struct (see tcl.h). If you change one, be sure to change the * other. * - * The interpreter's result is held in both the string and the - * objResultPtr fields. These fields hold, respectively, the result's - * string or object value. The interpreter's result is always in the - * result field if that is non-empty, otherwise it is in objResultPtr. - * The two fields are kept consistent unless some C code sets - * interp->result directly. Programs should not access result and - * objResultPtr directly; instead, they should always get and set the - * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, and - * Tcl_GetStringResult. See the SetResult man page for details. + * The interpreter's result is held in the objResultPtr field. This field + * holds the result's object value. The interpreter's result is always in + * objResultPtr. Programs should not access objResultPtr directly; + * instead, they should always get and set the result using procedures + * such as Tcl_SetObjResult, Tcl_GetObjResult, and Tcl_GetStringResult. + * See the SetResult man page for details. */ -#if 0 - char *result; /* If the last command returned a string - * result, this points to it. Should not be - * accessed directly; see comment above. */ - Tcl_FreeProc *freeProc; /* Zero means a string result is statically - * allocated. TCL_DYNAMIC means string result - * was allocated with ckalloc and should be - * freed with ckfree. Other values give - * address of procedure to invoke to free the - * string result. Tcl_Eval must free it before - * executing next command. */ -#else char *unused3; Tcl_FreeProc *unused4; -#endif int errorLine; /* When TCL_ERROR is returned, this gives the * line number in the command where the error * occurred (1 means first line). */ @@ -1883,19 +1867,9 @@ typedef struct Interp { * See Tcl_AppendResult code for details. */ -#if 0 - char *appendResult; /* Storage space for results generated by - * Tcl_AppendResult. Ckalloc-ed. NULL means - * not yet allocated. */ - int appendAvl; /* Total amount of space available at - * partialResult. */ - int appendUsed; /* Number of non-null bytes currently stored - * at partialResult. */ -#else char *unused5; int unused6; int unused7; -#endif /* * Information about packages. Used only in tclPkg.c. @@ -1957,12 +1931,7 @@ typedef struct Interp { * string. Returned by Tcl_ObjSetVar2 when * variable traces change a variable in a * gross way. */ -#if 0 - char resultSpace[TCL_RESULT_SIZE+1]; - /* Static space holding small results. */ -#else char unused8[TCL_RESULT_SIZE+1]; -#endif Tcl_Obj *objResultPtr; /* If the last command returned an object * result, this points to it. Should not be * accessed directly; see comment above. */ diff --git a/generic/tclResult.c b/generic/tclResult.c index cbaefcb..693c650 100644 --- a/generic/tclResult.c +++ b/generic/tclResult.c @@ -27,9 +27,6 @@ enum returnKeys { static Tcl_Obj ** GetKeys(void); static void ReleaseKeys(ClientData clientData); static void ResetObjResult(Interp *iPtr); -#if 0 -static void SetupAppendBuffer(Interp *iPtr, int newSpace); -#endif /* * This structure is used to take a snapshot of the interpreter state in @@ -248,46 +245,6 @@ Tcl_SaveResult( statePtr->objResultPtr = iPtr->objResultPtr; iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); - -#if 0 - /* - * Save the string result. - */ - - statePtr->freeProc = iPtr->freeProc; - if (iPtr->result == iPtr->resultSpace) { - /* - * Copy the static string data out of the interp buffer. - */ - - statePtr->result = statePtr->resultSpace; - strcpy(statePtr->result, iPtr->result); - statePtr->appendResult = NULL; - } else if (iPtr->result == iPtr->appendResult) { - /* - * Move the append buffer out of the interp. - */ - - statePtr->appendResult = iPtr->appendResult; - statePtr->appendAvl = iPtr->appendAvl; - statePtr->appendUsed = iPtr->appendUsed; - statePtr->result = statePtr->appendResult; - iPtr->appendResult = NULL; - iPtr->appendAvl = 0; - iPtr->appendUsed = 0; - } else { - /* - * Move the dynamic or static string out of the interpreter. - */ - - statePtr->result = iPtr->result; - statePtr->appendResult = NULL; - } - - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; - iPtr->freeProc = 0; -#endif } /* @@ -317,41 +274,6 @@ Tcl_RestoreResult( Tcl_ResetResult(interp); -#if 0 - /* - * Restore the string result. - */ - - iPtr->freeProc = statePtr->freeProc; - if (statePtr->result == statePtr->resultSpace) { - /* - * Copy the static string data into the interp buffer. - */ - - iPtr->result = iPtr->resultSpace; - strcpy(iPtr->result, statePtr->result); - } else if (statePtr->result == statePtr->appendResult) { - /* - * Move the append buffer back into the interp. - */ - - if (iPtr->appendResult != NULL) { - ckfree(iPtr->appendResult); - } - - iPtr->appendResult = statePtr->appendResult; - iPtr->appendAvl = statePtr->appendAvl; - iPtr->appendUsed = statePtr->appendUsed; - iPtr->result = iPtr->appendResult; - } else { - /* - * Move the dynamic or static string back into the interpreter. - */ - - iPtr->result = statePtr->result; - } -#endif - /* * Restore the object result. */ @@ -383,18 +305,6 @@ Tcl_DiscardResult( Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */ { TclDecrRefCount(statePtr->objResultPtr); - -#if 0 - if (statePtr->result == statePtr->appendResult) { - ckfree(statePtr->appendResult); - } else if (statePtr->freeProc) { - if (statePtr->freeProc == TCL_DYNAMIC) { - ckfree(statePtr->result); - } else { - statePtr->freeProc(statePtr->result); - } - } -#endif } /* @@ -424,51 +334,6 @@ Tcl_SetResult( * TCL_STATIC, TCL_VOLATILE, or the address of * a Tcl_FreeProc such as free. */ { -#if 0 - Interp *iPtr = (Interp *) interp; - register Tcl_FreeProc *oldFreeProc = iPtr->freeProc; - char *oldResult = iPtr->result; - - if (result == NULL) { - iPtr->resultSpace[0] = 0; - iPtr->result = iPtr->resultSpace; - iPtr->freeProc = 0; - } else if (freeProc == TCL_VOLATILE) { - int length = strlen(result); - - if (length > TCL_RESULT_SIZE) { - iPtr->result = ckalloc(length + 1); - iPtr->freeProc = TCL_DYNAMIC; - } else { - iPtr->result = iPtr->resultSpace; - iPtr->freeProc = 0; - } - memcpy(iPtr->result, result, (unsigned) length+1); - } else { - iPtr->result = (char *) result; - iPtr->freeProc = freeProc; - } - - /* - * If the old result was dynamically-allocated, free it up. Do it here, - * rather than at the beginning, in case the new result value was part of - * the old result value. - */ - - if (oldFreeProc != 0) { - if (oldFreeProc == TCL_DYNAMIC) { - ckfree(oldResult); - } else { - oldFreeProc(oldResult); - } - } - - /* - * Reset the object result since we just set the string result. - */ - - ResetObjResult(iPtr); -#else Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); if (result == NULL || freeProc == NULL || freeProc == TCL_VOLATILE) { return; @@ -478,7 +343,6 @@ Tcl_SetResult( } else { (*freeProc)(result); } -#endif } /* @@ -502,23 +366,9 @@ const char * Tcl_GetStringResult( register Tcl_Interp *interp)/* Interpreter whose result to return. */ { -#if 0 - /* - * If the string result is empty, move the object result to the string - * result, then reset the object result. - */ - Interp *iPtr = (Interp *) interp; - if (*(iPtr->result) == 0) { - Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), - TCL_VOLATILE); - } - return iPtr->result; -#else - Interp *iPtr = (Interp *)interp; return Tcl_GetString(iPtr->objResultPtr); -#endif } /* @@ -559,23 +409,6 @@ Tcl_SetObjResult( */ TclDecrRefCount(oldObjResult); - -#if 0 - /* - * Reset the string result since we just set the result object. - */ - - if (iPtr->freeProc != NULL) { - if (iPtr->freeProc == TCL_DYNAMIC) { - ckfree(iPtr->result); - } else { - iPtr->freeProc(iPtr->result); - } - iPtr->freeProc = 0; - } - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; -#endif } /* @@ -604,34 +437,7 @@ Tcl_GetObjResult( Tcl_Interp *interp) /* Interpreter whose result to return. */ { register Interp *iPtr = (Interp *) interp; -#if 0 - Tcl_Obj *objResultPtr; - int length; - - /* - * If the string result is non-empty, move the string result to the object - * result, then reset the string result. - */ - if (*(iPtr->result) != 0) { - ResetObjResult(iPtr); - - objResultPtr = iPtr->objResultPtr; - length = strlen(iPtr->result); - TclInitStringRep(objResultPtr, iPtr->result, length); - - if (iPtr->freeProc != NULL) { - if (iPtr->freeProc == TCL_DYNAMIC) { - ckfree(iPtr->result); - } else { - iPtr->freeProc(iPtr->result); - } - iPtr->freeProc = 0; - } - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; - } -#endif return iPtr->objResultPtr; } @@ -750,51 +556,6 @@ Tcl_AppendElement( * to result. */ { Interp *iPtr = (Interp *) interp; -#if 0 - char *dst; - int size; - int flags; - - /* - * If the string result is empty, move the object result to the string - * result, then reset the object result. - */ - - (void) Tcl_GetStringResult(interp); - - /* - * See how much space is needed, and grow the append buffer if needed to - * accommodate the list element. - */ - - size = Tcl_ScanElement(element, &flags) + 1; - if ((iPtr->result != iPtr->appendResult) - || (iPtr->appendResult[iPtr->appendUsed] != 0) - || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) { - SetupAppendBuffer(iPtr, size+iPtr->appendUsed); - } - - /* - * Convert the string into a list element and copy it to the buffer that's - * forming, with a space separator if needed. - */ - - dst = iPtr->appendResult + iPtr->appendUsed; - if (TclNeedSpace(iPtr->appendResult, dst)) { - iPtr->appendUsed++; - *dst = ' '; - dst++; - - /* - * If we need a space to separate this element from preceding stuff, - * then this element will not lead a list, and need not have it's - * leading '#' quoted. - */ - - flags |= TCL_DONT_QUOTE_HASH; - } - iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags); -#else Tcl_Obj *elementPtr = Tcl_NewStringObj(element, -1); Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr); int length; @@ -809,90 +570,7 @@ Tcl_AppendElement( } Tcl_AppendObjToObj(iPtr->objResultPtr, listPtr); Tcl_DecrRefCount(listPtr); -#endif -} -#if 0 - -/* - *---------------------------------------------------------------------- - * - * SetupAppendBuffer -- - * - * This function makes sure that there is an append buffer properly - * initialized, if necessary, from the interpreter's result, and that it - * has at least enough room to accommodate newSpace new bytes of - * information. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static void -SetupAppendBuffer( - Interp *iPtr, /* Interpreter whose result is being set up. */ - int newSpace) /* Make sure that at least this many bytes of - * new information may be added. */ -{ - int totalSpace; - - /* - * Make the append buffer larger, if that's necessary, then copy the - * result into the append buffer and make the append buffer the official - * Tcl result. - */ - - if (iPtr->result != iPtr->appendResult) { - /* - * If an oversized buffer was used recently, then free it up so we go - * back to a smaller buffer. This avoids tying up memory forever after - * a large operation. - */ - - if (iPtr->appendAvl > 500) { - ckfree(iPtr->appendResult); - iPtr->appendResult = NULL; - iPtr->appendAvl = 0; - } - iPtr->appendUsed = strlen(iPtr->result); - } else if (iPtr->result[iPtr->appendUsed] != 0) { - /* - * Most likely someone has modified a result created by - * Tcl_AppendResult et al. so that it has a different size. Just - * recompute the size. - */ - - iPtr->appendUsed = strlen(iPtr->result); - } - - totalSpace = newSpace + iPtr->appendUsed; - if (totalSpace >= iPtr->appendAvl) { - char *new; - - if (totalSpace < 100) { - totalSpace = 200; - } else { - totalSpace *= 2; - } - new = ckalloc(totalSpace); - strcpy(new, iPtr->result); - if (iPtr->appendResult != NULL) { - ckfree(iPtr->appendResult); - } - iPtr->appendResult = new; - iPtr->appendAvl = totalSpace; - } else if (iPtr->result != iPtr->appendResult) { - strcpy(iPtr->appendResult, iPtr->result); - } - - Tcl_FreeResult((Tcl_Interp *) iPtr); - iPtr->result = iPtr->appendResult; } -#endif /* *---------------------------------------------------------------------- @@ -900,18 +578,17 @@ SetupAppendBuffer( * Tcl_FreeResult -- * * This function frees up the memory associated with an interpreter's - * string result. It also resets the interpreter's result object. - * Tcl_FreeResult is most commonly used when a function is about to - * replace one result value with another. + * result, resetting the interpreter's result object. Tcl_FreeResult is + * most commonly used when a function is about to replace one result + * value with another. * * Results: * None. * * Side effects: - * Frees the memory associated with interp's string result and sets - * interp->freeProc to zero, but does not change interp->result or clear - * error state. Resets interp's result object to an unshared empty - * object. + * Frees the memory associated with interp's result but does not change + * any part of the error dictionary (i.e., the errorinfo and errorcode + * remain the same). * *---------------------------------------------------------------------- */ @@ -922,17 +599,6 @@ Tcl_FreeResult( { register Interp *iPtr = (Interp *) interp; -#if 0 - if (iPtr->freeProc != NULL) { - if (iPtr->freeProc == TCL_DYNAMIC) { - ckfree(iPtr->result); - } else { - iPtr->freeProc(iPtr->result); - } - iPtr->freeProc = 0; - } -#endif - ResetObjResult(iPtr); } @@ -962,18 +628,6 @@ Tcl_ResetResult( register Interp *iPtr = (Interp *) interp; ResetObjResult(iPtr); -#if 0 - if (iPtr->freeProc != NULL) { - if (iPtr->freeProc == TCL_DYNAMIC) { - ckfree(iPtr->result); - } else { - iPtr->freeProc(iPtr->result); - } - iPtr->freeProc = 0; - } - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; -#endif if (iPtr->errorCode) { /* Legacy support */ if (iPtr->flags & ERR_LEGACY_COPY) { diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index 71933a0..b36627c 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -37,20 +37,16 @@ HasStubSupport( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; + static Tcl_Obj errorMsg = { + 2, /* Stop anything from trying to deallocate this memory! */ + "This interpreter does not support stubs-enabled extensions.", + 59, NULL, {0} + }; if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) { return iPtr->stubTable; } -#if 0 - iPtr->result = - (char *)"This interpreter does not support stubs-enabled extensions."; - iPtr->freeProc = TCL_STATIC; -#else - Tcl_Obj errorMsg = {2, - "This interpreter does not support stubs-enabled extensions.", - 59, NULL, {0}}; iPtr->objResultPtr = &errorMsg; -#endif return NULL; } diff --git a/generic/tclTest.c b/generic/tclTest.c index 1a189c7..b407f51 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -120,15 +120,6 @@ typedef struct TclEncoding { char *fromUtfCmd; } TclEncoding; -#if 0 -/* - * The counter below is used to determine if the TestsaveresultFree routine - * was called for a result. - */ - -static int freeCount; -#endif - /* * Boolean flag used by the "testsetmainloop" and "testexitmainloop" commands. */ @@ -5065,9 +5056,6 @@ TestsaveresultCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { -#if 0 - Interp* iPtr = (Interp*) interp; -#endif int discard, result, index; Tcl_SavedResult state; Tcl_Obj *objPtr; @@ -5118,9 +5106,6 @@ TestsaveresultCmd( break; } -#if 0 - freeCount = 0; -#endif Tcl_SaveResult(interp, &state); if (((enum options) index) == RESULT_OBJECT) { @@ -5137,19 +5122,10 @@ TestsaveresultCmd( } switch ((enum options) index) { - case RESULT_DYNAMIC: { -#if 0 - int present = iPtr->freeProc == TestsaveresultFree; - int called = freeCount; - - Tcl_AppendElement(interp, called ? "called" : "notCalled"); - Tcl_AppendElement(interp, present ? "present" : "missing"); -#else + case RESULT_DYNAMIC: Tcl_AppendElement(interp, discard ? "called" : "notCalled"); Tcl_AppendElement(interp, !discard ? "present" : "missing"); -#endif break; - } case RESULT_OBJECT: Tcl_AppendElement(interp, Tcl_GetObjResult(interp) == objPtr ? "same" : "different"); @@ -5180,9 +5156,7 @@ static void TestsaveresultFree( char *blockPtr) { -#if 0 - freeCount++; -#endif + /* empty... */ } /* diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 32b1bfe..f316dfb 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -2626,23 +2626,7 @@ Tcl_DStringResult( Tcl_DString *dsPtr) /* Dynamic string that is to become the * result of interp. */ { -#if 0 - Interp *iPtr = (Interp *) interp; - - Tcl_ResetResult(interp); - - if (dsPtr->string != dsPtr->staticSpace) { - iPtr->result = dsPtr->string; - iPtr->freeProc = TCL_DYNAMIC; - } else if (dsPtr->length < TCL_RESULT_SIZE) { - iPtr->result = iPtr->resultSpace; - memcpy(iPtr->result, dsPtr->string, dsPtr->length + 1); - } else { -#endif - Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE); -#if 0 - } -#endif + Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE); dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; @@ -2676,53 +2660,12 @@ Tcl_DStringGetResult( Tcl_DString *dsPtr) /* Dynamic string that is to become the result * of interp. */ { -#if 0 - Interp *iPtr = (Interp *) interp; - - if (dsPtr->string != dsPtr->staticSpace) { - ckfree(dsPtr->string); - } - - /* - * If the string result is empty, move the object result to the string - * result, then reset the object result. - */ - - (void) Tcl_GetStringResult(interp); - - dsPtr->length = strlen(iPtr->result); - if (iPtr->freeProc != NULL) { - if (iPtr->freeProc == TCL_DYNAMIC) { - dsPtr->string = iPtr->result; - dsPtr->spaceAvl = dsPtr->length+1; - } else { - dsPtr->string = ckalloc(dsPtr->length+1); - memcpy(dsPtr->string, iPtr->result, (unsigned) dsPtr->length+1); - iPtr->freeProc(iPtr->result); - } - dsPtr->spaceAvl = dsPtr->length+1; - iPtr->freeProc = NULL; - } else { - if (dsPtr->length < TCL_DSTRING_STATIC_SIZE) { - dsPtr->string = dsPtr->staticSpace; - dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; - } else { - dsPtr->string = ckalloc(dsPtr->length+1); - dsPtr->spaceAvl = dsPtr->length + 1; - } - memcpy(dsPtr->string, iPtr->result, (unsigned) dsPtr->length+1); - } - - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; -#else int length; char *bytes = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); Tcl_DStringFree(dsPtr); Tcl_DStringAppend(dsPtr, bytes, length); Tcl_ResetResult(interp); -#endif } /* -- cgit v0.12 From b8074d77342d4166a599b933a111edd467153894 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 19 Apr 2012 12:57:45 +0000 Subject: To preserve the ability of [load] to bring in mistmatched stubs-enabled modules and react with an error rather than a crash, HasStubSupport() has to keep fiddling with the same fields as always. --- generic/tclStubLib.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index b36627c..9e9208d 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -37,16 +37,13 @@ HasStubSupport( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; - static Tcl_Obj errorMsg = { - 2, /* Stop anything from trying to deallocate this memory! */ - "This interpreter does not support stubs-enabled extensions.", - 59, NULL, {0} - }; if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) { return iPtr->stubTable; } - iPtr->objResultPtr = &errorMsg; + iPtr->unused3 + = "This interpreter does not support stubs-enabled extensions."; + iPtr->unused4 = TCL_STATIC; return NULL; } -- cgit v0.12 From bc2133334d0fb3580be3b1cd65ed85b991887e68 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 25 Apr 2012 21:03:58 +0000 Subject: Implement Tcl_DStringResult with call to TclDStringToObj. --- generic/tclUtil.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 8852a56..1e35165 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -2626,12 +2626,7 @@ Tcl_DStringResult( Tcl_DString *dsPtr) /* Dynamic string that is to become the * result of interp. */ { - Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE); - - dsPtr->string = dsPtr->staticSpace; - dsPtr->length = 0; - dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; - dsPtr->staticSpace[0] = '\0'; + Tcl_SetObjResult(interp, TclDStringToObj(dsPtr)); } /* -- cgit v0.12 From d0aa8bd6eb7c9ef510cf66beb42922019e05180d Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 26 Nov 2012 21:25:26 +0000 Subject: Comments and renamings around the legacy fields for string results. --- generic/tclInt.h | 38 ++++++++++++++++++++------------------ generic/tclStubLib.c | 27 +++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index 7ed9bdf..90f283c 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -1799,31 +1799,33 @@ typedef struct AllocCache { */ typedef struct Interp { + /* - * Note: the first three fields must match exactly the fields in a - * Tcl_Interp struct (see tcl.h). If you change one, be sure to change the - * other. - * - * The interpreter's result is held in the objResultPtr field. This field - * holds the result's object value. The interpreter's result is always in - * objResultPtr. Programs should not access objResultPtr directly; - * instead, they should always get and set the result using procedures - * such as Tcl_SetObjResult, Tcl_GetObjResult, and Tcl_GetStringResult. - * See the SetResult man page for details. + * The first two fields were named "result" and "freeProc" in earlier + * versions of Tcl. They are no longer used within Tcl, and are no + * longer available to be accessed by extensions. However, they cannot + * be removed. Why? There is a deployed base of stub-enabled extensions + * that query the value of iPtr->stubTable. For them to continue to work, + * the location of the field "stubTable" within the Interp struct cannot + * change. The most robust way to assure that is to leave all fields up to + * that one undisturbed. */ - char *unused3; - Tcl_FreeProc *unused4; + char *legacyResult; + Tcl_FreeProc *legacyFreeProc; int errorLine; /* When TCL_ERROR is returned, this gives the * line number in the command where the error * occurred (1 means first line). */ const struct TclStubs *stubTable; - /* Pointer to the exported Tcl stub table. On - * previous versions of Tcl this is a pointer - * to the objResultPtr or a pointer to a - * buckets array in a hash table. We therefore - * have to do some careful checking before we - * can use this. */ + /* Pointer to the exported Tcl stub table. In + * ancient pre-8.1 versions of Tcl this was a + * pointer to the objResultPtr or a pointer to a + * buckets array in a hash table. Deployed stubs + * enabled extensions check for a NULL pointer value + * and for a TCL_STUBS_MAGIC value to verify they + * are not [load]ing into one of those pre-stubs + * interps. + */ TclHandle handle; /* Handle used to keep track of when this * interp is deleted. */ diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index 9e9208d..35c7f09 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -41,9 +41,32 @@ HasStubSupport( if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) { return iPtr->stubTable; } - iPtr->unused3 + + /* + * Either interp has no stubTable field, or its magic number has been + * changed, indicating a release of Tcl that no longer supports the + * stubs mechanism with which the extension has been prepared. This + * either means interp comes from Tcl releases 7.5 - 8.0, when [load] + * of extensions was possible, but stubs were not yet in use, or it means + * interp come from some future release of Tcl where it has been necessary + * to stop supporting this particular stubs mechanism. In either case, + * we can count on the fields legacyResult and legacyFreeProc existing + * (since they persist to maintain the struct offset fo stubTable; see + * tclInt.h comments.), and we can hope that [load] or any sensible + * successor will be able to reach into them to report the mismatch error + * message sensibly. + * + * For maximum compat support, even if only for the sake of reporting + * clean errors, rather than crashing, we assume the TCL_STUB_MAGIC + * value is changed only when absolutely necessary. So long as the first + * slot in the stub table holds (some function compatible with) the routine + * Tcl_PkgRequireEx(), that routine can take care of verifying the version + * compatibility testing with all deployed + */ + + iPtr->legacyResult = "This interpreter does not support stubs-enabled extensions."; - iPtr->unused4 = TCL_STATIC; + iPtr->legacyFreeProc = TCL_STATIC; return NULL; } -- cgit v0.12 From 41e4423638af6265a31c1d9a83d1626801ed5b90 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 26 Nov 2012 21:30:13 +0000 Subject: ...and here's the lines left behind in the editor. --- generic/tclStubLib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index 35c7f09..fe1302c 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -61,7 +61,10 @@ HasStubSupport( * value is changed only when absolutely necessary. So long as the first * slot in the stub table holds (some function compatible with) the routine * Tcl_PkgRequireEx(), that routine can take care of verifying the version - * compatibility testing with all deployed + * compatibility testing with all deployed stubs-enabled extensions. That is, + * there is no need to change the value of TCL_STUB_MAGIC when transitioning + * from the Tcl 8 stubs table to the Tcl 9 stubs table, so long as they + * share just their first slot in common. */ iPtr->legacyResult -- cgit v0.12 From cbc47c069d3d222ae06bb469960912be8f12ef2b Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 26 Nov 2012 22:23:43 +0000 Subject: Stop segfaults in test suite. --- generic/tclBasic.c | 1 + generic/tclLoad.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 3906c0a..abfc456 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -485,6 +485,7 @@ Tcl_CreateInterp(void) iPtr = ckalloc(sizeof(Interp)); interp = (Tcl_Interp *) iPtr; + iPtr->legacyResult = NULL; iPtr->errorLine = 0; iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); diff --git a/generic/tclLoad.c b/generic/tclLoad.c index d4c67d7..ec1c617 100644 --- a/generic/tclLoad.c +++ b/generic/tclLoad.c @@ -472,11 +472,12 @@ Tcl_LoadObjCmd( Interp *iPtr = (Interp *) target; if (iPtr->legacyResult != NULL) { /* - * A call to Tcl_InitStubs() determined the caller extension and this - * interp are incompatible in their stubs mechanisms, and recorded the - * error in the oldest legacy place we have to do so. + * A call to Tcl_InitStubs() determined the caller extension and + * this interp are incompatible in their stubs mechanisms, and + * recorded the error in the oldest legacy place we have to do so. */ Tcl_SetObjResult(interp, Tcl_NewStringObj(iPtr->legacyResult, -1)); + iPtr->legacyResult = NULL; } else { Tcl_TransferResult(target, code, interp); } -- cgit v0.12 From 3c5544ba3c952c9e4415f040bfe93cb22041d02c Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 27 Nov 2012 21:09:20 +0000 Subject: 3588687 Added cross checks so that [load]ed extension, [load]ing interp, and linked stubs library all agree on their versions in the ways that matter. --- generic/tcl.h | 9 ++++++--- generic/tclStubLib.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 147672c..74dd452 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2394,8 +2394,8 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp, * main library in case an extension is statically linked into an application. */ -const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, - int exact); +const char * TclInitStubs(Tcl_Interp *interp, const char *version, + int exact, int major); const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); @@ -2403,7 +2403,10 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, * When not using stubs, make it a macro. */ -#ifndef USE_TCL_STUBS +#ifdef USE_TCL_STUBS +#define Tcl_InitStubs(interp, version, exact) \ + TclInitStubs(interp, version, exact, TCL_MAJOR_VERSION) +#else #define Tcl_InitStubs(interp, version, exact) \ Tcl_PkgInitStubsCheck(interp, version, exact) #endif diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index f569820..ca6f4ff 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -76,13 +76,52 @@ static int isDigit(const int c) */ MODULE_SCOPE const char * -Tcl_InitStubs( +TclInitStubs( Tcl_Interp *interp, const char *version, - int exact) + int exact, + int major) { + Interp *iPtr = (Interp *) interp; const char *actualVersion = NULL; ClientData pkgData = NULL; + const char *p, *q; + + /* + * Detect whether the extension and the stubs library were built + * against Tcl header files from different major versions. That's + * seriously broken. + */ + + if (major != TCL_MAJOR_VERSION) { + iPtr->result = + (char *)"extension linked to incompatible stubs library"; + iPtr->freeProc = TCL_STATIC; + return NULL; + } + + /* + * Detect whether an extension compiled against a Tcl header file + * of one major version is requesting to use a stubs table of a + * different major version. According to our compat rules, that's + * a request that cannot succeed. Different major versions imply + * incompatible stub tables. + */ + + p = version; + q = TCL_VERSION; + while (isDigit(*p)) { + if (*p++ != *q++) { + goto badVersion; + } + } + if (isDigit(*q)) { + badVersion: + iPtr->result = + (char *)"extension passed bad version argument to stubs library"; + iPtr->freeProc = TCL_STATIC; + return NULL; + } /* * We can't optimize this check by caching tclStubsPtr because that @@ -100,14 +139,14 @@ Tcl_InitStubs( return NULL; } if (exact) { - const char *p = version; int count = 0; + p = version; while (*p) { count += !isDigit(*p++); } if (count == 1) { - const char *q = actualVersion; + q = actualVersion; p = version; while (*p && (*p == *q)) { @@ -140,6 +179,16 @@ Tcl_InitStubs( return actualVersion; } +#undef Tcl_InitStubs +MODULE_SCOPE const char * +Tcl_InitStubs( + Tcl_Interp *interp, + const char *version, + int exact) +{ + return TclInitStubs(interp, version, exact, TCL_MAJOR_VERSION); +} + /* * Local Variables: * mode: c -- cgit v0.12 From 1213e2c7212fed431301f7cc330ecde40cebf0eb Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 29 Nov 2012 16:52:45 +0000 Subject: Get the updated error message --- generic/tclStubLib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index e875bf7..648ed24 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -68,7 +68,7 @@ HasStubSupport( */ iPtr->legacyResult - = "This interpreter does not support stubs-enabled extensions."; + = (char *) "interpreter uses an incompatible stubs mechanism"; iPtr->legacyFreeProc = TCL_STATIC; return NULL; } -- cgit v0.12 From 3382c0c47fc468888766bc6bdc9b32d9e485baa2 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 29 Nov 2012 17:03:17 +0000 Subject: missed bit of merge --- generic/tclStubLib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index 648ed24..23085e2 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -85,7 +85,7 @@ static int isDigit(const int c) /* *---------------------------------------------------------------------- * - * Tcl_InitStubs -- + * TclInitStubs -- * * Tries to initialise the stub table pointers and ensures that the * correct version of Tcl is loaded. -- cgit v0.12 From 7f282b3594655176c8010e0a744c3deb798b76e2 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 29 Nov 2012 21:34:22 +0000 Subject: No string result -> no more need for TCL_RESULT_SIZE --- generic/tcl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index c7b9e6a..48b5d53 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -600,8 +600,6 @@ typedef struct stat *Tcl_OldStat_; #define TCL_BREAK 3 #define TCL_CONTINUE 4 -#define TCL_RESULT_SIZE 200 - /* *---------------------------------------------------------------------------- * Flags to control what substitutions are performed by Tcl_SubstObj(): -- cgit v0.12