From fe508fa3b5c9dffaebbd68b86344a799a45075c4 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 30 Oct 2017 08:47:33 +0000 Subject: Experimental branch meant to eliminate the "wideint" type, just merge it to a single "int" type. No effect on linux64 and similar systems, code simplification for Win64 and 32-bit system. No TIP yet, implementation ongoing. --- generic/tclCmdMZ.c | 4 ++-- generic/tclDisassemble.c | 6 +++--- generic/tclExecute.c | 8 ++++---- generic/tclGet.c | 2 +- generic/tclInt.h | 14 +++++++------- generic/tclObj.c | 26 +++++++++++++------------- generic/tclProc.c | 4 ++-- generic/tclStrToD.c | 8 ++++---- generic/tclStubInit.c | 2 +- generic/tclUtil.c | 8 ++++---- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 2195aa1..522b76f 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1580,9 +1580,9 @@ StringIsCmd( result = length1 == 0; } } else if (((index == STR_IS_TRUE) && - objPtr->internalRep.longValue == 0) + objPtr->internalRep.wideValue == 0) || ((index == STR_IS_FALSE) && - objPtr->internalRep.longValue != 0)) { + objPtr->internalRep.wideValue != 0)) { result = 0; } break; diff --git a/generic/tclDisassemble.c b/generic/tclDisassemble.c index d61ed42..70a5847 100644 --- a/generic/tclDisassemble.c +++ b/generic/tclDisassemble.c @@ -797,7 +797,7 @@ TclNewInstNameObj( Tcl_Obj *objPtr = Tcl_NewObj(); objPtr->typePtr = &tclInstNameType; - objPtr->internalRep.longValue = (long) inst; + objPtr->internalRep.wideValue = (long) inst; objPtr->bytes = NULL; return objPtr; @@ -817,7 +817,7 @@ static void UpdateStringOfInstName( Tcl_Obj *objPtr) { - int inst = objPtr->internalRep.longValue; + int inst = objPtr->internalRep.wideValue; char *s, buf[20]; int len; @@ -825,7 +825,7 @@ UpdateStringOfInstName( sprintf(buf, "inst_%d", inst); s = buf; } else { - s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name; + s = (char *) tclInstructionTable[objPtr->internalRep.wideValue].name; } len = strlen(s); objPtr->bytes = ckalloc(len + 1); diff --git a/generic/tclExecute.c b/generic/tclExecute.c index f4c71ec..b068e0d 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -503,7 +503,7 @@ VarHashCreateVar( (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_LONG, \ *(ptrPtr) = (ClientData) \ - (&((objPtr)->internalRep.longValue)), TCL_OK) : \ + (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclDoubleType) \ ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \ ? (*(tPtr) = TCL_NUMBER_NAN) \ @@ -518,7 +518,7 @@ VarHashCreateVar( (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_LONG, \ *(ptrPtr) = (ClientData) \ - (&((objPtr)->internalRep.longValue)), TCL_OK) : \ + (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclWideIntType) \ ? (*(tPtr) = TCL_NUMBER_WIDE, \ *(ptrPtr) = (ClientData) \ @@ -545,7 +545,7 @@ VarHashCreateVar( #define TclGetBooleanFromObj(interp, objPtr, boolPtr) \ ((((objPtr)->typePtr == &tclIntType) \ || ((objPtr)->typePtr == &tclBooleanType)) \ - ? (*(boolPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK) \ + ? (*(boolPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \ : Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr))) /* @@ -6692,7 +6692,7 @@ TEBCresume( iterVarPtr = LOCAL(infoPtr->loopCtTemp); valuePtr = iterVarPtr->value.objPtr; - iterNum = valuePtr->internalRep.longValue + 1; + iterNum = valuePtr->internalRep.wideValue + 1; TclSetLongObj(valuePtr, iterNum); /* diff --git a/generic/tclGet.c b/generic/tclGet.c index 97e8c7b..727db0a 100644 --- a/generic/tclGet.c +++ b/generic/tclGet.c @@ -142,7 +142,7 @@ Tcl_GetBoolean( Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } if (code == TCL_OK) { - *boolPtr = obj.internalRep.longValue; + *boolPtr = obj.internalRep.wideValue; } return code; } diff --git a/generic/tclInt.h b/generic/tclInt.h index 0b5ff0c..feffeba 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2453,17 +2453,17 @@ typedef struct List { #define TclGetLongFromObj(interp, objPtr, longPtr) \ (((objPtr)->typePtr == &tclIntType) \ - ? ((*(longPtr) = (objPtr)->internalRep.longValue), TCL_OK) \ + ? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetLongFromObj((interp), (objPtr), (longPtr))) #if (LONG_MAX == INT_MAX) #define TclGetIntFromObj(interp, objPtr, intPtr) \ (((objPtr)->typePtr == &tclIntType) \ - ? ((*(intPtr) = (objPtr)->internalRep.longValue), TCL_OK) \ + ? ((*(intPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetIntFromObj((interp), (objPtr), (intPtr))) #define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \ (((objPtr)->typePtr == &tclIntType) \ - ? ((*(idxPtr) = (objPtr)->internalRep.longValue), TCL_OK) \ + ? ((*(idxPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ : TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr))) #else #define TclGetIntFromObj(interp, objPtr, intPtr) \ @@ -2484,7 +2484,7 @@ typedef struct List { #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(wideIntPtr) = (Tcl_WideInt) \ - ((objPtr)->internalRep.longValue), TCL_OK) : \ + ((objPtr)->internalRep.wideValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) #else /* !TCL_WIDE_INT_IS_LONG */ #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ @@ -2492,7 +2492,7 @@ typedef struct List { ? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \ ((objPtr)->typePtr == &tclIntType) \ ? (*(wideIntPtr) = (Tcl_WideInt) \ - ((objPtr)->internalRep.longValue), TCL_OK) : \ + ((objPtr)->internalRep.wideValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) #endif /* TCL_WIDE_INT_IS_LONG */ @@ -4545,7 +4545,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; do { \ TclInvalidateStringRep(objPtr); \ TclFreeIntRep(objPtr); \ - (objPtr)->internalRep.longValue = (long)(i); \ + (objPtr)->internalRep.wideValue = (long)(i); \ (objPtr)->typePtr = &tclIntType; \ } while (0) @@ -4589,7 +4589,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ - (objPtr)->internalRep.longValue = (long)(i); \ + (objPtr)->internalRep.wideValue = (long)(i); \ (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) diff --git a/generic/tclObj.c b/generic/tclObj.c index 1a00011..f0bcc5e 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -1810,7 +1810,7 @@ Tcl_DbNewBooleanObj( TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; - objPtr->internalRep.longValue = (boolValue != 0); + objPtr->internalRep.wideValue = (boolValue != 0); objPtr->typePtr = &tclIntType; return objPtr; } @@ -1888,11 +1888,11 @@ Tcl_GetBooleanFromObj( { do { if (objPtr->typePtr == &tclIntType) { - *boolPtr = (objPtr->internalRep.longValue != 0); + *boolPtr = (objPtr->internalRep.wideValue != 0); return TCL_OK; } if (objPtr->typePtr == &tclBooleanType) { - *boolPtr = (int) objPtr->internalRep.longValue; + *boolPtr = (int) objPtr->internalRep.wideValue; return TCL_OK; } if (objPtr->typePtr == &tclDoubleType) { @@ -1960,7 +1960,7 @@ TclSetBooleanFromAny( if (objPtr->bytes == NULL) { if (objPtr->typePtr == &tclIntType) { - switch (objPtr->internalRep.longValue) { + switch (objPtr->internalRep.wideValue) { case 0L: case 1L: return TCL_OK; } @@ -2107,13 +2107,13 @@ ParseBoolean( goodBoolean: TclFreeIntRep(objPtr); - objPtr->internalRep.longValue = newBool; + objPtr->internalRep.wideValue = newBool; objPtr->typePtr = &tclBooleanType; return TCL_OK; numericBoolean: TclFreeIntRep(objPtr); - objPtr->internalRep.longValue = newBool; + objPtr->internalRep.wideValue = newBool; objPtr->typePtr = &tclIntType; return TCL_OK; } @@ -2294,7 +2294,7 @@ Tcl_GetDoubleFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - *dblPtr = objPtr->internalRep.longValue; + *dblPtr = objPtr->internalRep.wideValue; return TCL_OK; } if (objPtr->typePtr == &tclBignumType) { @@ -2569,7 +2569,7 @@ UpdateStringOfInt( char buffer[TCL_INTEGER_SPACE]; register int len; - len = TclFormatInt(buffer, objPtr->internalRep.longValue); + len = TclFormatInt(buffer, objPtr->internalRep.wideValue); objPtr->bytes = ckalloc(len + 1); memcpy(objPtr->bytes, buffer, (unsigned) len + 1); @@ -2679,7 +2679,7 @@ Tcl_DbNewLongObj( TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; - objPtr->internalRep.longValue = longValue; + objPtr->internalRep.wideValue = longValue; objPtr->typePtr = &tclIntType; return objPtr; } @@ -2759,7 +2759,7 @@ Tcl_GetLongFromObj( { do { if (objPtr->typePtr == &tclIntType) { - *longPtr = objPtr->internalRep.longValue; + *longPtr = objPtr->internalRep.wideValue; return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG @@ -3080,7 +3080,7 @@ Tcl_GetWideIntFromObj( } #endif if (objPtr->typePtr == &tclIntType) { - *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue; + *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.wideValue; return TCL_OK; } if (objPtr->typePtr == &tclDoubleType) { @@ -3402,7 +3402,7 @@ GetBignumFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - TclInitBignumFromLong(bignumValue, objPtr->internalRep.longValue); + TclInitBignumFromLong(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG @@ -3653,7 +3653,7 @@ TclGetNumberFromObj( } if (objPtr->typePtr == &tclIntType) { *typePtr = TCL_NUMBER_LONG; - *clientDataPtr = &objPtr->internalRep.longValue; + *clientDataPtr = &objPtr->internalRep.wideValue; return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG diff --git a/generic/tclProc.c b/generic/tclProc.c index 96bdcf3..133f41d 100644 --- a/generic/tclProc.c +++ b/generic/tclProc.c @@ -826,7 +826,7 @@ TclObjGetFrame( level = curLevel - level; result = 1; } else if (objPtr->typePtr == &levelReferenceType) { - level = (int) objPtr->internalRep.longValue; + level = (int) objPtr->internalRep.wideValue; result = 1; } else { name = TclGetString(objPtr); @@ -834,7 +834,7 @@ TclObjGetFrame( if (TCL_OK == Tcl_GetInt(NULL, name+1, &level) && level >= 0) { TclFreeIntRep(objPtr); objPtr->typePtr = &levelReferenceType; - objPtr->internalRep.longValue = level; + objPtr->internalRep.wideValue = level; result = 1; } else { result = -1; diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 630e498..c8bc7b5 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -1289,10 +1289,10 @@ TclParseNumber( } else { objPtr->typePtr = &tclIntType; if (signum) { - objPtr->internalRep.longValue = + objPtr->internalRep.wideValue = - (long) octalSignificandWide; } else { - objPtr->internalRep.longValue = + objPtr->internalRep.wideValue = (long) octalSignificandWide; } } @@ -1336,10 +1336,10 @@ TclParseNumber( } else { objPtr->typePtr = &tclIntType; if (signum) { - objPtr->internalRep.longValue = + objPtr->internalRep.wideValue = - (long) significandWide; } else { - objPtr->internalRep.longValue = + objPtr->internalRep.wideValue = (long) significandWide; } } diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index ebd2086..c8b4dce 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -244,7 +244,7 @@ static Tcl_Obj *dbNewLongObj( TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; - objPtr->internalRep.longValue = (long) intValue; + objPtr->internalRep.wideValue = (long) intValue; objPtr->typePtr = &tclIntType; return objPtr; #else diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 608cd15..da4dc49 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3598,7 +3598,7 @@ TclGetIntForIndex( * be converted to one, use it. */ - *indexPtr = endValue + objPtr->internalRep.longValue; + *indexPtr = endValue + objPtr->internalRep.wideValue; return TCL_OK; } @@ -3690,9 +3690,9 @@ UpdateStringOfEndOffset( register int len = 3; memcpy(buffer, "end", 4); - if (objPtr->internalRep.longValue != 0) { + if (objPtr->internalRep.wideValue != 0) { buffer[len++] = '-'; - len += TclFormatInt(buffer+len, -(objPtr->internalRep.longValue)); + len += TclFormatInt(buffer+len, -(objPtr->internalRep.wideValue)); } objPtr->bytes = ckalloc((unsigned) len+1); memcpy(objPtr->bytes, buffer, (unsigned) len+1); @@ -3790,7 +3790,7 @@ SetEndOffsetFromAny( */ TclFreeIntRep(objPtr); - objPtr->internalRep.longValue = offset; + objPtr->internalRep.wideValue = offset; objPtr->typePtr = &tclEndOffsetType; return TCL_OK; -- cgit v0.12 From aad24c7ffcbdb7271ba73f1548b5be00185df1b2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 30 Oct 2017 11:01:28 +0000 Subject: Change (internal) TclFormatInt() signature, so it can handle WideInt's directly. Ongoing simplifications ... --- generic/tclInt.decls | 2 +- generic/tclIntDecls.h | 4 +-- generic/tclObj.c | 83 +++------------------------------------------------ generic/tclTimer.c | 32 +++++++------------- generic/tclUtil.c | 21 +++++++++---- 5 files changed, 33 insertions(+), 109 deletions(-) diff --git a/generic/tclInt.decls b/generic/tclInt.decls index dea698c..63ed6c6 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -114,7 +114,7 @@ declare 23 { } # Replaced with macro (see tclInt.h) in Tcl 8.5.0, restored in 8.5.10 declare 24 { - int TclFormatInt(char *buffer, long n) + int TclFormatInt(char *buffer, Tcl_WideInt n) } declare 25 { void TclFreePackageInfo(Interp *iPtr) diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index 5bccfe5..2d437d5 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -113,7 +113,7 @@ EXTERN int TclFindElement(Tcl_Interp *interp, /* 23 */ EXTERN Proc * TclFindProc(Interp *iPtr, const char *procName); /* 24 */ -EXTERN int TclFormatInt(char *buffer, long n); +EXTERN int TclFormatInt(char *buffer, Tcl_WideInt n); /* 25 */ EXTERN void TclFreePackageInfo(Interp *iPtr); /* Slot 26 is reserved */ @@ -668,7 +668,7 @@ typedef struct TclIntStubs { void (*reserved21)(void); int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, int *sizePtr, int *bracePtr); /* 22 */ Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */ - int (*tclFormatInt) (char *buffer, long n); /* 24 */ + int (*tclFormatInt) (char *buffer, Tcl_WideInt n); /* 24 */ void (*tclFreePackageInfo) (Interp *iPtr); /* 25 */ void (*reserved26)(void); void (*reserved27)(void); diff --git a/generic/tclObj.c b/generic/tclObj.c index f0bcc5e..bf1a2e6 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -210,10 +210,6 @@ static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfDouble(Tcl_Obj *objPtr); static void UpdateStringOfInt(Tcl_Obj *objPtr); -#ifndef TCL_WIDE_INT_IS_LONG -static void UpdateStringOfWideInt(Tcl_Obj *objPtr); -static int SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); -#endif static void FreeBignum(Tcl_Obj *objPtr); static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void UpdateStringOfBignum(Tcl_Obj *objPtr); @@ -275,8 +271,8 @@ const Tcl_ObjType tclWideIntType = { "wideInt", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ - UpdateStringOfWideInt, /* updateStringProc */ - SetWideIntFromAny /* setFromAnyProc */ + UpdateStringOfInt, /* updateStringProc */ + SetIntFromAny /* setFromAnyProc */ }; #endif const Tcl_ObjType tclBignumType = { @@ -2538,9 +2534,8 @@ SetIntFromAny( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *objPtr) /* Pointer to the object to convert */ { - long l; - - return TclGetLongFromObj(interp, objPtr, &l); + Tcl_WideInt w; + return Tcl_GetWideIntFromObj(interp, objPtr, &w); } /* @@ -2836,49 +2831,6 @@ Tcl_GetLongFromObj( TCL_PARSE_INTEGER_ONLY)==TCL_OK); return TCL_ERROR; } -#ifndef TCL_WIDE_INT_IS_LONG - -/* - *---------------------------------------------------------------------- - * - * UpdateStringOfWideInt -- - * - * Update the string representation for a wide integer object. Note: this - * function does not free an existing old string rep so storage will be - * lost if this has not already been done. - * - * Results: - * None. - * - * Side effects: - * The object's string is set to a valid string that results from the - * wideInt-to-string conversion. - * - *---------------------------------------------------------------------- - */ - -static void -UpdateStringOfWideInt( - register Tcl_Obj *objPtr) /* Int object whose string rep to update. */ -{ - char buffer[TCL_INTEGER_SPACE+2]; - register unsigned len; - register Tcl_WideInt wideVal = objPtr->internalRep.wideValue; - - /* - * Note that sprintf will generate a compiler warning under Mingw claiming - * %I64 is an unknown format specifier. Just ignore this warning. We can't - * use %L as the format specifier since that gets printed as a 32 bit - * value. - */ - - sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal); - len = strlen(buffer); - objPtr->bytes = ckalloc(len + 1); - memcpy(objPtr->bytes, buffer, len + 1); - objPtr->length = len; -} -#endif /* !TCL_WIDE_INT_IS_LONG */ /* *---------------------------------------------------------------------- @@ -3133,33 +3085,6 @@ Tcl_GetWideIntFromObj( TCL_PARSE_INTEGER_ONLY)==TCL_OK); return TCL_ERROR; } -#ifndef TCL_WIDE_INT_IS_LONG - -/* - *---------------------------------------------------------------------- - * - * SetWideIntFromAny -- - * - * Attempts to force the internal representation for a Tcl object to - * tclWideIntType, specifically. - * - * Results: - * The return value is a standard object Tcl result. If an error occurs - * during conversion, an error message is left in the interpreter's - * result unless "interp" is NULL. - * - *---------------------------------------------------------------------- - */ - -static int -SetWideIntFromAny( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_Obj *objPtr) /* Pointer to the object to convert */ -{ - Tcl_WideInt w; - return Tcl_GetWideIntFromObj(interp, objPtr, &w); -} -#endif /* !TCL_WIDE_INT_IS_LONG */ /* *---------------------------------------------------------------------- diff --git a/generic/tclTimer.c b/generic/tclTimer.c index 3467305..4bb5a35 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -1045,37 +1045,27 @@ AfterDelay( if (iPtr->limit.timeEvent == NULL || TCL_TIME_BEFORE(endTime, iPtr->limit.time)) { diff = TCL_TIME_DIFF_MS_CEILING(endTime, now); -#ifndef TCL_WIDE_INT_IS_LONG - if (diff > LONG_MAX) { - diff = LONG_MAX; - } -#endif if (diff > TCL_TIME_MAXIMUM_SLICE) { diff = TCL_TIME_MAXIMUM_SLICE; } - if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) { - diff = 1; - } + if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) { + diff = 1; + } if (diff > 0) { - Tcl_Sleep((long) diff); - if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) { - break; - } + Tcl_Sleep((int) diff); + if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) { + break; + } } else { - break; - } + break; + } } else { diff = TCL_TIME_DIFF_MS(iPtr->limit.time, now); -#ifndef TCL_WIDE_INT_IS_LONG - if (diff > LONG_MAX) { - diff = LONG_MAX; - } -#endif if (diff > TCL_TIME_MAXIMUM_SLICE) { diff = TCL_TIME_MAXIMUM_SLICE; } if (diff > 0) { - Tcl_Sleep((long) diff); + Tcl_Sleep((int) diff); } if (Tcl_AsyncReady()) { if (Tcl_AsyncInvoke(interp, TCL_OK) != TCL_OK) { @@ -1089,7 +1079,7 @@ AfterDelay( return TCL_ERROR; } } - Tcl_GetTime(&now); + Tcl_GetTime(&now); } while (TCL_TIME_BEFORE(now, endTime)); return TCL_OK; } diff --git a/generic/tclUtil.c b/generic/tclUtil.c index da4dc49..27e1877 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3489,9 +3489,9 @@ int TclFormatInt( char *buffer, /* Points to the storage into which the * formatted characters are written. */ - long n) /* The integer to format. */ + Tcl_WideInt n) /* The integer to format. */ { - long intVal; + Tcl_WideInt intVal; int i; int numFormatted, j; const char *digits = "0123456789"; @@ -3514,7 +3514,7 @@ TclFormatInt( intVal = -n; /* [Bug 3390638] Workaround for*/ if (n == -n || intVal == n) { /* broken compiler optimizers. */ - return sprintf(buffer, "%ld", n); + return sprintf(buffer, "%" TCL_LL_MODIFIER "d", n); } /* @@ -3722,7 +3722,7 @@ SetEndOffsetFromAny( Tcl_Interp *interp, /* Tcl interpreter or NULL */ Tcl_Obj *objPtr) /* Pointer to the object to parse */ { - int offset; /* Offset in the "end-offset" expression */ + Tcl_WideInt offset; /* Offset in the "end-offset" expression */ register const char *bytes; /* String rep of the object */ int length; /* Length of the object's string rep */ @@ -3758,15 +3758,24 @@ SetEndOffsetFromAny( } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) { /* * This is our limited string expression evaluator. Pass everything - * after "end-" to Tcl_GetInt, then reverse for offset. + * after "end-" to TclParseNumber. */ if (TclIsSpaceProc(bytes[4])) { goto badIndexFormat; } - if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) { + if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, + TCL_PARSE_INTEGER_ONLY) != TCL_OK) { return TCL_ERROR; } + if ((objPtr->typePtr != &tclIntType) +#ifndef TCL_WIDE_INT_IS_LONG + && (objPtr->typePtr != &tclWideIntType) +#endif + ) { + goto badIndexFormat; + } + offset = objPtr->internalRep.wideValue; if (bytes[3] == '-') { offset = -offset; } -- cgit v0.12 From ca470c3d4eeb58156583417df4011087612bb186 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 30 Oct 2017 14:32:52 +0000 Subject: more progress in code simplifications --- generic/tclAssembly.c | 2 +- generic/tclBasic.c | 30 +++------- generic/tclCmdMZ.c | 4 -- generic/tclExecute.c | 163 ++++++-------------------------------------------- generic/tclInt.h | 8 +-- generic/tclObj.c | 30 +--------- generic/tclTimer.c | 2 - generic/tclUtil.c | 2 - 8 files changed, 30 insertions(+), 211 deletions(-) diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index 4c5ae68..c7ded6e 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -4266,7 +4266,7 @@ AddBasicBlockRangeToErrorInfo( Tcl_AppendObjToErrorInfo(interp, lineNo); Tcl_AddErrorInfo(interp, " and "); if (bbPtr->successor1 != NULL) { - TclSetLongObj(lineNo, bbPtr->successor1->startLine); + TclSetWideIntObj(lineNo, bbPtr->successor1->startLine); Tcl_AppendObjToErrorInfo(interp, lineNo); } else { Tcl_AddErrorInfo(interp, "end of assembly code"); diff --git a/generic/tclBasic.c b/generic/tclBasic.c index e6022ac..a911028 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -7442,12 +7442,12 @@ ExprAbsFunc( return TCL_ERROR; } - if (type == TCL_NUMBER_LONG) { - long l = *((const long *) ptr); + if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) { + Tcl_WideInt l = *((const Tcl_WideInt *) ptr); - if (l > (long)0) { + if (l > (Tcl_WideInt)0) { goto unChanged; - } else if (l == (long)0) { + } else if (l == (Tcl_WideInt)0) { const char *string = objv[1]->bytes; if (string) { while (*string != '0') { @@ -7459,11 +7459,11 @@ ExprAbsFunc( } } goto unChanged; - } else if (l == LONG_MIN) { - TclInitBignumFromLong(&big, l); + } else if (l == LLONG_MIN) { + TclInitBignumFromWideInt(&big, l); goto tooLarge; } - Tcl_SetObjResult(interp, Tcl_NewLongObj(-l)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l)); return TCL_OK; } @@ -7487,22 +7487,6 @@ ExprAbsFunc( return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG - if (type == TCL_NUMBER_WIDE) { - Tcl_WideInt w = *((const Tcl_WideInt *) ptr); - - if (w >= (Tcl_WideInt)0) { - goto unChanged; - } - if (w == LLONG_MIN) { - TclInitBignumFromWideInt(&big, w); - goto tooLarge; - } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w)); - return TCL_OK; - } -#endif - if (type == TCL_NUMBER_BIG) { if (mp_cmp_d((const mp_int *) ptr, 0) == MP_LT) { Tcl_GetBignumFromObj(NULL, objv[1], &big); diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 522b76f..c984bbe 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1596,9 +1596,7 @@ StringIsCmd( /* TODO */ if ((objPtr->typePtr == &tclDoubleType) || (objPtr->typePtr == &tclIntType) || -#ifndef TCL_WIDE_INT_IS_LONG (objPtr->typePtr == &tclWideIntType) || -#endif (objPtr->typePtr == &tclBignumType)) { break; } @@ -1633,9 +1631,7 @@ StringIsCmd( goto failedIntParse; case STR_IS_ENTIER: if ((objPtr->typePtr == &tclIntType) || -#ifndef TCL_WIDE_INT_IS_LONG (objPtr->typePtr == &tclWideIntType) || -#endif (objPtr->typePtr == &tclBignumType)) { break; } diff --git a/generic/tclExecute.c b/generic/tclExecute.c index b068e0d..3e64805 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -1892,7 +1892,6 @@ TclIncrObj( TclSetLongObj(valuePtr, sum); return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG { Tcl_WideInt w1 = (Tcl_WideInt) augend; Tcl_WideInt w2 = (Tcl_WideInt) addend; @@ -1905,7 +1904,6 @@ TclIncrObj( TclSetWideIntObj(valuePtr, w1 + w2); return TCL_OK; } -#endif } if ((type1 == TCL_NUMBER_DOUBLE) || (type1 == TCL_NUMBER_NAN)) { @@ -1925,7 +1923,6 @@ TclIncrObj( return TCL_ERROR; } -#ifndef TCL_WIDE_INT_IS_LONG if ((type1 != TCL_NUMBER_BIG) && (type2 != TCL_NUMBER_BIG)) { Tcl_WideInt w1, w2, sum; @@ -1942,7 +1939,6 @@ TclIncrObj( return TCL_OK; } } -#endif Tcl_TakeBignumFromObj(interp, valuePtr, &value); Tcl_GetBignumFromObj(interp, incrPtr, &incr); @@ -3626,9 +3622,7 @@ TEBCresume( { Tcl_Obj *incrPtr; -#ifndef TCL_WIDE_INT_IS_LONG Tcl_WideInt w; -#endif long increment; case INST_INCR_SCALAR1: @@ -3750,7 +3744,6 @@ TEBCresume( } goto doneIncr; } -#ifndef TCL_WIDE_INT_IS_LONG w = (Tcl_WideInt)augend; TRACE(("%u %ld => ", opnd, increment)); @@ -3770,9 +3763,7 @@ TEBCresume( TclSetWideIntObj(objPtr, w+increment); } goto doneIncr; -#endif } /* end if (type == TCL_NUMBER_LONG) */ -#ifndef TCL_WIDE_INT_IS_LONG if (type == TCL_NUMBER_WIDE) { Tcl_WideInt sum; @@ -3804,7 +3795,6 @@ TEBCresume( goto doneIncr; } } -#endif } if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared */ @@ -5915,7 +5905,6 @@ TEBCresume( if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) != TCL_OK) { type1 = TCL_NUMBER_WIDE; } -#ifndef TCL_WIDE_INT_IS_LONG } else if (type1 == TCL_NUMBER_WIDE) { /* value is between WIDE_MIN and WIDE_MAX */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ @@ -5923,7 +5912,6 @@ TEBCresume( if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) == TCL_OK) { type1 = TCL_NUMBER_LONG; } -#endif } else if (type1 == TCL_NUMBER_BIG) { /* value is an integer outside the WIDE_MIN to WIDE_MAX range */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ @@ -6307,7 +6295,6 @@ TEBCresume( w1 = (Tcl_WideInt) l1; w2 = (Tcl_WideInt) l2; wResult = w1 + w2; -#ifdef TCL_WIDE_INT_IS_LONG /* * Check for overflow. */ @@ -6315,14 +6302,12 @@ TEBCresume( if (Overflowing(w1, w2, wResult)) { goto overflow; } -#endif goto wideResultOfArithmetic; case INST_SUB: w1 = (Tcl_WideInt) l1; w2 = (Tcl_WideInt) l2; wResult = w1 - w2; -#ifdef TCL_WIDE_INT_IS_LONG /* * Must check for overflow. The macro tests for overflows in * sums by looking at the sign bits. As we have a subtraction @@ -6336,7 +6321,6 @@ TEBCresume( if (Overflowing(w1, ~w2, wResult)) { goto overflow; } -#endif wideResultOfArithmetic: TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); if (Tcl_IsShared(valuePtr)) { @@ -8124,14 +8108,6 @@ ExecuteExtendedBinaryMathOp( Tcl_Obj *valuePtr, /* The first operand on the stack. */ Tcl_Obj *value2Ptr) /* The second operand on the stack. */ { -#define LONG_RESULT(l) \ - if (Tcl_IsShared(valuePtr)) { \ - TclNewLongObj(objResultPtr, l); \ - return objResultPtr; \ - } else { \ - Tcl_SetLongObj(valuePtr, l); \ - return NULL; \ - } #define WIDE_RESULT(w) \ if (Tcl_IsShared(valuePtr)) { \ return Tcl_NewWideIntObj(w); \ @@ -8186,7 +8162,6 @@ ExecuteExtendedBinaryMathOp( return constants[0]; } } -#ifndef TCL_WIDE_INT_IS_LONG if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *)ptr1); if (type2 != TCL_NUMBER_BIG) { @@ -8231,7 +8206,6 @@ ExecuteExtendedBinaryMathOp( mp_clear(&big2); return NULL; } -#endif Tcl_GetBignumFromObj(NULL, valuePtr, &big1); Tcl_GetBignumFromObj(NULL, value2Ptr, &big2); mp_init(&bigResult); @@ -8258,14 +8232,10 @@ ExecuteExtendedBinaryMathOp( */ switch (type2) { - case TCL_NUMBER_LONG: - invalid = (*((const long *)ptr2) < 0L); - break; -#ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: + case TCL_NUMBER_LONG: invalid = (*((const Tcl_WideInt *)ptr2) < (Tcl_WideInt)0); break; -#endif case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); invalid = (mp_cmp_d(&big2, 0) == MP_LT); @@ -8345,11 +8315,9 @@ ExecuteExtendedBinaryMathOp( case TCL_NUMBER_LONG: zero = (*(const long *)ptr1 > 0L); break; -#ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: zero = (*(const Tcl_WideInt *)ptr1 > (Tcl_WideInt)0); break; -#endif case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); zero = (mp_cmp_d(&big1, 0) == MP_GT); @@ -8362,11 +8330,10 @@ ExecuteExtendedBinaryMathOp( if (zero) { return constants[0]; } - LONG_RESULT(-1); + WIDE_RESULT(-1); } shift = (int)(*(const long *)ptr2); -#ifndef TCL_WIDE_INT_IS_LONG /* * Handle shifts within the native wide range. */ @@ -8377,11 +8344,10 @@ ExecuteExtendedBinaryMathOp( if (w1 >= (Tcl_WideInt)0) { return constants[0]; } - LONG_RESULT(-1); + WIDE_RESULT(-1); } WIDE_RESULT(w1 >> shift); } -#endif } Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); @@ -8549,7 +8515,6 @@ ExecuteExtendedBinaryMathOp( BIG_RESULT(&bigResult); } -#ifndef TCL_WIDE_INT_IS_LONG if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) { TclGetWideIntFromObj(NULL, valuePtr, &w1); TclGetWideIntFromObj(NULL, value2Ptr, &w2); @@ -8570,7 +8535,6 @@ ExecuteExtendedBinaryMathOp( } WIDE_RESULT(wResult); } -#endif l1 = *((const long *)ptr1); l2 = *((const long *)ptr2); @@ -8588,7 +8552,7 @@ ExecuteExtendedBinaryMathOp( /* Unused, here to silence compiler warning. */ lResult = 0; } - LONG_RESULT(lResult); + WIDE_RESULT(lResult); case INST_EXPON: { int oddExponent = 0, negativeExponent = 0; @@ -8627,13 +8591,11 @@ ExecuteExtendedBinaryMathOp( negativeExponent = (l2 < 0); oddExponent = (int) (l2 & 1); break; -#ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); negativeExponent = (w2 < 0); oddExponent = (int) (w2 & (Tcl_WideInt)1); break; -#endif case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); negativeExponent = (mp_cmp_d(&big2, 0) == MP_LT); @@ -8657,7 +8619,7 @@ ExecuteExtendedBinaryMathOp( return EXPONENT_OF_ZERO; case -1: if (oddExponent) { - LONG_RESULT(-1); + WIDE_RESULT(-1); } /* fallthrough */ case 1: @@ -8695,7 +8657,7 @@ ExecuteExtendedBinaryMathOp( if (!oddExponent) { return constants[1]; } - LONG_RESULT(-1); + WIDE_RESULT(-1); } } @@ -8720,14 +8682,9 @@ ExecuteExtendedBinaryMathOp( * Reduce small powers of 2 to shifts. */ - if ((unsigned long) l2 < CHAR_BIT * sizeof(long) - 1) { - LONG_RESULT(1L << l2); - } -#if !defined(TCL_WIDE_INT_IS_LONG) - if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1) { + if ((Tcl_WideUInt) l2 < (Tcl_WideUInt) CHAR_BIT*sizeof(Tcl_WideInt) - 1) { WIDE_RESULT(((Tcl_WideInt) 1) << l2); } -#endif goto overflowExpon; } if (l1 == -2) { @@ -8737,14 +8694,9 @@ ExecuteExtendedBinaryMathOp( * Reduce small powers of 2 to shifts. */ - if ((unsigned long) l2 < CHAR_BIT * sizeof(long) - 1) { - LONG_RESULT(signum * (1L << l2)); - } -#if !defined(TCL_WIDE_INT_IS_LONG) if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1){ WIDE_RESULT(signum * (((Tcl_WideInt) 1) << l2)); } -#endif goto overflowExpon; } #if (LONG_MAX == 0x7fffffff) @@ -8783,7 +8735,7 @@ ExecuteExtendedBinaryMathOp( lResult *= lResult; /* b**8 */ break; } - LONG_RESULT(lResult); + WIDE_RESULT(lResult); } if (l1 - 3 >= 0 && l1 -2 < (long)Exp32IndexSize @@ -8796,7 +8748,7 @@ ExecuteExtendedBinaryMathOp( * table lookup. */ - LONG_RESULT(Exp32Value[base]); + WIDE_RESULT(Exp32Value[base]); } } if (-l1 - 3 >= 0 && -l1 - 2 < (long)Exp32IndexSize @@ -8811,7 +8763,7 @@ ExecuteExtendedBinaryMathOp( lResult = (oddExponent) ? -Exp32Value[base] : Exp32Value[base]; - LONG_RESULT(lResult); + WIDE_RESULT(lResult); } } #endif @@ -8819,10 +8771,8 @@ ExecuteExtendedBinaryMathOp( #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) if (type1 == TCL_NUMBER_LONG) { w1 = l1; -#ifndef TCL_WIDE_INT_IS_LONG } else if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); -#endif } else { goto overflowExpon; } @@ -9022,9 +8972,7 @@ ExecuteExtendedBinaryMathOp( switch (opcode) { case INST_ADD: wResult = w1 + w2; -#ifndef TCL_WIDE_INT_IS_LONG if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) -#endif { /* * Check for overflow. @@ -9038,9 +8986,7 @@ ExecuteExtendedBinaryMathOp( case INST_SUB: wResult = w1 - w2; -#ifndef TCL_WIDE_INT_IS_LONG if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) -#endif { /* * Must check for overflow. The macro tests for overflows @@ -9164,12 +9110,10 @@ ExecuteExtendedUnaryMathOp( switch (opcode) { case INST_BITNOT: -#ifndef TCL_WIDE_INT_IS_LONG if (type == TCL_NUMBER_WIDE) { w = *((const Tcl_WideInt *) ptr); WIDE_RESULT(~w); } -#endif Tcl_TakeBignumFromObj(NULL, valuePtr, &big); /* ~a = - a - 1 */ mp_neg(&big, &big); @@ -9180,13 +9124,6 @@ ExecuteExtendedUnaryMathOp( case TCL_NUMBER_DOUBLE: DOUBLE_RESULT(-(*((const double *) ptr))); case TCL_NUMBER_LONG: - w = (Tcl_WideInt) (*((const long *) ptr)); - if (w != LLONG_MIN) { - WIDE_RESULT(-w); - } - TclInitBignumFromLong(&big, *(const long *) ptr); - break; -#ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w = *((const Tcl_WideInt *) ptr); if (w != LLONG_MIN) { @@ -9194,7 +9131,6 @@ ExecuteExtendedUnaryMathOp( } TclInitBignumFromWideInt(&big, w); break; -#endif default: Tcl_TakeBignumFromObj(NULL, valuePtr, &big); } @@ -9205,7 +9141,6 @@ ExecuteExtendedUnaryMathOp( Tcl_Panic("unexpected opcode"); return NULL; } -#undef LONG_RESULT #undef WIDE_RESULT #undef BIG_RESULT #undef DOUBLE_RESULT @@ -9237,31 +9172,24 @@ TclCompareTwoNumbers( ClientData ptr1, ptr2; mp_int big1, big2; double d1, d2, tmp; - long l1, l2; -#ifndef TCL_WIDE_INT_IS_LONG Tcl_WideInt w1, w2; -#endif (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2); switch (type1) { case TCL_NUMBER_LONG: - l1 = *((const long *)ptr1); + case TCL_NUMBER_WIDE: + w1 = *((const Tcl_WideInt *)ptr1); switch (type2) { case TCL_NUMBER_LONG: - l2 = *((const long *)ptr2); - longCompare: - return (l1 < l2) ? MP_LT : ((l1 > l2) ? MP_GT : MP_EQ); -#ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); - w1 = (Tcl_WideInt)l1; - goto wideCompare; -#endif + wideCompare: + return (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ); case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); - d1 = (double) l1; + d1 = (double) w1; /* * If the double has a fractional part, or if the long can be @@ -9269,7 +9197,7 @@ TclCompareTwoNumbers( * doubles. */ - if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) || l1 == (long) d1 + if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w1 == (Tcl_WideInt) d1 || modf(d2, &tmp) != 0.0) { goto doubleCompare; } @@ -9292,44 +9220,6 @@ TclCompareTwoNumbers( if (d2 > (double)LONG_MAX) { return MP_LT; } - l2 = (long) d2; - goto longCompare; - case TCL_NUMBER_BIG: - Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - if (mp_cmp_d(&big2, 0) == MP_LT) { - compare = MP_GT; - } else { - compare = MP_LT; - } - mp_clear(&big2); - return compare; - } - -#ifndef TCL_WIDE_INT_IS_LONG - case TCL_NUMBER_WIDE: - w1 = *((const Tcl_WideInt *)ptr1); - switch (type2) { - case TCL_NUMBER_WIDE: - w2 = *((const Tcl_WideInt *)ptr2); - wideCompare: - return (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ); - case TCL_NUMBER_LONG: - l2 = *((const long *)ptr2); - w2 = (Tcl_WideInt)l2; - goto wideCompare; - case TCL_NUMBER_DOUBLE: - d2 = *((const double *)ptr2); - d1 = (double) w1; - if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) - || w1 == (Tcl_WideInt) d1 || modf(d2, &tmp) != 0.0) { - goto doubleCompare; - } - if (d2 < (double)LLONG_MIN) { - return MP_GT; - } - if (d2 > (double)LLONG_MAX) { - return MP_LT; - } w2 = (Tcl_WideInt) d2; goto wideCompare; case TCL_NUMBER_BIG: @@ -9342,7 +9232,6 @@ TclCompareTwoNumbers( mp_clear(&big2); return compare; } -#endif case TCL_NUMBER_DOUBLE: d1 = *((const double *)ptr1); @@ -9352,21 +9241,6 @@ TclCompareTwoNumbers( doubleCompare: return (d1 < d2) ? MP_LT : ((d1 > d2) ? MP_GT : MP_EQ); case TCL_NUMBER_LONG: - l2 = *((const long *)ptr2); - d2 = (double) l2; - if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) || l2 == (long) d2 - || modf(d1, &tmp) != 0.0) { - goto doubleCompare; - } - if (d1 < (double)LONG_MIN) { - return MP_LT; - } - if (d1 > (double)LONG_MAX) { - return MP_GT; - } - l1 = (long) d1; - goto longCompare; -#ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); d2 = (double) w2; @@ -9382,7 +9256,6 @@ TclCompareTwoNumbers( } w1 = (Tcl_WideInt) d1; goto wideCompare; -#endif case TCL_NUMBER_BIG: if (TclIsInfinite(d1)) { return (d1 > 0.0) ? MP_GT : MP_LT; @@ -9410,10 +9283,8 @@ TclCompareTwoNumbers( case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); switch (type2) { -#ifndef TCL_WIDE_INT_IS_LONG - case TCL_NUMBER_WIDE: -#endif case TCL_NUMBER_LONG: + case TCL_NUMBER_WIDE: compare = mp_cmp_d(&big1, 0); mp_clear(&big1); return compare; diff --git a/generic/tclInt.h b/generic/tclInt.h index feffeba..bb02ddf 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2720,9 +2720,7 @@ MODULE_SCOPE const Tcl_ObjType tclDictType; MODULE_SCOPE const Tcl_ObjType tclProcBodyType; MODULE_SCOPE const Tcl_ObjType tclStringType; MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType; -#ifndef TCL_WIDE_INT_IS_LONG MODULE_SCOPE const Tcl_ObjType tclWideIntType; -#endif MODULE_SCOPE const Tcl_ObjType tclRegexpType; MODULE_SCOPE Tcl_ObjType tclCmdNameType; @@ -4545,11 +4543,13 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; do { \ TclInvalidateStringRep(objPtr); \ TclFreeIntRep(objPtr); \ - (objPtr)->internalRep.wideValue = (long)(i); \ + (objPtr)->internalRep.wideValue = (Tcl_WideInt)(i); \ (objPtr)->typePtr = &tclIntType; \ } while (0) -#ifndef TCL_WIDE_INT_IS_LONG +#ifdef TCL_WIDE_INT_IS_LONG +#define TclSetWideIntObj(objPtr, w) TclSetLongObj(objPtr, w) +#else #define TclSetWideIntObj(objPtr, w) \ do { \ TclInvalidateStringRep(objPtr); \ diff --git a/generic/tclObj.c b/generic/tclObj.c index bf1a2e6..78d7518 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -266,7 +266,6 @@ const Tcl_ObjType tclIntType = { UpdateStringOfInt, /* updateStringProc */ SetIntFromAny /* setFromAnyProc */ }; -#ifndef TCL_WIDE_INT_IS_LONG const Tcl_ObjType tclWideIntType = { "wideInt", /* name */ NULL, /* freeIntRepProc */ @@ -274,7 +273,6 @@ const Tcl_ObjType tclWideIntType = { UpdateStringOfInt, /* updateStringProc */ SetIntFromAny /* setFromAnyProc */ }; -#endif const Tcl_ObjType tclBignumType = { "bignum", /* name */ FreeBignum, /* freeIntRepProc */ @@ -403,9 +401,6 @@ TclInitObjSubsystem(void) /* For backward compatibility only ... */ Tcl_RegisterObjType(&oldBooleanType); -#ifndef TCL_WIDE_INT_IS_LONG - Tcl_RegisterObjType(&tclWideIntType); -#endif #ifdef TCL_COMPILE_STATS Tcl_MutexLock(&tclObjMutex); @@ -1912,12 +1907,10 @@ Tcl_GetBooleanFromObj( *boolPtr = 1; return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *boolPtr = (objPtr->internalRep.wideValue != 0); return TCL_OK; } -#endif } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK == TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0))); return TCL_ERROR; @@ -1967,11 +1960,9 @@ TclSetBooleanFromAny( goto badBoolean; } -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { goto badBoolean; } -#endif if (objPtr->typePtr == &tclDoubleType) { goto badBoolean; @@ -2300,12 +2291,10 @@ Tcl_GetDoubleFromObj( *dblPtr = TclBignumToDouble(&big); return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *dblPtr = (double) objPtr->internalRep.wideValue; return TCL_OK; } -#endif } while (SetDoubleFromAny(interp, objPtr) == TCL_OK); return TCL_ERROR; } @@ -2757,7 +2746,6 @@ Tcl_GetLongFromObj( *longPtr = objPtr->internalRep.wideValue; return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { /* * We return any integer in the range -ULONG_MAX to ULONG_MAX @@ -2776,7 +2764,6 @@ Tcl_GetLongFromObj( } goto tooLarge; } -#endif if (objPtr->typePtr == &tclDoubleType) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -2815,9 +2802,7 @@ Tcl_GetLongFromObj( return TCL_OK; } } -#ifndef TCL_WIDE_INT_IS_LONG tooLarge: -#endif if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_Obj *msg = Tcl_NewStringObj(s, -1); @@ -2983,16 +2968,9 @@ Tcl_SetWideIntObj( if ((wideValue >= (Tcl_WideInt) LONG_MIN) && (wideValue <= (Tcl_WideInt) LONG_MAX)) { - TclSetLongObj(objPtr, (long) wideValue); + TclSetLongObj(objPtr, wideValue); } else { -#ifndef TCL_WIDE_INT_IS_LONG TclSetWideIntObj(objPtr, wideValue); -#else - mp_int big; - - TclInitBignumFromWideInt(&big, wideValue); - Tcl_SetBignumObj(objPtr, &big); -#endif } } @@ -3025,12 +3003,10 @@ Tcl_GetWideIntFromObj( /* Place to store resulting long. */ { do { -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *wideIntPtr = objPtr->internalRep.wideValue; return TCL_OK; } -#endif if (objPtr->typePtr == &tclIntType) { *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.wideValue; return TCL_OK; @@ -3330,13 +3306,11 @@ GetBignumFromObj( TclInitBignumFromLong(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { TclInitBignumFromWideInt(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } -#endif if (objPtr->typePtr == &tclDoubleType) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -3581,13 +3555,11 @@ TclGetNumberFromObj( *clientDataPtr = &objPtr->internalRep.wideValue; return TCL_OK; } -#ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *typePtr = TCL_NUMBER_WIDE; *clientDataPtr = &objPtr->internalRep.wideValue; return TCL_OK; } -#endif if (objPtr->typePtr == &tclBignumType) { static Tcl_ThreadDataKey bignumKey; mp_int *bigPtr = Tcl_GetThreadData(&bignumKey, diff --git a/generic/tclTimer.c b/generic/tclTimer.c index 4bb5a35..279e110 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -819,9 +819,7 @@ Tcl_AfterObjCmd( */ if (objv[1]->typePtr == &tclIntType -#ifndef TCL_WIDE_INT_IS_LONG || objv[1]->typePtr == &tclWideIntType -#endif || objv[1]->typePtr == &tclBignumType || (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index) != TCL_OK)) { diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 27e1877..198424f 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3769,9 +3769,7 @@ SetEndOffsetFromAny( return TCL_ERROR; } if ((objPtr->typePtr != &tclIntType) -#ifndef TCL_WIDE_INT_IS_LONG && (objPtr->typePtr != &tclWideIntType) -#endif ) { goto badIndexFormat; } -- cgit v0.12 From b8b341fea6c287382301eb3de4309197d4390b60 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 30 Oct 2017 16:46:49 +0000 Subject: Fix some pointer arthemeric (only visible on big-endian systems) --- generic/tclExecute.c | 53 ++++++++++++++++++++++++---------------------------- generic/tclInt.h | 19 ++++++++++++++++++- generic/tclObj.c | 7 +------ 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 3e64805..ee9e2e0 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -1878,8 +1878,8 @@ TclIncrObj( } if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - long augend = *((const long *) ptr1); - long addend = *((const long *) ptr2); + long augend = *((const Tcl_WideInt *) ptr1); + long addend = *((const Tcl_WideInt *) ptr2); long sum = augend + addend; /* @@ -3722,7 +3722,7 @@ TEBCresume( objPtr = varPtr->value.objPtr; if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) { if (type == TCL_NUMBER_LONG) { - long augend = *((const long *)ptr); + long augend = *((const Tcl_WideInt *)ptr); long sum = augend + increment; /* @@ -5897,19 +5897,14 @@ TEBCresume( case INST_NUM_TYPE: if (GetNumberFromObj(NULL, OBJ_AT_TOS, &ptr1, &type1) != TCL_OK) { type1 = 0; - } else if (type1 == TCL_NUMBER_LONG) { + } else if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { /* value is between LONG_MIN and LONG_MAX */ /* [string is integer] is -UINT_MAX to UINT_MAX range */ int i; if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) != TCL_OK) { type1 = TCL_NUMBER_WIDE; - } - } else if (type1 == TCL_NUMBER_WIDE) { - /* value is between WIDE_MIN and WIDE_MAX */ - /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ - int i; - if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) == TCL_OK) { + } else { type1 = TCL_NUMBER_LONG; } } else if (type1 == TCL_NUMBER_BIG) { @@ -5957,8 +5952,8 @@ TEBCresume( goto convertComparison; } if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - l1 = *((const long *)ptr1); - l2 = *((const long *)ptr2); + l1 = *((const Tcl_WideInt *)ptr1); + l2 = *((const Tcl_WideInt *)ptr2); compare = (l1 < l2) ? MP_LT : ((l1 > l2) ? MP_GT : MP_EQ); } else { compare = TclCompareTwoNumbers(valuePtr, value2Ptr); @@ -6036,8 +6031,8 @@ TEBCresume( */ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - l1 = *((const long *)ptr1); - l2 = *((const long *)ptr2); + l1 = *((const Tcl_WideInt *)ptr1); + l2 = *((const Tcl_WideInt *)ptr2); switch (*pc) { case INST_MOD: @@ -6287,8 +6282,8 @@ TEBCresume( if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { Tcl_WideInt w1, w2, wResult; - l1 = *((const long *)ptr1); - l2 = *((const long *)ptr2); + l1 = *((const Tcl_WideInt *)ptr1); + l2 = *((const Tcl_WideInt *)ptr2); switch (*pc) { case INST_ADD: @@ -6434,7 +6429,7 @@ TEBCresume( goto gotError; } if (type1 == TCL_NUMBER_LONG) { - l1 = *((const long *) ptr1); + l1 = *((const Tcl_WideInt *) ptr1); if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, ~l1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); @@ -6471,7 +6466,7 @@ TEBCresume( TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); case TCL_NUMBER_LONG: - l1 = *((const long *) ptr1); + l1 = *((const Tcl_WideInt *) ptr1); if (l1 != LONG_MIN) { if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, -l1); @@ -8150,7 +8145,7 @@ ExecuteExtendedBinaryMathOp( l2 = 0; /* silence gcc warning */ if (type2 == TCL_NUMBER_LONG) { - l2 = *((const long *)ptr2); + l2 = *((const Tcl_WideInt *)ptr2); if (l2 == 0) { return DIVIDED_BY_ZERO; } @@ -8255,7 +8250,7 @@ ExecuteExtendedBinaryMathOp( * Zero shifted any number of bits is still zero. */ - if ((type1==TCL_NUMBER_LONG) && (*((const long *)ptr1) == (long)0)) { + if ((type1==TCL_NUMBER_LONG) && (*((const Tcl_WideInt *)ptr1) == (long)0)) { return constants[0]; } @@ -8269,7 +8264,7 @@ ExecuteExtendedBinaryMathOp( */ if ((type2 != TCL_NUMBER_LONG) - || (*((const long *)ptr2) > (long) INT_MAX)) { + || (*((const Tcl_WideInt *)ptr2) > (long) INT_MAX)) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) in * an mp_int, but since we're using mp_mul_2d() to do the @@ -8281,7 +8276,7 @@ ExecuteExtendedBinaryMathOp( "integer value too large to represent", -1)); return GENERAL_ARITHMETIC_ERROR; } - shift = (int)(*((const long *)ptr2)); + shift = (int)(*((const Tcl_WideInt *)ptr2)); /* * Handle shifts within the native wide range. @@ -8302,7 +8297,7 @@ ExecuteExtendedBinaryMathOp( */ if ((type2 != TCL_NUMBER_LONG) - || (*(const long *)ptr2 > INT_MAX)) { + || (*(const Tcl_WideInt *)ptr2 > INT_MAX)) { /* * Again, technically, the value to be shifted could be an * mp_int so huge that a right shift by (INT_MAX+1) bits could @@ -8313,7 +8308,7 @@ ExecuteExtendedBinaryMathOp( switch (type1) { case TCL_NUMBER_LONG: - zero = (*(const long *)ptr1 > 0L); + zero = (*(const Tcl_WideInt *)ptr1 > 0L); break; case TCL_NUMBER_WIDE: zero = (*(const Tcl_WideInt *)ptr1 > (Tcl_WideInt)0); @@ -8332,7 +8327,7 @@ ExecuteExtendedBinaryMathOp( } WIDE_RESULT(-1); } - shift = (int)(*(const long *)ptr2); + shift = (int)(*(const Tcl_WideInt *)ptr2); /* * Handle shifts within the native wide range. @@ -8535,8 +8530,8 @@ ExecuteExtendedBinaryMathOp( } WIDE_RESULT(wResult); } - l1 = *((const long *)ptr1); - l2 = *((const long *)ptr2); + l1 = *((const Tcl_WideInt *)ptr1); + l2 = *((const Tcl_WideInt *)ptr2); switch (opcode) { case INST_BITAND: @@ -8570,7 +8565,7 @@ ExecuteExtendedBinaryMathOp( } l1 = l2 = 0; if (type2 == TCL_NUMBER_LONG) { - l2 = *((const long *) ptr2); + l2 = *((const Tcl_WideInt *) ptr2); if (l2 == 0) { /* * Anything to the zero power is 1. @@ -8606,7 +8601,7 @@ ExecuteExtendedBinaryMathOp( } if (type1 == TCL_NUMBER_LONG) { - l1 = *((const long *)ptr1); + l1 = *((const Tcl_WideInt *)ptr1); } if (negativeExponent) { if (type1 == TCL_NUMBER_LONG) { diff --git a/generic/tclInt.h b/generic/tclInt.h index bb02ddf..3799287 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4589,11 +4589,25 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ - (objPtr)->internalRep.wideValue = (long)(i); \ + (objPtr)->internalRep.wideValue = (Tcl_WideInt)(i); \ (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) +#ifndef TCL_WIDE_INT_IS_LONG +#define TclNewWideObj(objPtr, i) \ + do { \ + TclIncrObjsAllocated(); \ + TclAllocObjStorage(objPtr); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = NULL; \ + (objPtr)->internalRep.wideValue = (Tcl_WideInt)(i); \ + (objPtr)->typePtr = &tclWideIntType; \ + TCL_DTRACE_OBJ_CREATE(objPtr); \ + } while (0) +#else +#define TclNewWideObj(objPtr, i) TclNewLongObj(objPtr, i) +#endif #define TclNewDoubleObj(objPtr, d) \ do { \ TclIncrObjsAllocated(); \ @@ -4619,6 +4633,9 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; #define TclNewLongObj(objPtr, l) \ (objPtr) = Tcl_NewLongObj(l) +#define TclNewWideObj(objPtr, w) \ + (objPtr) = Tcl_NewWideIntObj(w) + #define TclNewDoubleObj(objPtr, d) \ (objPtr) = Tcl_NewDoubleObj(d) diff --git a/generic/tclObj.c b/generic/tclObj.c index 78d7518..e4613ba 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3550,12 +3550,7 @@ TclGetNumberFromObj( *clientDataPtr = &objPtr->internalRep.doubleValue; return TCL_OK; } - if (objPtr->typePtr == &tclIntType) { - *typePtr = TCL_NUMBER_LONG; - *clientDataPtr = &objPtr->internalRep.wideValue; - return TCL_OK; - } - if (objPtr->typePtr == &tclWideIntType) { + if (objPtr->typePtr == &tclIntType || objPtr->typePtr == &tclWideIntType) { *typePtr = TCL_NUMBER_WIDE; *clientDataPtr = &objPtr->internalRep.wideValue; return TCL_OK; -- cgit v0.12 From c8fbbd8f3eef002f8913793c394ddc6f9e416da1 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 31 Oct 2017 11:37:29 +0000 Subject: Fix 2 failing test-cases, broken by some earlier commit --- generic/tclExecute.c | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index ee9e2e0..76e1496 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5893,13 +5893,15 @@ TEBCresume( ClientData ptr1, ptr2; int type1, type2; long l1, l2, lResult; + Tcl_WideInt w1, w2, wResult; case INST_NUM_TYPE: if (GetNumberFromObj(NULL, OBJ_AT_TOS, &ptr1, &type1) != TCL_OK) { type1 = 0; } else if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { - /* value is between LONG_MIN and LONG_MAX */ + /* value is between WIDE_MIN and WIDE_MAX */ /* [string is integer] is -UINT_MAX to UINT_MAX range */ + /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ int i; if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) != TCL_OK) { @@ -5909,10 +5911,14 @@ TEBCresume( } } else if (type1 == TCL_NUMBER_BIG) { /* value is an integer outside the WIDE_MIN to WIDE_MAX range */ + /* [string is integer] is -UINT_MAX to UINT_MAX range */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ + int i; Tcl_WideInt w; - if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &w) == TCL_OK) { + if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) == TCL_OK) { + type1 = TCL_NUMBER_LONG; + } else if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &w) == TCL_OK) { type1 = TCL_NUMBER_WIDE; } } @@ -5951,10 +5957,10 @@ TEBCresume( compare = MP_EQ; goto convertComparison; } - if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - l1 = *((const Tcl_WideInt *)ptr1); - l2 = *((const Tcl_WideInt *)ptr2); - compare = (l1 < l2) ? MP_LT : ((l1 > l2) ? MP_GT : MP_EQ); + if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + w1 = *((const Tcl_WideInt *)ptr1); + w2 = *((const Tcl_WideInt *)ptr2); + compare = (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ); } else { compare = TclCompareTwoNumbers(valuePtr, value2Ptr); } @@ -6280,15 +6286,13 @@ TEBCresume( */ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - Tcl_WideInt w1, w2, wResult; - - l1 = *((const Tcl_WideInt *)ptr1); - l2 = *((const Tcl_WideInt *)ptr2); + w1 = *((const Tcl_WideInt *)ptr1); + w2 = *((const Tcl_WideInt *)ptr2); + l1 = w1; + l2 = w2; switch (*pc) { case INST_ADD: - w1 = (Tcl_WideInt) l1; - w2 = (Tcl_WideInt) l2; wResult = w1 + w2; /* * Check for overflow. @@ -6300,8 +6304,6 @@ TEBCresume( goto wideResultOfArithmetic; case INST_SUB: - w1 = (Tcl_WideInt) l1; - w2 = (Tcl_WideInt) l2; wResult = w1 - w2; /* * Must check for overflow. The macro tests for overflows in @@ -6328,40 +6330,40 @@ TEBCresume( NEXT_INST_F(1, 1, 0); case INST_DIV: - if (l2 == 0) { + if (w2 == 0) { TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr), O2S(value2Ptr))); goto divideByZero; - } else if ((l1 == LONG_MIN) && (l2 == -1)) { + } else if ((w1 == LLONG_MIN) && (w2 == -1)) { /* - * Can't represent (-LONG_MIN) as a long. + * Can't represent (-LLONG_MIN) as a long. */ goto overflow; } - lResult = l1 / l2; + wResult = w1 / w2; /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ - if (((lResult < 0) || ((lResult == 0) && - ((l1 < 0 && l2 > 0) || (l1 > 0 && l2 < 0)))) && - ((lResult * l2) != l1)) { - lResult -= 1; + if (((wResult < 0) || ((wResult == 0) && + ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) && + ((wResult * w2) != w1)) { + wResult -= 1; } - goto longResultOfArithmetic; + goto wideResultOfArithmetic; case INST_MULT: if (((sizeof(long) >= 2*sizeof(int)) - && (l1 <= INT_MAX) && (l1 >= INT_MIN) - && (l2 <= INT_MAX) && (l2 >= INT_MIN)) + && (w1 <= INT_MAX) && (w1 >= INT_MIN) + && (w2 <= INT_MAX) && (w2 >= INT_MIN)) || ((sizeof(long) >= 2*sizeof(short)) - && (l1 <= SHRT_MAX) && (l1 >= SHRT_MIN) - && (l2 <= SHRT_MAX) && (l2 >= SHRT_MIN))) { - lResult = l1 * l2; - goto longResultOfArithmetic; + && (w1 <= SHRT_MAX) && (w1 >= SHRT_MIN) + && (w2 <= SHRT_MAX) && (w2 >= SHRT_MIN))) { + wResult = w1 * w2; + goto wideResultOfArithmetic; } } @@ -8227,8 +8229,8 @@ ExecuteExtendedBinaryMathOp( */ switch (type2) { - case TCL_NUMBER_WIDE: case TCL_NUMBER_LONG: + case TCL_NUMBER_WIDE: invalid = (*((const Tcl_WideInt *)ptr2) < (Tcl_WideInt)0); break; case TCL_NUMBER_BIG: @@ -8250,7 +8252,7 @@ ExecuteExtendedBinaryMathOp( * Zero shifted any number of bits is still zero. */ - if ((type1==TCL_NUMBER_LONG) && (*((const Tcl_WideInt *)ptr1) == (long)0)) { + if ((type1==TCL_NUMBER_LONG || type1==TCL_NUMBER_WIDE) && (*((const Tcl_WideInt *)ptr1) == (Tcl_WideInt)0)) { return constants[0]; } @@ -8308,8 +8310,6 @@ ExecuteExtendedBinaryMathOp( switch (type1) { case TCL_NUMBER_LONG: - zero = (*(const Tcl_WideInt *)ptr1 > 0L); - break; case TCL_NUMBER_WIDE: zero = (*(const Tcl_WideInt *)ptr1 > (Tcl_WideInt)0); break; @@ -8981,7 +8981,7 @@ ExecuteExtendedBinaryMathOp( case INST_SUB: wResult = w1 - w2; - if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) + if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { /* * Must check for overflow. The macro tests for overflows -- cgit v0.12 From 8fd76cb8733824c202c3eda72e9716013c8c2d82 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 31 Oct 2017 12:39:16 +0000 Subject: more simplifications --- generic/tclExecute.c | 57 ++++++++++------------------------------------------ 1 file changed, 11 insertions(+), 46 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 76e1496..ed4c00f 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -1877,35 +1877,6 @@ TclIncrObj( return TCL_ERROR; } - if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - long augend = *((const Tcl_WideInt *) ptr1); - long addend = *((const Tcl_WideInt *) ptr2); - long sum = augend + addend; - - /* - * Overflow when (augend and sum have different sign) and (augend and - * addend have the same sign). This is encapsulated in the Overflowing - * macro. - */ - - if (!Overflowing(augend, addend, sum)) { - TclSetLongObj(valuePtr, sum); - return TCL_OK; - } - { - Tcl_WideInt w1 = (Tcl_WideInt) augend; - Tcl_WideInt w2 = (Tcl_WideInt) addend; - - /* - * We know the sum value is outside the long range, so we use the - * macro form that doesn't range test again. - */ - - TclSetWideIntObj(valuePtr, w1 + w2); - return TCL_OK; - } - } - if ((type1 == TCL_NUMBER_DOUBLE) || (type1 == TCL_NUMBER_NAN)) { /* * Produce error message (reparse?!) @@ -8146,12 +8117,12 @@ ExecuteExtendedBinaryMathOp( /* TODO: Attempts to re-use unshared operands on stack */ l2 = 0; /* silence gcc warning */ - if (type2 == TCL_NUMBER_LONG) { - l2 = *((const Tcl_WideInt *)ptr2); - if (l2 == 0) { + if (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE) { + l2 = w2 = *((const Tcl_WideInt *)ptr2); + if (w2 == 0) { return DIVIDED_BY_ZERO; } - if ((l2 == 1) || (l2 == -1)) { + if ((w2 == 1) || (w2 == -1)) { /* * Div. by |1| always yields remainder of 0. */ @@ -8583,9 +8554,6 @@ ExecuteExtendedBinaryMathOp( switch (type2) { case TCL_NUMBER_LONG: - negativeExponent = (l2 < 0); - oddExponent = (int) (l2 & 1); - break; case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); negativeExponent = (w2 < 0); @@ -8600,12 +8568,12 @@ ExecuteExtendedBinaryMathOp( break; } - if (type1 == TCL_NUMBER_LONG) { - l1 = *((const Tcl_WideInt *)ptr1); + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + l1 = w1 = *((const Tcl_WideInt *)ptr1); } if (negativeExponent) { if (type1 == TCL_NUMBER_LONG) { - switch (l1) { + switch (w1) { case 0: /* * Zero to a negative power is div by zero error. @@ -8635,7 +8603,7 @@ ExecuteExtendedBinaryMathOp( } if (type1 == TCL_NUMBER_LONG) { - switch (l1) { + switch (w1) { case 0: /* * Zero to a positive power is zero. @@ -8764,9 +8732,7 @@ ExecuteExtendedBinaryMathOp( #endif } #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) - if (type1 == TCL_NUMBER_LONG) { - w1 = l1; - } else if (type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); } else { goto overflowExpon; @@ -9001,8 +8967,7 @@ ExecuteExtendedBinaryMathOp( break; case INST_MULT: - if ((type1 != TCL_NUMBER_LONG) || (type2 != TCL_NUMBER_LONG) - || (sizeof(Tcl_WideInt) < 2*sizeof(long))) { + if ((w1 < INT_MIN) || (w1 > INT_MAX) || (w2 < INT_MIN) || (w2 > INT_MAX)) { goto overflowBasic; } wResult = w1 * w2; @@ -9105,7 +9070,7 @@ ExecuteExtendedUnaryMathOp( switch (opcode) { case INST_BITNOT: - if (type == TCL_NUMBER_WIDE) { + if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) { w = *((const Tcl_WideInt *) ptr); WIDE_RESULT(~w); } -- cgit v0.12 From 2f2459e12003ac4f386e21b70b7929fe73859258 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 31 Oct 2017 14:40:33 +0000 Subject: more progress --- generic/tclExecute.c | 129 +++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 70 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index ed4c00f..704ee57 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5863,7 +5863,7 @@ TEBCresume( { ClientData ptr1, ptr2; int type1, type2; - long l1, l2, lResult; + long l1; Tcl_WideInt w1, w2, wResult; case INST_NUM_TYPE: @@ -6008,16 +6008,16 @@ TEBCresume( */ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - l1 = *((const Tcl_WideInt *)ptr1); - l2 = *((const Tcl_WideInt *)ptr2); + l1 = w1 = *((const Tcl_WideInt *)ptr1); + w2 = *((const Tcl_WideInt *)ptr2); switch (*pc) { case INST_MOD: - if (l2 == 0) { + if (w2 == 0) { TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr), O2S(value2Ptr))); goto divideByZero; - } else if ((l2 == 1) || (l2 == -1)) { + } else if ((w2 == 1) || (w2 == -1)) { /* * Div. by |1| always yields remainder of 0. */ @@ -6026,7 +6026,7 @@ TEBCresume( objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); - } else if (l1 == 0) { + } else if (w1 == 0) { /* * 0 % (non-zero) always yields remainder of 0. */ @@ -6036,24 +6036,24 @@ TEBCresume( TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else { - lResult = l1 / l2; + wResult = w1 / w2; /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ - if ((lResult < 0 || (lResult == 0 && - ((l1 < 0 && l2 > 0) || (l1 > 0 && l2 < 0)))) && - (lResult * l2 != l1)) { - lResult -= 1; + if ((wResult < 0 || (wResult == 0 && + ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) && + (wResult * w2 != w1)) { + wResult -= 1; } - lResult = l1 - l2*lResult; - goto longResultOfArithmetic; + wResult = w1 - w2*wResult; + goto wideResultOfArithmetic; } case INST_RSHIFT: - if (l2 < 0) { + if (w2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR @@ -6064,7 +6064,7 @@ TEBCresume( CACHE_STACK_INFO(); #endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */ goto gotError; - } else if (l1 == 0) { + } else if (w1 == 0) { TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); @@ -6074,7 +6074,7 @@ TEBCresume( * Quickly force large right shifts to 0 or -1. */ - if (l2 >= (long)(CHAR_BIT*sizeof(long))) { + if (w2 >= (long)(CHAR_BIT*sizeof(long))) { /* * We assume that INT_MAX is much larger than the * number of bits in a long. This is a pretty safe @@ -6083,7 +6083,7 @@ TEBCresume( */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); - if (l1 > 0L) { + if (w1 > 0L) { objResultPtr = TCONST(0); } else { TclNewLongObj(objResultPtr, -1); @@ -6096,12 +6096,12 @@ TEBCresume( * Handle shifts within the native long range. */ - lResult = l1 >> ((int) l2); - goto longResultOfArithmetic; + wResult = w1 >> ((int) w2); + goto wideResultOfArithmetic; } case INST_LSHIFT: - if (l2 < 0) { + if (w2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR @@ -6112,12 +6112,12 @@ TEBCresume( CACHE_STACK_INFO(); #endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */ goto gotError; - } else if (l1 == 0) { + } else if (w1 == 0) { TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); - } else if (l2 > (long) INT_MAX) { + } else if (w2 > (long) INT_MAX) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) * in an mp_int, but since we're using mp_mul_2d() to do @@ -6135,17 +6135,17 @@ TEBCresume( #endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */ goto gotError; } else { - int shift = (int) l2; + int shift = (int) w2; /* * Handle shifts within the native long range. */ - if ((size_t) shift < CHAR_BIT*sizeof(long) && (l1 != 0) - && !((l1>0 ? l1 : ~l1) & + if ((size_t) shift < CHAR_BIT*sizeof(long) && (w1 != 0) + && !((w1>0 ? w1 : ~w1) & -(1L<<(CHAR_BIT*sizeof(long) - 1 - shift)))) { - lResult = l1 << shift; - goto longResultOfArithmetic; + wResult = w1 << shift; + goto wideResultOfArithmetic; } } @@ -6157,23 +6157,14 @@ TEBCresume( break; case INST_BITAND: - lResult = l1 & l2; - goto longResultOfArithmetic; + wResult = w1 & w2; + goto wideResultOfArithmetic; case INST_BITOR: - lResult = l1 | l2; - goto longResultOfArithmetic; + wResult = w1 | w2; + goto wideResultOfArithmetic; case INST_BITXOR: - lResult = l1 ^ l2; - longResultOfArithmetic: - TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); - if (Tcl_IsShared(valuePtr)) { - TclNewLongObj(objResultPtr, lResult); - TRACE(("%s\n", O2S(objResultPtr))); - NEXT_INST_F(1, 2, 1); - } - TclSetLongObj(valuePtr, lResult); - TRACE(("%s\n", O2S(valuePtr))); - NEXT_INST_F(1, 1, 0); + wResult = w1 ^ w2; + goto wideResultOfArithmetic; } } @@ -6257,10 +6248,8 @@ TEBCresume( */ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - w1 = *((const Tcl_WideInt *)ptr1); + l1 = w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); - l1 = w1; - l2 = w2; switch (*pc) { case INST_ADD: @@ -6401,14 +6390,14 @@ TEBCresume( CACHE_STACK_INFO(); goto gotError; } - if (type1 == TCL_NUMBER_LONG) { - l1 = *((const Tcl_WideInt *) ptr1); + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + w1 = *((const Tcl_WideInt *) ptr1); if (Tcl_IsShared(valuePtr)) { - TclNewLongObj(objResultPtr, ~l1); + TclNewWideObj(objResultPtr, ~w1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } - TclSetLongObj(valuePtr, ~l1); + TclSetWideIntObj(valuePtr, ~w1); TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } @@ -6439,7 +6428,7 @@ TEBCresume( TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); case TCL_NUMBER_LONG: - l1 = *((const Tcl_WideInt *) ptr1); + l1 = w1 = *((const Tcl_WideInt *) ptr1); if (l1 != LONG_MIN) { if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, -l1); @@ -8501,8 +8490,8 @@ ExecuteExtendedBinaryMathOp( } WIDE_RESULT(wResult); } - l1 = *((const Tcl_WideInt *)ptr1); - l2 = *((const Tcl_WideInt *)ptr2); + l1 = w1 = *((const Tcl_WideInt *)ptr1); + l2 = w2 = *((const Tcl_WideInt *)ptr2); switch (opcode) { case INST_BITAND: @@ -8536,14 +8525,14 @@ ExecuteExtendedBinaryMathOp( } l1 = l2 = 0; if (type2 == TCL_NUMBER_LONG) { - l2 = *((const Tcl_WideInt *) ptr2); - if (l2 == 0) { + l2 = w2 = *((const Tcl_WideInt *) ptr2); + if (w2 == 0) { /* * Anything to the zero power is 1. */ return constants[1]; - } else if (l2 == 1) { + } else if (w2 == 1) { /* * Anything to the first power is itself */ @@ -8640,25 +8629,25 @@ ExecuteExtendedBinaryMathOp( } if (type1 == TCL_NUMBER_LONG) { - if (l1 == 2) { + if (w1 == 2) { /* * Reduce small powers of 2 to shifts. */ - if ((Tcl_WideUInt) l2 < (Tcl_WideUInt) CHAR_BIT*sizeof(Tcl_WideInt) - 1) { - WIDE_RESULT(((Tcl_WideInt) 1) << l2); + if ((Tcl_WideUInt) w2 < (Tcl_WideUInt) CHAR_BIT*sizeof(Tcl_WideInt) - 1) { + WIDE_RESULT(((Tcl_WideInt) 1) << (int)w2); } goto overflowExpon; } - if (l1 == -2) { + if (w1 == -2) { int signum = oddExponent ? -1 : 1; /* * Reduce small powers of 2 to shifts. */ - if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1){ - WIDE_RESULT(signum * (((Tcl_WideInt) 1) << l2)); + if ((Tcl_WideUInt)w2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1){ + WIDE_RESULT(signum * (((Tcl_WideInt) 1) << (int) w2)); } goto overflowExpon; } @@ -8737,19 +8726,19 @@ ExecuteExtendedBinaryMathOp( } else { goto overflowExpon; } - if (l2 - 2 < (long)MaxBase64Size - && w1 <= MaxBase64[l2 - 2] - && w1 >= -MaxBase64[l2 - 2]) { + if (w2 - 2 < (long)MaxBase64Size + && w1 <= MaxBase64[w2 - 2] + && w1 >= -MaxBase64[w2 - 2]) { /* * Small powers of integers whose result is wide. */ wResult = w1 * w1; /* b**2 */ - switch (l2) { + switch (w2) { case 2: break; case 3: - wResult *= l1; /* b**3 */ + wResult *= w1; /* b**3 */ break; case 4: wResult *= wResult; /* b**4 */ @@ -8826,9 +8815,9 @@ ExecuteExtendedBinaryMathOp( */ if (w1 - 3 >= 0 && w1 - 2 < (long)Exp64IndexSize - && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { + && w2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { base = Exp64Index[w1 - 3] - + (unsigned short) (l2 - 2 - MaxBase64Size); + + (unsigned short) (w2 - 2 - MaxBase64Size); if (base < Exp64Index[w1 - 2]) { /* * 64-bit number raised to intermediate power, done by @@ -8840,9 +8829,9 @@ ExecuteExtendedBinaryMathOp( } if (-w1 - 3 >= 0 && -w1 - 2 < (long)Exp64IndexSize - && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { + && w2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { base = Exp64Index[-w1 - 3] - + (unsigned short) (l2 - 2 - MaxBase64Size); + + (unsigned short) (w2 - 2 - MaxBase64Size); if (base < Exp64Index[-w1 - 2]) { /* * 64-bit number raised to intermediate power, done by -- cgit v0.12 From db930a501ff7f2b3826325f52d9bbcf2f26eaead Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 31 Oct 2017 14:48:28 +0000 Subject: Only use 64-bit tables for all platforms --- generic/tclExecute.c | 105 --------------------------------------------------- 1 file changed, 105 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 704ee57..2c77979 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -576,40 +576,6 @@ VarHashCreateVar( * Auxiliary tables used to compute powers of small integers. */ -#if (LONG_MAX == 0x7fffffff) - -/* - * Maximum base that, when raised to powers 2, 3, ... 8, fits in a 32-bit - * signed integer. - */ - -static const long MaxBase32[] = {46340, 1290, 215, 73, 35, 21, 14}; -static const size_t MaxBase32Size = sizeof(MaxBase32)/sizeof(long); - -/* - * Table giving 3, 4, ..., 11, raised to the powers 9, 10, ..., as far as they - * fit in a 32-bit signed integer. Exp32Index[i] gives the starting index of - * powers of i+3; Exp32Value[i] gives the corresponding powers. - */ - -static const unsigned short Exp32Index[] = { - 0, 11, 18, 23, 26, 29, 31, 32, 33 -}; -static const size_t Exp32IndexSize = - sizeof(Exp32Index) / sizeof(unsigned short); -static const long Exp32Value[] = { - 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, - 129140163, 387420489, 1162261467, 262144, 1048576, 4194304, - 16777216, 67108864, 268435456, 1073741824, 1953125, 9765625, - 48828125, 244140625, 1220703125, 10077696, 60466176, 362797056, - 40353607, 282475249, 1977326743, 134217728, 1073741824, 387420489, - 1000000000 -}; -static const size_t Exp32ValueSize = sizeof(Exp32Value)/sizeof(long); -#endif /* LONG_MAX == 0x7fffffff -- 32 bit machine */ - -#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) - /* * Maximum base that, when raised to powers 2, 3, ..., 16, fits in a * Tcl_WideInt. @@ -713,7 +679,6 @@ static const Tcl_WideInt Exp64Value[] = { (Tcl_WideInt)371293*371293*371293*13*13 }; static const size_t Exp64ValueSize = sizeof(Exp64Value) / sizeof(Tcl_WideInt); -#endif /* (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) */ /* * Markers for ExecuteExtendedBinaryMathOp. @@ -8651,76 +8616,7 @@ ExecuteExtendedBinaryMathOp( } goto overflowExpon; } -#if (LONG_MAX == 0x7fffffff) - if (l2 - 2 < (long)MaxBase32Size - && l1 <= MaxBase32[l2 - 2] - && l1 >= -MaxBase32[l2 - 2]) { - /* - * Small powers of 32-bit integers. - */ - - lResult = l1 * l1; /* b**2 */ - switch (l2) { - case 2: - break; - case 3: - lResult *= l1; /* b**3 */ - break; - case 4: - lResult *= lResult; /* b**4 */ - break; - case 5: - lResult *= lResult; /* b**4 */ - lResult *= l1; /* b**5 */ - break; - case 6: - lResult *= l1; /* b**3 */ - lResult *= lResult; /* b**6 */ - break; - case 7: - lResult *= l1; /* b**3 */ - lResult *= lResult; /* b**6 */ - lResult *= l1; /* b**7 */ - break; - case 8: - lResult *= lResult; /* b**4 */ - lResult *= lResult; /* b**8 */ - break; - } - WIDE_RESULT(lResult); - } - - if (l1 - 3 >= 0 && l1 -2 < (long)Exp32IndexSize - && l2 - 2 < (long)(Exp32ValueSize + MaxBase32Size)) { - base = Exp32Index[l1 - 3] - + (unsigned short) (l2 - 2 - MaxBase32Size); - if (base < Exp32Index[l1 - 2]) { - /* - * 32-bit number raised to intermediate power, done by - * table lookup. - */ - - WIDE_RESULT(Exp32Value[base]); - } - } - if (-l1 - 3 >= 0 && -l1 - 2 < (long)Exp32IndexSize - && l2 - 2 < (long)(Exp32ValueSize + MaxBase32Size)) { - base = Exp32Index[-l1 - 3] - + (unsigned short) (l2 - 2 - MaxBase32Size); - if (base < Exp32Index[-l1 - 2]) { - /* - * 32-bit number raised to intermediate power, done by - * table lookup. - */ - - lResult = (oddExponent) ? - -Exp32Value[base] : Exp32Value[base]; - WIDE_RESULT(lResult); - } - } -#endif } -#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); } else { @@ -8842,7 +8738,6 @@ ExecuteExtendedBinaryMathOp( WIDE_RESULT(wResult); } } -#endif overflowExpon: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); -- cgit v0.12 From 1cbd95eeee01fe3a144bba18c710be5c8442ff14 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 31 Oct 2017 16:16:46 +0000 Subject: eliminate most use of (long) type, except for increments --- generic/tclExecute.c | 110 ++++++++++++++++++--------------------------------- 1 file changed, 39 insertions(+), 71 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 2c77979..846b04f 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -3657,9 +3657,9 @@ TEBCresume( objPtr = varPtr->value.objPtr; if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) { - if (type == TCL_NUMBER_LONG) { - long augend = *((const Tcl_WideInt *)ptr); - long sum = augend + increment; + if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) { + Tcl_WideInt augend = *((const Tcl_WideInt *)ptr); + Tcl_WideInt sum = augend + increment; /* * Overflow when (augend and sum have different sign) and @@ -3671,12 +3671,12 @@ TEBCresume( TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ - TclNewLongObj(objResultPtr, sum); + TclNewWideObj(objResultPtr, sum); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; - TclSetLongObj(objPtr, sum); + TclSetWideIntObj(objPtr, sum); } goto doneIncr; } @@ -3699,38 +3699,7 @@ TEBCresume( TclSetWideIntObj(objPtr, w+increment); } goto doneIncr; - } /* end if (type == TCL_NUMBER_LONG) */ - if (type == TCL_NUMBER_WIDE) { - Tcl_WideInt sum; - - w = *((const Tcl_WideInt *) ptr); - sum = w + increment; - - /* - * Check for overflow. - */ - - if (!Overflowing(w, increment, sum)) { - TRACE(("%u %ld => ", opnd, increment)); - if (Tcl_IsShared(objPtr)) { - objPtr->refCount--; /* We know it's shared. */ - objResultPtr = Tcl_NewWideIntObj(sum); - Tcl_IncrRefCount(objResultPtr); - varPtr->value.objPtr = objResultPtr; - } else { - objResultPtr = objPtr; - - /* - * We *do not* know the sum value is outside the - * long range (wide + long can yield long); use - * the function call that checks range. - */ - - Tcl_SetWideIntObj(objPtr, sum); - } - goto doneIncr; - } - } + } /* end if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) */ } if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared */ @@ -5828,7 +5797,6 @@ TEBCresume( { ClientData ptr1, ptr2; int type1, type2; - long l1; Tcl_WideInt w1, w2, wResult; case INST_NUM_TYPE: @@ -5972,8 +5940,8 @@ TEBCresume( * Check for common, simple case. */ - if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - l1 = w1 = *((const Tcl_WideInt *)ptr1); + if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); switch (*pc) { @@ -6039,7 +6007,7 @@ TEBCresume( * Quickly force large right shifts to 0 or -1. */ - if (w2 >= (long)(CHAR_BIT*sizeof(long))) { + if (w2 >= (Tcl_WideInt)(CHAR_BIT*sizeof(long))) { /* * We assume that INT_MAX is much larger than the * number of bits in a long. This is a pretty safe @@ -6082,7 +6050,7 @@ TEBCresume( objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); - } else if (w2 > (long) INT_MAX) { + } else if (w2 > (Tcl_WideInt) INT_MAX) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) * in an mp_int, but since we're using mp_mul_2d() to do @@ -6212,8 +6180,8 @@ TEBCresume( * an external function. */ - if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { - l1 = w1 = *((const Tcl_WideInt *)ptr1); + if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); switch (*pc) { @@ -6393,14 +6361,15 @@ TEBCresume( TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); case TCL_NUMBER_LONG: - l1 = w1 = *((const Tcl_WideInt *) ptr1); - if (l1 != LONG_MIN) { + case TCL_NUMBER_WIDE: + w1 = *((const Tcl_WideInt *) ptr1); + if (w1 != LLONG_MIN) { if (Tcl_IsShared(valuePtr)) { - TclNewLongObj(objResultPtr, -l1); + TclNewWideObj(objResultPtr, -w1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } - TclSetLongObj(valuePtr, -l1); + TclSetWideIntObj(valuePtr, -w1); TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } @@ -8056,7 +8025,6 @@ ExecuteExtendedBinaryMathOp( int type1, type2; ClientData ptr1, ptr2; double d1, d2, dResult; - long l1, l2, lResult; Tcl_WideInt w1, w2, wResult; mp_int big1, big2, bigResult, bigRemainder; Tcl_Obj *objResultPtr; @@ -8070,9 +8038,9 @@ ExecuteExtendedBinaryMathOp( case INST_MOD: /* TODO: Attempts to re-use unshared operands on stack */ - l2 = 0; /* silence gcc warning */ + w2 = 0; /* silence gcc warning */ if (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE) { - l2 = w2 = *((const Tcl_WideInt *)ptr2); + w2 = *((const Tcl_WideInt *)ptr2); if (w2 == 0) { return DIVIDED_BY_ZERO; } @@ -8190,7 +8158,7 @@ ExecuteExtendedBinaryMathOp( * counterparts, leading to incorrect results. */ - if ((type2 != TCL_NUMBER_LONG) + if ((type2 != TCL_NUMBER_LONG && type2 != TCL_NUMBER_WIDE) || (*((const Tcl_WideInt *)ptr2) > (long) INT_MAX)) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) in @@ -8223,7 +8191,7 @@ ExecuteExtendedBinaryMathOp( * Quickly force large right shifts to 0 or -1. */ - if ((type2 != TCL_NUMBER_LONG) + if ((type2 != TCL_NUMBER_LONG && type2 != TCL_NUMBER_WIDE) || (*(const Tcl_WideInt *)ptr2 > INT_MAX)) { /* * Again, technically, the value to be shifted could be an @@ -8258,7 +8226,7 @@ ExecuteExtendedBinaryMathOp( * Handle shifts within the native wide range. */ - if (type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { w1 = *(const Tcl_WideInt *)ptr1; if ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideInt)) { if (w1 >= (Tcl_WideInt)0) { @@ -8435,7 +8403,7 @@ ExecuteExtendedBinaryMathOp( BIG_RESULT(&bigResult); } - if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) { + if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { TclGetWideIntFromObj(NULL, valuePtr, &w1); TclGetWideIntFromObj(NULL, value2Ptr, &w2); @@ -8455,24 +8423,24 @@ ExecuteExtendedBinaryMathOp( } WIDE_RESULT(wResult); } - l1 = w1 = *((const Tcl_WideInt *)ptr1); - l2 = w2 = *((const Tcl_WideInt *)ptr2); + w1 = *((const Tcl_WideInt *)ptr1); + w2 = *((const Tcl_WideInt *)ptr2); switch (opcode) { case INST_BITAND: - lResult = l1 & l2; + wResult = w1 & w2; break; case INST_BITOR: - lResult = l1 | l2; + wResult = w1 | w2; break; case INST_BITXOR: - lResult = l1 ^ l2; + wResult = w1 ^ w2; break; default: /* Unused, here to silence compiler warning. */ - lResult = 0; + wResult = 0; } - WIDE_RESULT(lResult); + WIDE_RESULT(wResult); case INST_EXPON: { int oddExponent = 0, negativeExponent = 0; @@ -8488,9 +8456,9 @@ ExecuteExtendedBinaryMathOp( dResult = pow(d1, d2); goto doubleResult; } - l1 = l2 = 0; - if (type2 == TCL_NUMBER_LONG) { - l2 = w2 = *((const Tcl_WideInt *) ptr2); + w2 = 0; + if (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE) { + w2 = *((const Tcl_WideInt *) ptr2); if (w2 == 0) { /* * Anything to the zero power is 1. @@ -8523,10 +8491,10 @@ ExecuteExtendedBinaryMathOp( } if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { - l1 = w1 = *((const Tcl_WideInt *)ptr1); + w1 = *((const Tcl_WideInt *)ptr1); } if (negativeExponent) { - if (type1 == TCL_NUMBER_LONG) { + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { switch (w1) { case 0: /* @@ -8556,7 +8524,7 @@ ExecuteExtendedBinaryMathOp( return constants[0]; } - if (type1 == TCL_NUMBER_LONG) { + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { switch (w1) { case 0: /* @@ -8587,13 +8555,13 @@ ExecuteExtendedBinaryMathOp( * accept. */ - if (type2 != TCL_NUMBER_LONG) { + if (type2 != TCL_NUMBER_LONG && type2 != TCL_NUMBER_WIDE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "exponent too large", -1)); return GENERAL_ARITHMETIC_ERROR; } - if (type1 == TCL_NUMBER_LONG) { + if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { if (w1 == 2) { /* * Reduce small powers of 2 to shifts. @@ -8817,7 +8785,7 @@ ExecuteExtendedBinaryMathOp( switch (opcode) { case INST_ADD: wResult = w1 + w2; - if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) + if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { /* * Check for overflow. -- cgit v0.12 From adc216698f7b3e45354f185b714df1754c429aa9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 31 Oct 2017 16:40:57 +0000 Subject: Eliminate most usage of TCL_NUMBER_LONG, just use TCL_NUMBER_WIDE in stead (since both have the same internal representation now) --- generic/tclBasic.c | 3 +-- generic/tclExecute.c | 67 +++++++++++++++++++++------------------------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index a911028..f69e861 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -6466,7 +6466,6 @@ Tcl_ExprLongObj( resultPtr = Tcl_NewBignumObj(&big); /* FALLTHROUGH */ } - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: case TCL_NUMBER_BIG: result = TclGetLongFromObj(interp, resultPtr, ptr); @@ -7442,7 +7441,7 @@ ExprAbsFunc( return TCL_ERROR; } - if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) { + if (type == TCL_NUMBER_WIDE) { Tcl_WideInt l = *((const Tcl_WideInt *) ptr); if (l > (Tcl_WideInt)0) { diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 846b04f..9eed936 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -501,7 +501,7 @@ VarHashCreateVar( #ifdef TCL_WIDE_INT_IS_LONG #define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ - ? (*(tPtr) = TCL_NUMBER_LONG, \ + ? (*(tPtr) = TCL_NUMBER_WIDE, \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclDoubleType) \ @@ -516,7 +516,7 @@ VarHashCreateVar( #else /* !TCL_WIDE_INT_IS_LONG */ #define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ - ? (*(tPtr) = TCL_NUMBER_LONG, \ + ? (*(tPtr) = TCL_NUMBER_WIDE, \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclWideIntType) \ @@ -3657,7 +3657,7 @@ TEBCresume( objPtr = varPtr->value.objPtr; if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) { - if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) { + if (type == TCL_NUMBER_WIDE) { Tcl_WideInt augend = *((const Tcl_WideInt *)ptr); Tcl_WideInt sum = augend + increment; @@ -3699,7 +3699,7 @@ TEBCresume( TclSetWideIntObj(objPtr, w+increment); } goto doneIncr; - } /* end if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) */ + } /* end if (type == TCL_NUMBER_WIDE) */ } if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared */ @@ -5802,7 +5802,7 @@ TEBCresume( case INST_NUM_TYPE: if (GetNumberFromObj(NULL, OBJ_AT_TOS, &ptr1, &type1) != TCL_OK) { type1 = 0; - } else if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + } else if (type1 == TCL_NUMBER_WIDE) { /* value is between WIDE_MIN and WIDE_MAX */ /* [string is integer] is -UINT_MAX to UINT_MAX range */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ @@ -5815,14 +5815,10 @@ TEBCresume( } } else if (type1 == TCL_NUMBER_BIG) { /* value is an integer outside the WIDE_MIN to WIDE_MAX range */ - /* [string is integer] is -UINT_MAX to UINT_MAX range */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ - int i; Tcl_WideInt w; - if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) == TCL_OK) { - type1 = TCL_NUMBER_LONG; - } else if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &w) == TCL_OK) { + if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &w) == TCL_OK) { type1 = TCL_NUMBER_WIDE; } } @@ -5861,7 +5857,7 @@ TEBCresume( compare = MP_EQ; goto convertComparison; } - if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + if ((type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_WIDE)) { w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); compare = (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ); @@ -5940,7 +5936,7 @@ TEBCresume( * Check for common, simple case. */ - if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + if ((type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_WIDE)) { w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); @@ -6180,7 +6176,7 @@ TEBCresume( * an external function. */ - if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + if ((type1 == TCL_NUMBER_WIDE) && (type2 == TCL_NUMBER_WIDE)) { w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); @@ -6323,7 +6319,7 @@ TEBCresume( CACHE_STACK_INFO(); goto gotError; } - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); if (Tcl_IsShared(valuePtr)) { TclNewWideObj(objResultPtr, ~w1); @@ -6360,7 +6356,6 @@ TEBCresume( /* -NaN => NaN */ TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: w1 = *((const Tcl_WideInt *) ptr1); if (w1 != LLONG_MIN) { @@ -8039,7 +8034,7 @@ ExecuteExtendedBinaryMathOp( /* TODO: Attempts to re-use unshared operands on stack */ w2 = 0; /* silence gcc warning */ - if (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE) { + if (type2 == TCL_NUMBER_WIDE) { w2 = *((const Tcl_WideInt *)ptr2); if (w2 == 0) { return DIVIDED_BY_ZERO; @@ -8122,7 +8117,6 @@ ExecuteExtendedBinaryMathOp( */ switch (type2) { - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: invalid = (*((const Tcl_WideInt *)ptr2) < (Tcl_WideInt)0); break; @@ -8145,7 +8139,7 @@ ExecuteExtendedBinaryMathOp( * Zero shifted any number of bits is still zero. */ - if ((type1==TCL_NUMBER_LONG || type1==TCL_NUMBER_WIDE) && (*((const Tcl_WideInt *)ptr1) == (Tcl_WideInt)0)) { + if ((type1==TCL_NUMBER_WIDE) && (*((const Tcl_WideInt *)ptr1) == (Tcl_WideInt)0)) { return constants[0]; } @@ -8158,7 +8152,7 @@ ExecuteExtendedBinaryMathOp( * counterparts, leading to incorrect results. */ - if ((type2 != TCL_NUMBER_LONG && type2 != TCL_NUMBER_WIDE) + if ((type2 != TCL_NUMBER_WIDE) || (*((const Tcl_WideInt *)ptr2) > (long) INT_MAX)) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) in @@ -8191,7 +8185,7 @@ ExecuteExtendedBinaryMathOp( * Quickly force large right shifts to 0 or -1. */ - if ((type2 != TCL_NUMBER_LONG && type2 != TCL_NUMBER_WIDE) + if ((type2 != TCL_NUMBER_WIDE) || (*(const Tcl_WideInt *)ptr2 > INT_MAX)) { /* * Again, technically, the value to be shifted could be an @@ -8202,7 +8196,6 @@ ExecuteExtendedBinaryMathOp( */ switch (type1) { - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: zero = (*(const Tcl_WideInt *)ptr1 > (Tcl_WideInt)0); break; @@ -8226,7 +8219,7 @@ ExecuteExtendedBinaryMathOp( * Handle shifts within the native wide range. */ - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { w1 = *(const Tcl_WideInt *)ptr1; if ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideInt)) { if (w1 >= (Tcl_WideInt)0) { @@ -8403,7 +8396,7 @@ ExecuteExtendedBinaryMathOp( BIG_RESULT(&bigResult); } - if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) { + if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) { TclGetWideIntFromObj(NULL, valuePtr, &w1); TclGetWideIntFromObj(NULL, value2Ptr, &w2); @@ -8457,7 +8450,7 @@ ExecuteExtendedBinaryMathOp( goto doubleResult; } w2 = 0; - if (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE) { + if (type2 == TCL_NUMBER_WIDE) { w2 = *((const Tcl_WideInt *) ptr2); if (w2 == 0) { /* @@ -8475,7 +8468,6 @@ ExecuteExtendedBinaryMathOp( } switch (type2) { - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); negativeExponent = (w2 < 0); @@ -8490,11 +8482,11 @@ ExecuteExtendedBinaryMathOp( break; } - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *)ptr1); } if (negativeExponent) { - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { switch (w1) { case 0: /* @@ -8524,7 +8516,7 @@ ExecuteExtendedBinaryMathOp( return constants[0]; } - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { switch (w1) { case 0: /* @@ -8551,17 +8543,17 @@ ExecuteExtendedBinaryMathOp( * which means the max exponent value is 2**28-1 = 0x0fffffff = * 268435455, which fits into a signed 32 bit int which is within the * range of the long int type. This means any numeric Tcl_Obj value - * not using TCL_NUMBER_LONG type must hold a value larger than we + * not using TCL_NUMBER_WIDE type must hold a value larger than we * accept. */ - if (type2 != TCL_NUMBER_LONG && type2 != TCL_NUMBER_WIDE) { + if (type2 != TCL_NUMBER_WIDE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "exponent too large", -1)); return GENERAL_ARITHMETIC_ERROR; } - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { if (w1 == 2) { /* * Reduce small powers of 2 to shifts. @@ -8585,7 +8577,7 @@ ExecuteExtendedBinaryMathOp( goto overflowExpon; } } - if (type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) { + if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); } else { goto overflowExpon; @@ -8785,7 +8777,7 @@ ExecuteExtendedBinaryMathOp( switch (opcode) { case INST_ADD: wResult = w1 + w2; - if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) + if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) { /* * Check for overflow. @@ -8799,7 +8791,7 @@ ExecuteExtendedBinaryMathOp( case INST_SUB: wResult = w1 - w2; - if ((type1 == TCL_NUMBER_LONG || type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_LONG || type2 == TCL_NUMBER_WIDE)) + if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) { /* * Must check for overflow. The macro tests for overflows @@ -8922,7 +8914,7 @@ ExecuteExtendedUnaryMathOp( switch (opcode) { case INST_BITNOT: - if (type == TCL_NUMBER_LONG || type == TCL_NUMBER_WIDE) { + if (type == TCL_NUMBER_WIDE) { w = *((const Tcl_WideInt *) ptr); WIDE_RESULT(~w); } @@ -8935,7 +8927,6 @@ ExecuteExtendedUnaryMathOp( switch (type) { case TCL_NUMBER_DOUBLE: DOUBLE_RESULT(-(*((const double *) ptr))); - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: w = *((const Tcl_WideInt *) ptr); if (w != LLONG_MIN) { @@ -8990,11 +8981,9 @@ TclCompareTwoNumbers( (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2); switch (type1) { - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: w1 = *((const Tcl_WideInt *)ptr1); switch (type2) { - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); wideCompare: @@ -9052,7 +9041,6 @@ TclCompareTwoNumbers( d2 = *((const double *)ptr2); doubleCompare: return (d1 < d2) ? MP_LT : ((d1 > d2) ? MP_GT : MP_EQ); - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); d2 = (double) w2; @@ -9095,7 +9083,6 @@ TclCompareTwoNumbers( case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); switch (type2) { - case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: compare = mp_cmp_d(&big1, 0); mp_clear(&big1); -- cgit v0.12 From 9e2ed8b729812f2ab4c70025a0e71f255bec1a78 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 1 Nov 2017 12:35:40 +0000 Subject: Finally, get rid of tclWideIntType completely --- generic/tclAssembly.c | 2 +- generic/tclBasic.c | 2 +- generic/tclCmdMZ.c | 4 +-- generic/tclExecute.c | 68 +++++++++++++++++---------------------------------- generic/tclInt.h | 53 +++++---------------------------------- generic/tclObj.c | 67 +++++++++++++++----------------------------------- generic/tclStrToD.c | 4 +-- generic/tclTimer.c | 1 - generic/tclUtil.c | 4 +-- generic/tclZlib.c | 2 +- 10 files changed, 56 insertions(+), 151 deletions(-) diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index c7ded6e..0fd7c60 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -4266,7 +4266,7 @@ AddBasicBlockRangeToErrorInfo( Tcl_AppendObjToErrorInfo(interp, lineNo); Tcl_AddErrorInfo(interp, " and "); if (bbPtr->successor1 != NULL) { - TclSetWideIntObj(lineNo, bbPtr->successor1->startLine); + TclSetWideObj(lineNo, bbPtr->successor1->startLine); Tcl_AppendObjToErrorInfo(interp, lineNo); } else { Tcl_AddErrorInfo(interp, "end of assembly code"); diff --git a/generic/tclBasic.c b/generic/tclBasic.c index f69e861..f84b420 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -3651,7 +3651,7 @@ OldMathFuncProc( */ if (funcResult.type == TCL_INT) { - TclNewLongObj(valuePtr, funcResult.intValue); + TclNewWideObj(valuePtr, funcResult.intValue); } else if (funcResult.type == TCL_WIDE_INT) { valuePtr = Tcl_NewWideIntObj(funcResult.wideValue); } else { diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index c984bbe..8ab687f 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1596,7 +1596,6 @@ StringIsCmd( /* TODO */ if ((objPtr->typePtr == &tclDoubleType) || (objPtr->typePtr == &tclIntType) || - (objPtr->typePtr == &tclWideIntType) || (objPtr->typePtr == &tclBignumType)) { break; } @@ -1631,7 +1630,6 @@ StringIsCmd( goto failedIntParse; case STR_IS_ENTIER: if ((objPtr->typePtr == &tclIntType) || - (objPtr->typePtr == &tclWideIntType) || (objPtr->typePtr == &tclBignumType)) { break; } @@ -4289,7 +4287,7 @@ TclNRTryObjCmd( } info[0] = objv[i]; /* type */ - TclNewLongObj(info[1], code); /* returnCode */ + TclNewWideObj(info[1], code); /* returnCode */ if (info[2] == NULL) { /* errorCodePrefix */ TclNewObj(info[2]); } diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 9eed936..51f9bff 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -325,7 +325,7 @@ VarHashCreateVar( NEXT_INST_F(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ default: \ if ((condition) < 0) { \ - TclNewLongObj(objResultPtr, -1); \ + TclNewWideObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -346,7 +346,7 @@ VarHashCreateVar( NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ default: \ if ((condition) < 0) { \ - TclNewLongObj(objResultPtr, -1); \ + TclNewWideObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -357,7 +357,7 @@ VarHashCreateVar( #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ - TclNewLongObj(objResultPtr, -1); \ + TclNewWideObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -366,7 +366,7 @@ VarHashCreateVar( #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ - TclNewLongObj(objResultPtr, -1); \ + TclNewWideObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -498,7 +498,6 @@ VarHashCreateVar( * ClientData *ptrPtr, int *tPtr); */ -#ifdef TCL_WIDE_INT_IS_LONG #define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_WIDE, \ @@ -513,26 +512,6 @@ VarHashCreateVar( (((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \ ? TCL_ERROR : \ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) -#else /* !TCL_WIDE_INT_IS_LONG */ -#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ - (((objPtr)->typePtr == &tclIntType) \ - ? (*(tPtr) = TCL_NUMBER_WIDE, \ - *(ptrPtr) = (ClientData) \ - (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ - ((objPtr)->typePtr == &tclWideIntType) \ - ? (*(tPtr) = TCL_NUMBER_WIDE, \ - *(ptrPtr) = (ClientData) \ - (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ - ((objPtr)->typePtr == &tclDoubleType) \ - ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \ - ? (*(tPtr) = TCL_NUMBER_NAN) \ - : (*(tPtr) = TCL_NUMBER_DOUBLE)), \ - *(ptrPtr) = (ClientData) \ - (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \ - (((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \ - ? TCL_ERROR : \ - TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) -#endif /* TCL_WIDE_INT_IS_LONG */ /* * Macro used in this file to save a function call for common uses of @@ -873,9 +852,9 @@ TclCreateExecEnv( + (size_t) (size-1) * sizeof(Tcl_Obj *)); eePtr->execStackPtr = esPtr; - TclNewLongObj(eePtr->constants[0], 0); + TclNewWideObj(eePtr->constants[0], 0); Tcl_IncrRefCount(eePtr->constants[0]); - TclNewLongObj(eePtr->constants[1], 1); + TclNewWideObj(eePtr->constants[1], 1); Tcl_IncrRefCount(eePtr->constants[1]); eePtr->interp = interp; eePtr->callbackPtr = NULL; @@ -3676,7 +3655,7 @@ TEBCresume( varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; - TclSetWideIntObj(objPtr, sum); + TclSetWideObj(objPtr, sum); } goto doneIncr; } @@ -3696,7 +3675,7 @@ TEBCresume( * use macro form that doesn't range test again. */ - TclSetWideIntObj(objPtr, w+increment); + TclSetWideObj(objPtr, w+increment); } goto doneIncr; } /* end if (type == TCL_NUMBER_WIDE) */ @@ -3709,7 +3688,7 @@ TEBCresume( } else { objResultPtr = objPtr; } - TclNewLongObj(incrPtr, increment); + TclNewWideObj(incrPtr, increment); if (TclIncrObj(interp, objResultPtr, incrPtr) != TCL_OK) { Tcl_DecrRefCount(incrPtr); TRACE_ERROR(interp); @@ -3723,7 +3702,7 @@ TEBCresume( * All other cases, flow through to generic handling. */ - TclNewLongObj(incrPtr, increment); + TclNewWideObj(incrPtr, increment); Tcl_IncrRefCount(incrPtr); doIncrScalar: @@ -4421,7 +4400,7 @@ TEBCresume( NEXT_INST_F(1, 0, 1); } case INST_INFO_LEVEL_NUM: - TclNewLongObj(objResultPtr, iPtr->varFramePtr->level); + TclNewWideObj(objResultPtr, iPtr->varFramePtr->level); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_INFO_LEVEL_ARGS: { @@ -4790,7 +4769,7 @@ TEBCresume( TRACE_ERROR(interp); goto gotError; } - TclNewLongObj(objResultPtr, length); + TclNewWideObj(objResultPtr, length); TRACE_APPEND(("%d\n", length)); NEXT_INST_F(1, 1, 1); @@ -5261,7 +5240,7 @@ TEBCresume( case INST_STR_LEN: valuePtr = OBJ_AT_TOS; length = Tcl_GetCharLength(valuePtr); - TclNewLongObj(objResultPtr, length); + TclNewWideObj(objResultPtr, length); TRACE(("\"%.20s\" => %d\n", O2S(valuePtr), length)); NEXT_INST_F(1, 1, 1); @@ -5616,7 +5595,7 @@ TEBCresume( TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); - TclNewLongObj(objResultPtr, match); + TclNewWideObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_FIND_LAST: @@ -5624,7 +5603,7 @@ TEBCresume( TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); - TclNewLongObj(objResultPtr, match); + TclNewWideObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_CLASS: @@ -5822,7 +5801,7 @@ TEBCresume( type1 = TCL_NUMBER_WIDE; } } - TclNewLongObj(objResultPtr, type1); + TclNewWideObj(objResultPtr, type1); TRACE(("\"%.20s\" => %d\n", O2S(OBJ_AT_TOS), type1)); NEXT_INST_F(1, 1, 1); @@ -6015,7 +5994,7 @@ TEBCresume( if (w1 > 0L) { objResultPtr = TCONST(0); } else { - TclNewLongObj(objResultPtr, -1); + TclNewWideObj(objResultPtr, -1); } TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); @@ -6326,7 +6305,7 @@ TEBCresume( TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } - TclSetWideIntObj(valuePtr, ~w1); + TclSetWideObj(valuePtr, ~w1); TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } @@ -6364,7 +6343,7 @@ TEBCresume( TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } - TclSetWideIntObj(valuePtr, -w1); + TclSetWideObj(valuePtr, -w1); TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } @@ -6525,10 +6504,10 @@ TEBCresume( oldValuePtr = iterVarPtr->value.objPtr; if (oldValuePtr == NULL) { - TclNewLongObj(iterVarPtr->value.objPtr, -1); + TclNewWideObj(iterVarPtr->value.objPtr, -1); Tcl_IncrRefCount(iterVarPtr->value.objPtr); } else { - TclSetLongObj(oldValuePtr, -1); + TclSetWideObj(oldValuePtr, -1); } TRACE(("%u => loop iter count temp %d\n", opnd, iterTmpIndex)); @@ -6563,7 +6542,7 @@ TEBCresume( iterVarPtr = LOCAL(infoPtr->loopCtTemp); valuePtr = iterVarPtr->value.objPtr; iterNum = valuePtr->internalRep.wideValue + 1; - TclSetLongObj(valuePtr, iterNum); + TclSetWideObj(valuePtr, iterNum); /* * Check whether all value lists are exhausted and we should stop the @@ -6896,7 +6875,7 @@ TEBCresume( NEXT_INST_F(1, 0, -1); case INST_PUSH_RETURN_CODE: - TclNewLongObj(objResultPtr, result); + TclNewWideObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); @@ -7562,7 +7541,6 @@ TEBCresume( default: Tcl_Panic("clockRead instruction with unknown clock#"); } - /* TclNewWideObj(objResultPtr, wval); doesn't exist */ objResultPtr = Tcl_NewWideIntObj(wval); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(2, 0, 1); diff --git a/generic/tclInt.h b/generic/tclInt.h index 3799287..34e3e43 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2451,12 +2451,13 @@ typedef struct List { * WARNING: these macros eval their args more than once. */ -#define TclGetLongFromObj(interp, objPtr, longPtr) \ +#define TclGetLongFromObj(interp, objPtr, longPtr) Tcl_GetLongFromObj(interp, objPtr, longPtr) +#define TclGetLongFromObjX(interp, objPtr, longPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetLongFromObj((interp), (objPtr), (longPtr))) -#if (LONG_MAX == INT_MAX) +#if 0 #define TclGetIntFromObj(interp, objPtr, intPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? ((*(intPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ @@ -2480,21 +2481,11 @@ typedef struct List { * Tcl_WideInt *wideIntPtr); */ -#ifdef TCL_WIDE_INT_IS_LONG #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(wideIntPtr) = (Tcl_WideInt) \ ((objPtr)->internalRep.wideValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) -#else /* !TCL_WIDE_INT_IS_LONG */ -#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ - (((objPtr)->typePtr == &tclWideIntType) \ - ? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \ - ((objPtr)->typePtr == &tclIntType) \ - ? (*(wideIntPtr) = (Tcl_WideInt) \ - ((objPtr)->internalRep.wideValue), TCL_OK) : \ - Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) -#endif /* TCL_WIDE_INT_IS_LONG */ /* * Flag values for TclTraceDictPath(). @@ -2720,7 +2711,6 @@ MODULE_SCOPE const Tcl_ObjType tclDictType; MODULE_SCOPE const Tcl_ObjType tclProcBodyType; MODULE_SCOPE const Tcl_ObjType tclStringType; MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType; -MODULE_SCOPE const Tcl_ObjType tclWideIntType; MODULE_SCOPE const Tcl_ObjType tclRegexpType; MODULE_SCOPE Tcl_ObjType tclCmdNameType; @@ -4533,13 +4523,12 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; * core. They should only be called on unshared objects. The ANSI C * "prototypes" for these macros are: * - * MODULE_SCOPE void TclSetLongObj(Tcl_Obj *objPtr, long longValue); - * MODULE_SCOPE void TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); + * MODULE_SCOPE void TclSetWideObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d); *---------------------------------------------------------------- */ -#define TclSetLongObj(objPtr, i) \ +#define TclSetWideObj(objPtr, i) \ do { \ TclInvalidateStringRep(objPtr); \ TclFreeIntRep(objPtr); \ @@ -4547,18 +4536,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; (objPtr)->typePtr = &tclIntType; \ } while (0) -#ifdef TCL_WIDE_INT_IS_LONG -#define TclSetWideIntObj(objPtr, w) TclSetLongObj(objPtr, w) -#else -#define TclSetWideIntObj(objPtr, w) \ - do { \ - TclInvalidateStringRep(objPtr); \ - TclFreeIntRep(objPtr); \ - (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \ - (objPtr)->typePtr = &tclWideIntType; \ - } while (0) -#endif - #define TclSetDoubleObj(objPtr, d) \ do { \ TclInvalidateStringRep(objPtr); \ @@ -4573,7 +4550,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; * types, avoiding the corresponding function calls in time critical parts of * the core. The ANSI C "prototypes" for these macros are: * - * MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l); * MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d); * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, int len); @@ -4583,7 +4559,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; */ #ifndef TCL_MEM_DEBUG -#define TclNewLongObj(objPtr, i) \ +#define TclNewWideObj(objPtr, i) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ @@ -4594,20 +4570,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) -#ifndef TCL_WIDE_INT_IS_LONG -#define TclNewWideObj(objPtr, i) \ - do { \ - TclIncrObjsAllocated(); \ - TclAllocObjStorage(objPtr); \ - (objPtr)->refCount = 0; \ - (objPtr)->bytes = NULL; \ - (objPtr)->internalRep.wideValue = (Tcl_WideInt)(i); \ - (objPtr)->typePtr = &tclWideIntType; \ - TCL_DTRACE_OBJ_CREATE(objPtr); \ - } while (0) -#else -#define TclNewWideObj(objPtr, i) TclNewLongObj(objPtr, i) -#endif #define TclNewDoubleObj(objPtr, d) \ do { \ TclIncrObjsAllocated(); \ @@ -4630,9 +4592,6 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; } while (0) #else /* TCL_MEM_DEBUG */ -#define TclNewLongObj(objPtr, l) \ - (objPtr) = Tcl_NewLongObj(l) - #define TclNewWideObj(objPtr, w) \ (objPtr) = Tcl_NewWideIntObj(w) diff --git a/generic/tclObj.c b/generic/tclObj.c index e4613ba..04fdeaa 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -266,13 +266,6 @@ const Tcl_ObjType tclIntType = { UpdateStringOfInt, /* updateStringProc */ SetIntFromAny /* setFromAnyProc */ }; -const Tcl_ObjType tclWideIntType = { - "wideInt", /* name */ - NULL, /* freeIntRepProc */ - NULL, /* dupIntRepProc */ - UpdateStringOfInt, /* updateStringProc */ - SetIntFromAny /* setFromAnyProc */ -}; const Tcl_ObjType tclBignumType = { "bignum", /* name */ FreeBignum, /* freeIntRepProc */ @@ -1753,7 +1746,7 @@ Tcl_NewBooleanObj( { register Tcl_Obj *objPtr; - TclNewLongObj(objPtr, boolValue!=0); + TclNewWideObj(objPtr, boolValue!=0); return objPtr; } #endif /* TCL_MEM_DEBUG */ @@ -1848,7 +1841,7 @@ Tcl_SetBooleanObj( Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj"); } - TclSetLongObj(objPtr, boolValue!=0); + TclSetWideObj(objPtr, boolValue!=0); } #endif /* TCL_NO_DEPRECATED */ @@ -1907,10 +1900,6 @@ Tcl_GetBooleanFromObj( *boolPtr = 1; return TCL_OK; } - if (objPtr->typePtr == &tclWideIntType) { - *boolPtr = (objPtr->internalRep.wideValue != 0); - return TCL_OK; - } } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK == TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0))); return TCL_ERROR; @@ -1960,10 +1949,6 @@ TclSetBooleanFromAny( goto badBoolean; } - if (objPtr->typePtr == &tclWideIntType) { - goto badBoolean; - } - if (objPtr->typePtr == &tclDoubleType) { goto badBoolean; } @@ -2281,7 +2266,7 @@ Tcl_GetDoubleFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - *dblPtr = objPtr->internalRep.wideValue; + *dblPtr = (double) objPtr->internalRep.wideValue; return TCL_OK; } if (objPtr->typePtr == &tclBignumType) { @@ -2291,10 +2276,6 @@ Tcl_GetDoubleFromObj( *dblPtr = TclBignumToDouble(&big); return TCL_OK; } - if (objPtr->typePtr == &tclWideIntType) { - *dblPtr = (double) objPtr->internalRep.wideValue; - return TCL_OK; - } } while (SetDoubleFromAny(interp, objPtr) == TCL_OK); return TCL_ERROR; } @@ -2412,7 +2393,7 @@ Tcl_NewIntObj( { register Tcl_Obj *objPtr; - TclNewLongObj(objPtr, intValue); + TclNewWideObj(objPtr, intValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ @@ -2445,7 +2426,7 @@ Tcl_SetIntObj( Tcl_Panic("%s called with shared object", "Tcl_SetIntObj"); } - TclSetLongObj(objPtr, intValue); + TclSetWideObj(objPtr, intValue); } /* @@ -2610,7 +2591,7 @@ Tcl_NewLongObj( { register Tcl_Obj *objPtr; - TclNewLongObj(objPtr, longValue); + TclNewWideObj(objPtr, longValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ @@ -2711,7 +2692,7 @@ Tcl_SetLongObj( Tcl_Panic("%s called with shared object", "Tcl_SetLongObj"); } - TclSetLongObj(objPtr, longValue); + TclSetWideObj(objPtr, longValue); } /* @@ -2742,11 +2723,13 @@ Tcl_GetLongFromObj( register long *longPtr) /* Place to store resulting long. */ { do { +#if (LONG_MAX == LLONG_MAX) if (objPtr->typePtr == &tclIntType) { *longPtr = objPtr->internalRep.wideValue; return TCL_OK; } - if (objPtr->typePtr == &tclWideIntType) { +#else + if (objPtr->typePtr == &tclIntType) { /* * We return any integer in the range -ULONG_MAX to ULONG_MAX * converted to a long, ignoring overflow. The rule preserves @@ -2764,6 +2747,7 @@ Tcl_GetLongFromObj( } goto tooLarge; } +#endif if (objPtr->typePtr == &tclDoubleType) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -2802,7 +2786,9 @@ Tcl_GetLongFromObj( return TCL_OK; } } +#if (LONG_MAX != LLONG_MAX) tooLarge: +#endif if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_Obj *msg = Tcl_NewStringObj(s, -1); @@ -2966,12 +2952,7 @@ Tcl_SetWideIntObj( Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj"); } - if ((wideValue >= (Tcl_WideInt) LONG_MIN) - && (wideValue <= (Tcl_WideInt) LONG_MAX)) { - TclSetLongObj(objPtr, wideValue); - } else { - TclSetWideIntObj(objPtr, wideValue); - } + TclSetWideObj(objPtr, wideValue); } /* @@ -3003,12 +2984,8 @@ Tcl_GetWideIntFromObj( /* Place to store resulting long. */ { do { - if (objPtr->typePtr == &tclWideIntType) { - *wideIntPtr = objPtr->internalRep.wideValue; - return TCL_OK; - } if (objPtr->typePtr == &tclIntType) { - *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.wideValue; + *wideIntPtr = objPtr->internalRep.wideValue; return TCL_OK; } if (objPtr->typePtr == &tclDoubleType) { @@ -3303,10 +3280,6 @@ GetBignumFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - TclInitBignumFromLong(bignumValue, objPtr->internalRep.wideValue); - return TCL_OK; - } - if (objPtr->typePtr == &tclWideIntType) { TclInitBignumFromWideInt(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; @@ -3435,9 +3408,9 @@ Tcl_SetBignumObj( goto tooLargeForLong; } if (bignumValue->sign) { - TclSetLongObj(objPtr, -(long)value); + TclSetWideObj(objPtr, -(long)value); } else { - TclSetLongObj(objPtr, (long)value); + TclSetWideObj(objPtr, (long)value); } mp_clear(bignumValue); return; @@ -3461,9 +3434,9 @@ Tcl_SetBignumObj( goto tooLargeForWide; } if (bignumValue->sign) { - TclSetWideIntObj(objPtr, -(Tcl_WideInt)value); + TclSetWideObj(objPtr, -(Tcl_WideInt)value); } else { - TclSetWideIntObj(objPtr, (Tcl_WideInt)value); + TclSetWideObj(objPtr, (Tcl_WideInt)value); } mp_clear(bignumValue); return; @@ -3550,7 +3523,7 @@ TclGetNumberFromObj( *clientDataPtr = &objPtr->internalRep.doubleValue; return TCL_OK; } - if (objPtr->typePtr == &tclIntType || objPtr->typePtr == &tclWideIntType) { + if (objPtr->typePtr == &tclIntType) { *typePtr = TCL_NUMBER_WIDE; *clientDataPtr = &objPtr->internalRep.wideValue; return TCL_OK; diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index c8bc7b5..9663c21 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -1272,7 +1272,7 @@ TclParseNumber( (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) { #ifndef TCL_WIDE_INT_IS_LONG if (octalSignificandWide <= (MOST_BITS + signum)) { - objPtr->typePtr = &tclWideIntType; + objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.wideValue = - (Tcl_WideInt) octalSignificandWide; @@ -1319,7 +1319,7 @@ TclParseNumber( (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) { #ifndef TCL_WIDE_INT_IS_LONG if (significandWide <= MOST_BITS+signum) { - objPtr->typePtr = &tclWideIntType; + objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.wideValue = - (Tcl_WideInt) significandWide; diff --git a/generic/tclTimer.c b/generic/tclTimer.c index 279e110..54854d0 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -819,7 +819,6 @@ Tcl_AfterObjCmd( */ if (objv[1]->typePtr == &tclIntType - || objv[1]->typePtr == &tclWideIntType || objv[1]->typePtr == &tclBignumType || (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index) != TCL_OK)) { diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 198424f..61a84ce 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3768,9 +3768,7 @@ SetEndOffsetFromAny( TCL_PARSE_INTEGER_ONLY) != TCL_OK) { return TCL_ERROR; } - if ((objPtr->typePtr != &tclIntType) - && (objPtr->typePtr != &tclWideIntType) - ) { + if (objPtr->typePtr != &tclIntType) { goto badIndexFormat; } offset = objPtr->internalRep.wideValue; diff --git a/generic/tclZlib.c b/generic/tclZlib.c index 33eebd1..dc124f7 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -373,7 +373,7 @@ ConvertErrorToList( default: TclNewLiteralStringObj(objv[2], "UNKNOWN"); - TclNewLongObj(objv[3], code); + TclNewWideObj(objv[3], code); return Tcl_NewListObj(4, objv); } } -- cgit v0.12 From 42764c99bec23aaae227ff1aba60c1ff9e7d9230 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 7 Nov 2017 16:16:52 +0000 Subject: More code simplifications, with still equal functionality. --- generic/tclExecute.c | 6 ++---- generic/tclObj.c | 33 +++------------------------------ generic/tclStrToD.c | 40 ++++++---------------------------------- 3 files changed, 11 insertions(+), 68 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 51f9bff..68056c6 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5776,7 +5776,7 @@ TEBCresume( { ClientData ptr1, ptr2; int type1, type2; - Tcl_WideInt w1, w2, wResult; + Tcl_WideInt w1, w2, wResult; case INST_NUM_TYPE: if (GetNumberFromObj(NULL, OBJ_AT_TOS, &ptr1, &type1) != TCL_OK) { @@ -5787,9 +5787,7 @@ TEBCresume( /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ int i; - if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) != TCL_OK) { - type1 = TCL_NUMBER_WIDE; - } else { + if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) == TCL_OK) { type1 = TCL_NUMBER_LONG; } } else if (type1 == TCL_NUMBER_BIG) { diff --git a/generic/tclObj.c b/generic/tclObj.c index 04fdeaa..634f8db 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3393,38 +3393,12 @@ Tcl_SetBignumObj( Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj"); } if ((size_t) bignumValue->used - <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) { - unsigned long value = 0, numBytes = sizeof(long); - long scratch; + <= (CHAR_BIT * sizeof(Tcl_WideUInt) + DIGIT_BIT - 1) / DIGIT_BIT) { + Tcl_WideUInt value = 0, numBytes = sizeof(Tcl_WideUInt); + Tcl_WideUInt scratch; unsigned char *bytes = (unsigned char *) &scratch; if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) { - goto tooLargeForLong; - } - while (numBytes-- > 0) { - value = (value << CHAR_BIT) | *bytes++; - } - if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) { - goto tooLargeForLong; - } - if (bignumValue->sign) { - TclSetWideObj(objPtr, -(long)value); - } else { - TclSetWideObj(objPtr, (long)value); - } - mp_clear(bignumValue); - return; - } - tooLargeForLong: -#ifndef TCL_WIDE_INT_IS_LONG - if ((size_t) bignumValue->used - <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) { - Tcl_WideUInt value = 0; - unsigned long numBytes = sizeof(Tcl_WideInt); - Tcl_WideInt scratch; - unsigned char *bytes = (unsigned char *)&scratch; - - if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) { goto tooLargeForWide; } while (numBytes-- > 0) { @@ -3442,7 +3416,6 @@ Tcl_SetBignumObj( return; } tooLargeForWide: -#endif TclInvalidateStringRep(objPtr); TclFreeIntRep(objPtr); TclSetBignumIntRep(objPtr, bignumValue); diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 9663c21..ac2ca68 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -1268,21 +1268,7 @@ TclParseNumber( } } if (!octalSignificandOverflow) { - if (octalSignificandWide > - (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) { -#ifndef TCL_WIDE_INT_IS_LONG - if (octalSignificandWide <= (MOST_BITS + signum)) { - objPtr->typePtr = &tclIntType; - if (signum) { - objPtr->internalRep.wideValue = - - (Tcl_WideInt) octalSignificandWide; - } else { - objPtr->internalRep.wideValue = - (Tcl_WideInt) octalSignificandWide; - } - break; - } -#endif + if (octalSignificandWide > (MOST_BITS + signum)) { TclInitBignumFromWideUInt(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; @@ -1290,10 +1276,10 @@ TclParseNumber( objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.wideValue = - - (long) octalSignificandWide; + - (Tcl_WideInt) octalSignificandWide; } else { objPtr->internalRep.wideValue = - (long) octalSignificandWide; + (Tcl_WideInt) octalSignificandWide; } } } @@ -1315,21 +1301,7 @@ TclParseNumber( } returnInteger: if (!significandOverflow) { - if (significandWide > - (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) { -#ifndef TCL_WIDE_INT_IS_LONG - if (significandWide <= MOST_BITS+signum) { - objPtr->typePtr = &tclIntType; - if (signum) { - objPtr->internalRep.wideValue = - - (Tcl_WideInt) significandWide; - } else { - objPtr->internalRep.wideValue = - (Tcl_WideInt) significandWide; - } - break; - } -#endif + if (significandWide > MOST_BITS+signum) { TclInitBignumFromWideUInt(&significandBig, significandWide); significandOverflow = 1; @@ -1337,10 +1309,10 @@ TclParseNumber( objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.wideValue = - - (long) significandWide; + - (Tcl_WideInt) significandWide; } else { objPtr->internalRep.wideValue = - (long) significandWide; + (Tcl_WideInt) significandWide; } } } -- cgit v0.12 From 1ed5a135edb9b30eae6aa9dcc091929aba2c3864 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 14 Nov 2017 18:35:22 +0000 Subject: TIP 484 proposes a re-implementation of Tcl's "int" Tcl_ObjType. Since the new implementation is not consistent with the former one, any callers of Tcl_GetObjType("int") who are expecting the return value to point them at something playing by the former rules are at risk of having their code broken. In this branch I remove the registation of Tcl's "int" type, so such callers will get NULL (which they should already be able to handle) instead of something misleading them into breakage. Examine this branch and decide if it should be incorporated into TIP 484. --- generic/tclObj.c | 1 - 1 file changed, 1 deletion(-) diff --git a/generic/tclObj.c b/generic/tclObj.c index 634f8db..318e41f 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -383,7 +383,6 @@ TclInitObjSubsystem(void) Tcl_RegisterObjType(&tclByteArrayType); Tcl_RegisterObjType(&tclDoubleType); Tcl_RegisterObjType(&tclEndOffsetType); - Tcl_RegisterObjType(&tclIntType); Tcl_RegisterObjType(&tclStringType); Tcl_RegisterObjType(&tclListType); Tcl_RegisterObjType(&tclDictType); -- cgit v0.12 From 07c71d17a255fb07143dbb73659a64a589a214f6 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 19 Dec 2017 15:20:32 +0000 Subject: Somewhat better backwards compatibility on 64-bit platforms. --- generic/tclObj.c | 4 ++-- generic/tclTestObj.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/generic/tclObj.c b/generic/tclObj.c index 183ad7f..8ec95ce 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -262,10 +262,10 @@ const Tcl_ObjType tclDoubleType = { SetDoubleFromAny /* setFromAnyProc */ }; const Tcl_ObjType tclIntType = { -#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 +#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 || defined(TCL_WIDE_INT_IS_LONG) "int", /* name */ #else - "wideInt", /* name, keeping maximum compatibility with Tcl 8.6 */ + "wideInt", /* name, keeping maximum compatibility with Tcl 8.6 on 32-bit platforms*/ #endif NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 6b08761..547792a 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -1088,7 +1088,9 @@ TestobjCmd( Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); } else { typeName = objv[2]->typePtr->name; +#ifndef TCL_WIDE_INT_IS_LONG if (!strcmp(typeName, "wideInt")) typeName = "int"; +#endif Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1)); } } else if (strcmp(subCmd, "refcount") == 0) { @@ -1116,9 +1118,11 @@ TestobjCmd( } if (varPtr[varIndex]->typePtr == NULL) { /* a string! */ Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1); +#ifndef TCL_WIDE_INT_IS_LONG } else if (!strcmp(varPtr[varIndex]->typePtr->name, "wideInt")) { Tcl_AppendToObj(Tcl_GetObjResult(interp), "int", -1); +#endif } else { Tcl_AppendToObj(Tcl_GetObjResult(interp), varPtr[varIndex]->typePtr->name, -1); -- cgit v0.12 From 6631e46bd3d3c18c60f319c4879ce8682f954229 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 29 Dec 2017 16:49:47 +0000 Subject: Remove handling of http 1.0 package files from Makefiles. --- unix/Makefile.in | 9 ++------- win/Makefile.in | 7 +------ win/makefile.vc | 3 --- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index f3b9782..244ad29 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -829,7 +829,7 @@ install-libraries: libraries else true; \ fi; \ done; - @for i in opt0.4 http1.0 encoding ../tcl8 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5 ../tcl8/8.6; \ + @for i in opt0.4 encoding ../tcl8 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5 ../tcl8/8.6; \ do \ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \ @@ -843,11 +843,6 @@ install-libraries: libraries do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \ done; - @echo "Installing package http1.0 files to $(SCRIPT_INSTALL_DIR)/http1.0/"; - @for i in $(TOP_DIR)/library/http1.0/*.tcl ; \ - do \ - $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \ - done; @echo "Installing package http 2.8.12 as a Tcl Module"; @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.12.tm; @echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/"; @@ -2010,7 +2005,7 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in $(M @mkdir $(DISTDIR)/library cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \ $(TOP_DIR)/library/tclIndex $(DISTDIR)/library - for i in http1.0 http opt msgcat reg dde tcltest platform; \ + for i in http opt msgcat reg dde tcltest platform; \ do \ mkdir $(DISTDIR)/library/$$i ;\ cp -p $(TOP_DIR)/library/$$i/*.tcl $(DISTDIR)/library/$$i; \ diff --git a/win/Makefile.in b/win/Makefile.in index a3275ba..5be7492 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -630,7 +630,7 @@ install-libraries: libraries install-tzdata install-msgs else true; \ fi; \ done; - @for i in http1.0 opt0.4 encoding ../tcl8 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5 ../tcl8/8.6; \ + @for i in opt0.4 encoding ../tcl8 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5 ../tcl8/8.6; \ do \ if [ ! -d $(SCRIPT_INSTALL_DIR)/$$i ] ; then \ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \ @@ -652,11 +652,6 @@ install-libraries: libraries install-tzdata install-msgs do \ $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \ done; - @echo "Installing library http1.0 directory"; - @for j in $(ROOT_DIR)/library/http1.0/*.tcl; \ - do \ - $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \ - done; @echo "Installing package http 2.8.12 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.6/http-2.8.12.tm; @echo "Installing library opt0.4 directory"; diff --git a/win/makefile.vc b/win/makefile.vc index de80452..64717af 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -860,9 +860,6 @@ install-libraries: tclConfig tcl-nmake install-msgs install-tzdata @$(CPY) "$(WINDIR)\targets.vc" "$(LIB_INSTALL_DIR)\nmake\" @$(CPY) "$(WINDIR)\nmakehlp.c" "$(LIB_INSTALL_DIR)\nmake\" @$(CPY) "$(OUT_DIR)\tcl.nmake" "$(LIB_INSTALL_DIR)\nmake\" - @echo Installing library http1.0 directory - @$(CPY) "$(ROOT)\library\http1.0\*.tcl" \ - "$(SCRIPT_INSTALL_DIR)\http1.0\" @echo Installing library opt0.4 directory @$(CPY) "$(ROOT)\library\opt\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\opt0.4\" -- cgit v0.12 From a922e9fd15daadaa80f131c7cb9884423e6873a3 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 29 Dec 2017 16:54:50 +0000 Subject: Remove http 1.0 files from fossil management. --- library/http1.0/http.tcl | 377 ------------------------------------------- library/http1.0/pkgIndex.tcl | 11 -- 2 files changed, 388 deletions(-) delete mode 100644 library/http1.0/http.tcl delete mode 100644 library/http1.0/pkgIndex.tcl diff --git a/library/http1.0/http.tcl b/library/http1.0/http.tcl deleted file mode 100644 index 8329de4..0000000 --- a/library/http1.0/http.tcl +++ /dev/null @@ -1,377 +0,0 @@ -# http.tcl -# Client-side HTTP for GET, POST, and HEAD commands. -# These routines can be used in untrusted code that uses the Safesock -# security policy. -# These procedures use a callback interface to avoid using vwait, -# which is not defined in the safe base. -# -# See the http.n man page for documentation - -package provide http 1.0 - -array set http { - -accept */* - -proxyhost {} - -proxyport {} - -useragent {Tcl http client package 1.0} - -proxyfilter httpProxyRequired -} -proc http_config {args} { - global http - set options [lsort [array names http -*]] - set usage [join $options ", "] - if {[llength $args] == 0} { - set result {} - foreach name $options { - lappend result $name $http($name) - } - return $result - } - regsub -all -- - $options {} options - set pat ^-([join $options |])$ - if {[llength $args] == 1} { - set flag [lindex $args 0] - if {[regexp -- $pat $flag]} { - return $http($flag) - } else { - return -code error "Unknown option $flag, must be: $usage" - } - } else { - foreach {flag value} $args { - if {[regexp -- $pat $flag]} { - set http($flag) $value - } else { - return -code error "Unknown option $flag, must be: $usage" - } - } - } -} - - proc httpFinish { token {errormsg ""} } { - upvar #0 $token state - global errorInfo errorCode - if {[string length $errormsg] != 0} { - set state(error) [list $errormsg $errorInfo $errorCode] - set state(status) error - } - catch {close $state(sock)} - catch {after cancel $state(after)} - if {[info exists state(-command)]} { - if {[catch {eval $state(-command) {$token}} err]} { - if {[string length $errormsg] == 0} { - set state(error) [list $err $errorInfo $errorCode] - set state(status) error - } - } - unset state(-command) - } -} -proc http_reset { token {why reset} } { - upvar #0 $token state - set state(status) $why - catch {fileevent $state(sock) readable {}} - httpFinish $token - if {[info exists state(error)]} { - set errorlist $state(error) - unset state(error) - eval error $errorlist - } -} -proc http_get { url args } { - global http - if {![info exists http(uid)]} { - set http(uid) 0 - } - set token http#[incr http(uid)] - upvar #0 $token state - http_reset $token - array set state { - -blocksize 8192 - -validate 0 - -headers {} - -timeout 0 - state header - meta {} - currentsize 0 - totalsize 0 - type text/html - body {} - status "" - } - set options {-blocksize -channel -command -handler -headers \ - -progress -query -validate -timeout} - set usage [join $options ", "] - regsub -all -- - $options {} options - set pat ^-([join $options |])$ - foreach {flag value} $args { - if {[regexp $pat $flag]} { - # Validate numbers - if {[info exists state($flag)] && \ - [regexp {^[0-9]+$} $state($flag)] && \ - ![regexp {^[0-9]+$} $value]} { - return -code error "Bad value for $flag ($value), must be integer" - } - set state($flag) $value - } else { - return -code error "Unknown option $flag, can be: $usage" - } - } - if {! [regexp -nocase {^(http://)?([^/:]+)(:([0-9]+))?(/.*)?$} $url \ - x proto host y port srvurl]} { - error "Unsupported URL: $url" - } - if {[string length $port] == 0} { - set port 80 - } - if {[string length $srvurl] == 0} { - set srvurl / - } - if {[string length $proto] == 0} { - set url http://$url - } - set state(url) $url - if {![catch {$http(-proxyfilter) $host} proxy]} { - set phost [lindex $proxy 0] - set pport [lindex $proxy 1] - } - if {$state(-timeout) > 0} { - set state(after) [after $state(-timeout) [list http_reset $token timeout]] - } - if {[info exists phost] && [string length $phost]} { - set srvurl $url - set s [socket $phost $pport] - } else { - set s [socket $host $port] - } - set state(sock) $s - - # Send data in cr-lf format, but accept any line terminators - - fconfigure $s -translation {auto crlf} -buffersize $state(-blocksize) - - # The following is disallowed in safe interpreters, but the socket - # is already in non-blocking mode in that case. - - catch {fconfigure $s -blocking off} - set len 0 - set how GET - if {[info exists state(-query)]} { - set len [string length $state(-query)] - if {$len > 0} { - set how POST - } - } elseif {$state(-validate)} { - set how HEAD - } - puts $s "$how $srvurl HTTP/1.0" - puts $s "Accept: $http(-accept)" - puts $s "Host: $host" - puts $s "User-Agent: $http(-useragent)" - foreach {key value} $state(-headers) { - regsub -all \[\n\r\] $value {} value - set key [string trim $key] - if {[string length $key]} { - puts $s "$key: $value" - } - } - if {$len > 0} { - puts $s "Content-Length: $len" - puts $s "Content-Type: application/x-www-form-urlencoded" - puts $s "" - fconfigure $s -translation {auto binary} - puts -nonewline $s $state(-query) - } else { - puts $s "" - } - flush $s - fileevent $s readable [list httpEvent $token] - if {! [info exists state(-command)]} { - http_wait $token - } - return $token -} -proc http_data {token} { - upvar #0 $token state - return $state(body) -} -proc http_status {token} { - upvar #0 $token state - return $state(status) -} -proc http_code {token} { - upvar #0 $token state - return $state(http) -} -proc http_size {token} { - upvar #0 $token state - return $state(currentsize) -} - - proc httpEvent {token} { - upvar #0 $token state - set s $state(sock) - - if {[eof $s]} { - httpEof $token - return - } - if {$state(state) == "header"} { - set n [gets $s line] - if {$n == 0} { - set state(state) body - if {![regexp -nocase ^text $state(type)]} { - # Turn off conversions for non-text data - fconfigure $s -translation binary - if {[info exists state(-channel)]} { - fconfigure $state(-channel) -translation binary - } - } - if {[info exists state(-channel)] && - ![info exists state(-handler)]} { - # Initiate a sequence of background fcopies - fileevent $s readable {} - httpCopyStart $s $token - } - } elseif {$n > 0} { - if {[regexp -nocase {^content-type:(.+)$} $line x type]} { - set state(type) [string trim $type] - } - if {[regexp -nocase {^content-length:(.+)$} $line x length]} { - set state(totalsize) [string trim $length] - } - if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { - lappend state(meta) $key $value - } elseif {[regexp ^HTTP $line]} { - set state(http) $line - } - } - } else { - if {[catch { - if {[info exists state(-handler)]} { - set n [eval $state(-handler) {$s $token}] - } else { - set block [read $s $state(-blocksize)] - set n [string length $block] - if {$n >= 0} { - append state(body) $block - } - } - if {$n >= 0} { - incr state(currentsize) $n - } - } err]} { - httpFinish $token $err - } else { - if {[info exists state(-progress)]} { - eval $state(-progress) {$token $state(totalsize) $state(currentsize)} - } - } - } -} - proc httpCopyStart {s token} { - upvar #0 $token state - if {[catch { - fcopy $s $state(-channel) -size $state(-blocksize) -command \ - [list httpCopyDone $token] - } err]} { - httpFinish $token $err - } -} - proc httpCopyDone {token count {error {}}} { - upvar #0 $token state - set s $state(sock) - incr state(currentsize) $count - if {[info exists state(-progress)]} { - eval $state(-progress) {$token $state(totalsize) $state(currentsize)} - } - if {([string length $error] != 0)} { - httpFinish $token $error - } elseif {[eof $s]} { - httpEof $token - } else { - httpCopyStart $s $token - } -} - proc httpEof {token} { - upvar #0 $token state - if {$state(state) == "header"} { - # Premature eof - set state(status) eof - } else { - set state(status) ok - } - set state(state) eof - httpFinish $token -} -proc http_wait {token} { - upvar #0 $token state - if {![info exists state(status)] || [string length $state(status)] == 0} { - vwait $token\(status) - } - if {[info exists state(error)]} { - set errorlist $state(error) - unset state(error) - eval error $errorlist - } - return $state(status) -} - -# Call http_formatQuery with an even number of arguments, where the first is -# a name, the second is a value, the third is another name, and so on. - -proc http_formatQuery {args} { - set result "" - set sep "" - foreach i $args { - append result $sep [httpMapReply $i] - if {$sep != "="} { - set sep = - } else { - set sep & - } - } - return $result -} - -# do x-www-urlencoded character mapping -# The spec says: "non-alphanumeric characters are replaced by '%HH'" -# 1 leave alphanumerics characters alone -# 2 Convert every other character to an array lookup -# 3 Escape constructs that are "special" to the tcl parser -# 4 "subst" the result, doing all the array substitutions - - proc httpMapReply {string} { - global httpFormMap - set alphanumeric a-zA-Z0-9 - if {![info exists httpFormMap]} { - - for {set i 1} {$i <= 256} {incr i} { - set c [format %c $i] - if {![string match \[$alphanumeric\] $c]} { - set httpFormMap($c) %[format %.2x $i] - } - } - # These are handled specially - array set httpFormMap { - " " + \n %0d%0a - } - } - regsub -all \[^$alphanumeric\] $string {$httpFormMap(&)} string - regsub -all \n $string {\\n} string - regsub -all \t $string {\\t} string - regsub -all {[][{})\\]\)} $string {\\&} string - return [subst $string] -} - -# Default proxy filter. - proc httpProxyRequired {host} { - global http - if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} { - if {![info exists http(-proxyport)] || ![string length $http(-proxyport)]} { - set http(-proxyport) 8080 - } - return [list $http(-proxyhost) $http(-proxyport)] - } else { - return {} - } -} diff --git a/library/http1.0/pkgIndex.tcl b/library/http1.0/pkgIndex.tcl deleted file mode 100644 index ab6170f..0000000 --- a/library/http1.0/pkgIndex.tcl +++ /dev/null @@ -1,11 +0,0 @@ -# Tcl package index file, version 1.0 -# This file is generated by the "pkg_mkIndex" command -# and sourced either when an application starts up or -# by a "package unknown" script. It invokes the -# "package ifneeded" command to set up package-related -# information so that packages will be loaded automatically -# in response to "package require" commands. When this -# script is sourced, the variable $dir must contain the -# full path name of this file's directory. - -package ifneeded http 1.0 [list tclPkgSetup $dir http 1.0 {{http.tcl source {httpCopyDone httpCopyStart httpEof httpEvent httpFinish httpMapReply httpProxyRequired http_code http_config http_data http_formatQuery http_get http_reset http_size http_status http_wait}}}] -- cgit v0.12 From b0898beca68aa150062cb6eacc8daee6e6490f55 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 29 Dec 2017 17:38:10 +0000 Subject: Remove http 1.0 tests. --- tests/httpold.test | 300 ----------------------------------------------------- 1 file changed, 300 deletions(-) delete mode 100644 tests/httpold.test diff --git a/tests/httpold.test b/tests/httpold.test deleted file mode 100644 index dda0189..0000000 --- a/tests/httpold.test +++ /dev/null @@ -1,300 +0,0 @@ -# -*- tcl -*- -# Commands covered: http_config, http_get, http_wait, http_reset -# -# This file contains a collection of tests for the http script library. -# Sourcing this file into Tcl runs the tests and -# generates output for errors. No output means no errors were found. -# -# Copyright (c) 1991-1993 The Regents of the University of California. -# Copyright (c) 1994-1996 Sun Microsystems, Inc. -# Copyright (c) 1998-1999 by Scriptics Corporation. -# -# See the file "license.terms" for information on usage and redistribution -# of this file, and for a DISCLAIMER OF ALL WARRANTIES. - -if {[lsearch [namespace children] ::tcltest] == -1} { - package require tcltest - namespace import -force ::tcltest::* -} - -if {[catch {package require http 1.0}]} { - if {[info exists httpold]} { - catch {puts "Cannot load http 1.0 package"} - ::tcltest::cleanupTests - return - } else { - catch {puts "Running http 1.0 tests in slave interp"} - set interp [interp create httpold] - $interp eval [list set httpold "running"] - $interp eval [list set argv $argv] - $interp eval [list source [info script]] - interp delete $interp - ::tcltest::cleanupTests - return - } -} - -if {$::tcl_platform(os) eq "Darwin"} { - # Name resolution often a problem on OSX; not focus of HTTP package anyway - set HOST localhost -} else { - set HOST [info hostname] -} - -set bindata "This is binary data\x0d\x0amore\x0dmore\x0amore\x00null" -catch {unset data} - -## -## The httpd script implement a stub http server -## -source [file join [file dirname [info script]] httpd] - -if [catch {httpd_init 0} listen] { - puts "Cannot start http server, http test skipped" - catch {unset port} - ::tcltest::cleanupTests - return -} - -test httpold-1.1 {http_config} { - http_config -} {-accept */* -proxyfilter httpProxyRequired -proxyhost {} -proxyport {} -useragent {Tcl http client package 1.0}} - -test httpold-1.2 {http_config} { - http_config -proxyfilter -} httpProxyRequired - -test httpold-1.3 {http_config} { - catch {http_config -junk} -} 1 - -test httpold-1.4 {http_config} { - http_config -proxyhost nowhere.come -proxyport 8080 -proxyfilter myFilter -useragent "Tcl Test Suite" - set x [http_config] - http_config -proxyhost {} -proxyport {} -proxyfilter httpProxyRequired \ - -useragent "Tcl http client package 1.0" - set x -} {-accept */* -proxyfilter myFilter -proxyhost nowhere.come -proxyport 8080 -useragent {Tcl Test Suite}} - -test httpold-1.5 {http_config} { - catch {http_config -proxyhost {} -junk 8080} -} 1 - -test httpold-2.1 {http_reset} { - catch {http_reset http#1} -} 0 - -test httpold-3.1 {http_get} { - catch {http_get -bogus flag} -} 1 -test httpold-3.2 {http_get} { - catch {http_get http:junk} err - set err -} {Unsupported URL: http:junk} - -set url ${::HOST}:$port -test httpold-3.3 {http_get} { - set token [http_get $url] - http_data $token -} "HTTP/1.0 TEST -

Hello, World!

-

GET /

-" - -set tail /a/b/c -set url ${::HOST}:$port/a/b/c -set binurl ${::HOST}:$port/binary - -test httpold-3.4 {http_get} { - set token [http_get $url] - http_data $token -} "HTTP/1.0 TEST -

Hello, World!

-

GET $tail

-" - -proc selfproxy {host} { - global port - return [list ${::HOST} $port] -} -test httpold-3.5 {http_get} { - http_config -proxyfilter selfproxy - set token [http_get $url] - http_config -proxyfilter httpProxyRequired - http_data $token -} "HTTP/1.0 TEST -

Hello, World!

-

GET http://$url

-" - -test httpold-3.6 {http_get} { - http_config -proxyfilter bogus - set token [http_get $url] - http_config -proxyfilter httpProxyRequired - http_data $token -} "HTTP/1.0 TEST -

Hello, World!

-

GET $tail

-" - -test httpold-3.7 {http_get} { - set token [http_get $url -headers {Pragma no-cache}] - http_data $token -} "HTTP/1.0 TEST -

Hello, World!

-

GET $tail

-" - -test httpold-3.8 {http_get} { - set token [http_get $url -query Name=Value&Foo=Bar] - http_data $token -} "HTTP/1.0 TEST -

Hello, World!

-

POST $tail

-

Query

-
-
Name
Value -
Foo
Bar -
-" - -test httpold-3.9 {http_get} { - set token [http_get $url -validate 1] - http_code $token -} "HTTP/1.0 200 OK" - - -test httpold-4.1 {httpEvent} { - set token [http_get $url] - upvar #0 $token data - array set meta $data(meta) - expr ($data(totalsize) == $meta(Content-Length)) -} 1 - -test httpold-4.2 {httpEvent} { - set token [http_get $url] - upvar #0 $token data - array set meta $data(meta) - string compare $data(type) [string trim $meta(Content-Type)] -} 0 - -test httpold-4.3 {httpEvent} { - set token [http_get $url] - http_code $token -} {HTTP/1.0 200 Data follows} - -test httpold-4.4 {httpEvent} { - set testfile [makeFile "" testfile] - set out [open $testfile w] - set token [http_get $url -channel $out] - close $out - set in [open $testfile] - set x [read $in] - close $in - removeFile $testfile - set x -} "HTTP/1.0 TEST -

Hello, World!

-

GET $tail

-" - -test httpold-4.5 {httpEvent} { - set testfile [makeFile "" testfile] - set out [open $testfile w] - set token [http_get $url -channel $out] - close $out - upvar #0 $token data - removeFile $testfile - expr $data(currentsize) == $data(totalsize) -} 1 - -test httpold-4.6 {httpEvent} { - set testfile [makeFile "" testfile] - set out [open $testfile w] - set token [http_get $binurl -channel $out] - close $out - set in [open $testfile] - fconfigure $in -translation binary - set x [read $in] - close $in - removeFile $testfile - set x -} "$bindata$binurl" - -proc myProgress {token total current} { - global progress httpLog - if {[info exists httpLog] && $httpLog} { - puts "progress $total $current" - } - set progress [list $total $current] -} -if 0 { - # This test hangs on Windows95 because the client never gets EOF - set httpLog 1 - test httpold-4.6 {httpEvent} { - set token [http_get $url -blocksize 50 -progress myProgress] - set progress - } {111 111} -} -test httpold-4.7 {httpEvent} { - set token [http_get $url -progress myProgress] - set progress -} {111 111} -test httpold-4.8 {httpEvent} { - set token [http_get $url] - http_status $token -} {ok} -test httpold-4.9 {httpEvent} { - set token [http_get $url -progress myProgress] - http_code $token -} {HTTP/1.0 200 Data follows} -test httpold-4.10 {httpEvent} { - set token [http_get $url -progress myProgress] - http_size $token -} {111} -test httpold-4.11 {httpEvent} { - set token [http_get $url -timeout 1 -command {#}] - http_reset $token - http_status $token -} {reset} -test httpold-4.12 {httpEvent} { - update - set x {} - after 500 {lappend x ok} - set token [http_get $url -timeout 1 -command {lappend x fail}] - vwait x - list [http_status $token] $x -} {timeout ok} - -test httpold-5.1 {http_formatQuery} { - http_formatQuery name1 value1 name2 "value two" -} {name1=value1&name2=value+two} - -test httpold-5.2 {http_formatQuery} { - http_formatQuery name1 ~bwelch name2 \xa1\xa2\xa2 -} {name1=%7ebwelch&name2=%a1%a2%a2} - -test httpold-5.3 {http_formatQuery} { - http_formatQuery lines "line1\nline2\nline3" -} {lines=line1%0d%0aline2%0d%0aline3} - -test httpold-6.1 {httpProxyRequired} { - update - http_config -proxyhost ${::HOST} -proxyport $port - set token [http_get $url] - http_wait $token - http_config -proxyhost {} -proxyport {} - upvar #0 $token data - set data(body) -} "HTTP/1.0 TEST -

Hello, World!

-

GET http://$url

-" - -# cleanup -catch {unset url} -catch {unset port} -catch {unset data} -close $listen -::tcltest::cleanupTests -return -- cgit v0.12 From daa36e9a1bc07b908f1f3fdb5e9fe52b699047e5 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 29 Dec 2017 17:47:50 +0000 Subject: Use http 2 instead of http 1 for Safe Base testing. --- tests/safe.test | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/safe.test b/tests/safe.test index 33ee166..df60de6 100644 --- a/tests/safe.test +++ b/tests/safe.test @@ -180,17 +180,17 @@ test safe-6.3 {test safe interpreters knowledge of the world} { # leaking infos, but they still do... # high level general test -test safe-7.1 {tests that everything works at high level} { +test safe-7.1 {tests that everything works at high level} -body { set i [safe::interpCreate] # no error shall occur: # (because the default access_path shall include 1st level sub dirs so # package require in a slave works like in the master) - set v [interp eval $i {package require http 1}] + set v [interp eval $i {package require http 2}] # no error shall occur: - interp eval $i {http_config} + interp eval $i {http::config} safe::interpDelete $i set v -} 1.0 +} -match glob -result 2.* test safe-7.2 {tests specific path and interpFind/AddToAccessPath} -body { set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]] # should not add anything (p0) -- cgit v0.12 From 03a71b070685eecb97de3d3cfe830823b056054e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 22 Jan 2018 09:18:19 +0000 Subject: Put old "int" type back. Not used by Tcl anymore, but this restores compatibility with Tk < 8.6.9 and some extensions: "nsf", "tdbcload", "tclxml" and "VecTcl" (this workaround was used by "boolean" as well, when its internal implementation changed, there's still an oldBooleanType because of that) --- generic/tclInt.h | 1 + generic/tclObj.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/generic/tclInt.h b/generic/tclInt.h index 50d0469..d74cd0e 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2713,6 +2713,7 @@ MODULE_SCOPE const Tcl_ObjType tclByteCodeType; MODULE_SCOPE const Tcl_ObjType tclDoubleType; MODULE_SCOPE const Tcl_ObjType tclEndOffsetType; MODULE_SCOPE const Tcl_ObjType tclIntType; +MODULE_SCOPE const Tcl_ObjType tclOldIntType; MODULE_SCOPE const Tcl_ObjType tclListType; MODULE_SCOPE const Tcl_ObjType tclDictType; MODULE_SCOPE const Tcl_ObjType tclProcBodyType; diff --git a/generic/tclObj.c b/generic/tclObj.c index 8ec95ce..e02f6c4 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -210,6 +210,9 @@ static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfDouble(Tcl_Obj *objPtr); static void UpdateStringOfInt(Tcl_Obj *objPtr); +#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG) +static void UpdateStringOfOldInt(Tcl_Obj *objPtr); +#endif static void FreeBignum(Tcl_Obj *objPtr); static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void UpdateStringOfBignum(Tcl_Obj *objPtr); @@ -272,6 +275,15 @@ const Tcl_ObjType tclIntType = { UpdateStringOfInt, /* updateStringProc */ SetIntFromAny /* setFromAnyProc */ }; +#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG) +const Tcl_ObjType tclOldIntType = { + "int", /* name */ + NULL, /* freeIntRepProc */ + NULL, /* dupIntRepProc */ + UpdateStringOfOldInt, /* updateStringProc */ + SetIntFromAny /* setFromAnyProc */ +}; +#endif const Tcl_ObjType tclBignumType = { "bignum", /* name */ FreeBignum, /* freeIntRepProc */ @@ -400,6 +412,9 @@ TclInitObjSubsystem(void) /* For backward compatibility only ... */ #if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 Tcl_RegisterObjType(&tclIntType); +#if !defined(TCL_WIDE_INT_IS_LONG) + Tcl_RegisterObjType(&tclOldIntType); +#endif Tcl_RegisterObjType(&oldBooleanType); #endif @@ -2548,6 +2563,22 @@ UpdateStringOfInt( memcpy(objPtr->bytes, buffer, (unsigned) len + 1); objPtr->length = len; } + +#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG) +static void +UpdateStringOfOldInt( + register Tcl_Obj *objPtr) /* Int object whose string rep to update. */ +{ + char buffer[TCL_INTEGER_SPACE]; + register int len; + + len = TclFormatInt(buffer, objPtr->internalRep.longValue); + + objPtr->bytes = ckalloc(len + 1); + memcpy(objPtr->bytes, buffer, (unsigned) len + 1); + objPtr->length = len; +} +#endif /* *---------------------------------------------------------------------- -- cgit v0.12 From fb10dc69eead85da6836ed1c28ee1269d1738337 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 22 Jan 2018 09:54:40 +0000 Subject: make the old "int" type "static", since it's just used in a single file. --- generic/tclInt.h | 1 - generic/tclObj.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index d74cd0e..50d0469 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2713,7 +2713,6 @@ MODULE_SCOPE const Tcl_ObjType tclByteCodeType; MODULE_SCOPE const Tcl_ObjType tclDoubleType; MODULE_SCOPE const Tcl_ObjType tclEndOffsetType; MODULE_SCOPE const Tcl_ObjType tclIntType; -MODULE_SCOPE const Tcl_ObjType tclOldIntType; MODULE_SCOPE const Tcl_ObjType tclListType; MODULE_SCOPE const Tcl_ObjType tclDictType; MODULE_SCOPE const Tcl_ObjType tclProcBodyType; diff --git a/generic/tclObj.c b/generic/tclObj.c index e02f6c4..ebe1450 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -276,7 +276,7 @@ const Tcl_ObjType tclIntType = { SetIntFromAny /* setFromAnyProc */ }; #if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG) -const Tcl_ObjType tclOldIntType = { +static const Tcl_ObjType oldIntType = { "int", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ @@ -413,7 +413,7 @@ TclInitObjSubsystem(void) #if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 Tcl_RegisterObjType(&tclIntType); #if !defined(TCL_WIDE_INT_IS_LONG) - Tcl_RegisterObjType(&tclOldIntType); + Tcl_RegisterObjType(&oldIntType); #endif Tcl_RegisterObjType(&oldBooleanType); #endif -- cgit v0.12 From 2eba1ce11e24976640d99ae78cec26cc67508f15 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 26 Jan 2018 13:29:01 +0000 Subject: Rename (internal) TclNewWideObj macro to TclNewIntObj. Change Tcl_SetIntObj/Tcl_SetLongObj to macro's referencing Tcl_SetWideIntObj (since all of those do the same now) --- generic/tclBasic.c | 2 +- generic/tclCmdMZ.c | 2 +- generic/tclDecls.h | 6 ++++-- generic/tclExecute.c | 46 +++++++++++++++++++++++----------------------- generic/tclInt.h | 6 +++--- generic/tclObj.c | 11 ++++++----- generic/tclScan.c | 4 ++-- generic/tclStubInit.c | 1 + generic/tclZlib.c | 2 +- 9 files changed, 42 insertions(+), 38 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 51d9a64..e2879f1 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -3686,7 +3686,7 @@ OldMathFuncProc( */ if (funcResult.type == TCL_INT) { - TclNewWideObj(valuePtr, funcResult.intValue); + TclNewIntObj(valuePtr, funcResult.intValue); } else if (funcResult.type == TCL_WIDE_INT) { valuePtr = Tcl_NewWideIntObj(funcResult.wideValue); } else { diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 8ae3f51..fd9858b 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -4303,7 +4303,7 @@ TclNRTryObjCmd( } info[0] = objv[i]; /* type */ - TclNewWideObj(info[1], code); /* returnCode */ + TclNewIntObj(info[1], code); /* returnCode */ if (info[2] == NULL) { /* errorCodePrefix */ TclNewObj(info[2]); } diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 464609c..49f34e8 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -3935,7 +3935,6 @@ extern const TclStubs *tclStubsPtr; * without introducing a binary incompatibility. */ # undef Tcl_GetLongFromObj -# undef Tcl_SetLongObj # undef Tcl_ExprLong # undef Tcl_ExprLongObj # undef Tcl_UniCharNcmp @@ -3943,7 +3942,6 @@ extern const TclStubs *tclStubsPtr; # undef Tcl_UtfNcasecmp # undef Tcl_UniCharNcasecmp # define Tcl_GetLongFromObj ((int(*)(Tcl_Interp*,Tcl_Obj*,long*))Tcl_GetWideIntFromObj) -# define Tcl_SetLongObj ((void(*)(Tcl_Obj*,long))Tcl_SetWideIntObj) # define Tcl_ExprLong TclExprLong static inline int TclExprLong(Tcl_Interp *interp, const char *string, long *ptr){ int intValue; @@ -3975,6 +3973,10 @@ extern const TclStubs *tclStubsPtr; #define Tcl_NewIntObj(value) Tcl_NewWideIntObj((int)(value)) #undef Tcl_DbNewLongObj #define Tcl_DbNewLongObj(value, file, line) Tcl_DbNewWideIntObj((long)(value), file, line) +#undef Tcl_SetIntObj +#define Tcl_SetIntObj(objPtr, value) Tcl_SetWideIntObj(objPtr, (int)(value)) +#undef Tcl_SetLongObj +#define Tcl_SetLongObj(objPtr, value) Tcl_SetWideIntObj(objPtr, (long)(value)) /* * Deprecated Tcl procedures: diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 81f7fe7..eb730ce 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -325,7 +325,7 @@ VarHashCreateVar( NEXT_INST_F(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ default: \ if ((condition) < 0) { \ - TclNewWideObj(objResultPtr, -1); \ + TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -346,7 +346,7 @@ VarHashCreateVar( NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ default: \ if ((condition) < 0) { \ - TclNewWideObj(objResultPtr, -1); \ + TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -357,7 +357,7 @@ VarHashCreateVar( #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ - TclNewWideObj(objResultPtr, -1); \ + TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -366,7 +366,7 @@ VarHashCreateVar( #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ - TclNewWideObj(objResultPtr, -1); \ + TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ @@ -851,9 +851,9 @@ TclCreateExecEnv( + (size_t) (size-1) * sizeof(Tcl_Obj *)); eePtr->execStackPtr = esPtr; - TclNewWideObj(eePtr->constants[0], 0); + TclNewIntObj(eePtr->constants[0], 0); Tcl_IncrRefCount(eePtr->constants[0]); - TclNewWideObj(eePtr->constants[1], 1); + TclNewIntObj(eePtr->constants[1], 1); Tcl_IncrRefCount(eePtr->constants[1]); eePtr->interp = interp; eePtr->callbackPtr = NULL; @@ -1849,7 +1849,7 @@ TclIncrObj( */ if (!Overflowing(w1, w2, sum)) { - Tcl_SetWideIntObj(valuePtr, sum); + TclSetIntObj(valuePtr, sum); return TCL_OK; } } @@ -3649,7 +3649,7 @@ TEBCresume( TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ - TclNewWideObj(objResultPtr, sum); + TclNewIntObj(objResultPtr, sum); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { @@ -3687,7 +3687,7 @@ TEBCresume( } else { objResultPtr = objPtr; } - TclNewWideObj(incrPtr, increment); + TclNewIntObj(incrPtr, increment); if (TclIncrObj(interp, objResultPtr, incrPtr) != TCL_OK) { Tcl_DecrRefCount(incrPtr); TRACE_ERROR(interp); @@ -3701,7 +3701,7 @@ TEBCresume( * All other cases, flow through to generic handling. */ - TclNewWideObj(incrPtr, increment); + TclNewIntObj(incrPtr, increment); Tcl_IncrRefCount(incrPtr); doIncrScalar: @@ -4399,7 +4399,7 @@ TEBCresume( NEXT_INST_F(1, 0, 1); } case INST_INFO_LEVEL_NUM: - TclNewWideObj(objResultPtr, iPtr->varFramePtr->level); + TclNewIntObj(objResultPtr, iPtr->varFramePtr->level); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_INFO_LEVEL_ARGS: { @@ -4768,7 +4768,7 @@ TEBCresume( TRACE_ERROR(interp); goto gotError; } - TclNewWideObj(objResultPtr, length); + TclNewIntObj(objResultPtr, length); TRACE_APPEND(("%d\n", length)); NEXT_INST_F(1, 1, 1); @@ -5239,7 +5239,7 @@ TEBCresume( case INST_STR_LEN: valuePtr = OBJ_AT_TOS; length = Tcl_GetCharLength(valuePtr); - TclNewWideObj(objResultPtr, length); + TclNewIntObj(objResultPtr, length); TRACE(("\"%.20s\" => %d\n", O2S(valuePtr), length)); NEXT_INST_F(1, 1, 1); @@ -5594,7 +5594,7 @@ TEBCresume( TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); - TclNewWideObj(objResultPtr, match); + TclNewIntObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_FIND_LAST: @@ -5602,7 +5602,7 @@ TEBCresume( TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); - TclNewWideObj(objResultPtr, match); + TclNewIntObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_CLASS: @@ -5798,7 +5798,7 @@ TEBCresume( type1 = TCL_NUMBER_WIDE; } } - TclNewWideObj(objResultPtr, type1); + TclNewIntObj(objResultPtr, type1); TRACE(("\"%.20s\" => %d\n", O2S(OBJ_AT_TOS), type1)); NEXT_INST_F(1, 1, 1); @@ -5991,7 +5991,7 @@ TEBCresume( if (w1 > 0L) { objResultPtr = TCONST(0); } else { - TclNewWideObj(objResultPtr, -1); + TclNewIntObj(objResultPtr, -1); } TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); @@ -6190,7 +6190,7 @@ TEBCresume( TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } - Tcl_SetWideIntObj(valuePtr, wResult); + TclSetIntObj(valuePtr, wResult); TRACE(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); @@ -6298,7 +6298,7 @@ TEBCresume( if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); if (Tcl_IsShared(valuePtr)) { - TclNewWideObj(objResultPtr, ~w1); + TclNewIntObj(objResultPtr, ~w1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } @@ -6336,7 +6336,7 @@ TEBCresume( w1 = *((const Tcl_WideInt *) ptr1); if (w1 != LLONG_MIN) { if (Tcl_IsShared(valuePtr)) { - TclNewWideObj(objResultPtr, -w1); + TclNewIntObj(objResultPtr, -w1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } @@ -6501,7 +6501,7 @@ TEBCresume( oldValuePtr = iterVarPtr->value.objPtr; if (oldValuePtr == NULL) { - TclNewWideObj(iterVarPtr->value.objPtr, -1); + TclNewIntObj(iterVarPtr->value.objPtr, -1); Tcl_IncrRefCount(iterVarPtr->value.objPtr); } else { TclSetIntObj(oldValuePtr, -1); @@ -6872,7 +6872,7 @@ TEBCresume( NEXT_INST_F(1, 0, -1); case INST_PUSH_RETURN_CODE: - TclNewWideObj(objResultPtr, result); + TclNewIntObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); @@ -7973,7 +7973,7 @@ ExecuteExtendedBinaryMathOp( if (Tcl_IsShared(valuePtr)) { \ return Tcl_NewWideIntObj(w); \ } else { \ - Tcl_SetWideIntObj(valuePtr, w); \ + TclSetIntObj(valuePtr, w); \ return NULL; \ } #define BIG_RESULT(b) \ diff --git a/generic/tclInt.h b/generic/tclInt.h index b061ed0..d5f4c9b 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4583,7 +4583,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; * types, avoiding the corresponding function calls in time critical parts of * the core. The ANSI C "prototypes" for these macros are: * - * MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w); + * MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d); * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, int len); * MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, const char *sLiteral); @@ -4592,7 +4592,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; */ #ifndef TCL_MEM_DEBUG -#define TclNewWideObj(objPtr, i) \ +#define TclNewIntObj(objPtr, i) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ @@ -4625,7 +4625,7 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; } while (0) #else /* TCL_MEM_DEBUG */ -#define TclNewWideObj(objPtr, w) \ +#define TclNewIntObj(objPtr, w) \ (objPtr) = Tcl_NewWideIntObj(w) #define TclNewDoubleObj(objPtr, d) \ diff --git a/generic/tclObj.c b/generic/tclObj.c index b4dfc63..5f60d9d 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -1769,7 +1769,7 @@ Tcl_NewBooleanObj( { register Tcl_Obj *objPtr; - TclNewWideObj(objPtr, boolValue!=0); + TclNewIntObj(objPtr, boolValue!=0); return objPtr; } #endif /* TCL_MEM_DEBUG */ @@ -2416,7 +2416,7 @@ Tcl_NewIntObj( { register Tcl_Obj *objPtr; - TclNewWideObj(objPtr, intValue); + TclNewIntObj(objPtr, intValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ @@ -2630,7 +2630,7 @@ Tcl_NewLongObj( { register Tcl_Obj *objPtr; - TclNewWideObj(objPtr, longValue); + TclNewIntObj(objPtr, longValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ @@ -2722,6 +2722,7 @@ Tcl_DbNewLongObj( *---------------------------------------------------------------------- */ +#undef Tcl_SetLongObj void Tcl_SetLongObj( register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ @@ -2891,7 +2892,7 @@ Tcl_NewWideIntObj( register Tcl_Obj *objPtr; TclNewObj(objPtr); - Tcl_SetWideIntObj(objPtr, wideValue); + TclSetIntObj(objPtr, wideValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ @@ -2943,7 +2944,7 @@ Tcl_DbNewWideIntObj( register Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); - Tcl_SetWideIntObj(objPtr, wideValue); + TclSetIntObj(objPtr, wideValue); return objPtr; } diff --git a/generic/tclScan.c b/generic/tclScan.c index e0798df..1bdc3ef 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -942,7 +942,7 @@ Tcl_ScanObjCmd( (Tcl_WideUInt)wideValue); Tcl_SetStringObj(objPtr, buf, -1); } else { - Tcl_SetWideIntObj(objPtr, wideValue); + TclSetIntObj(objPtr, wideValue); } } else if (!(flags & SCAN_BIG)) { if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) { @@ -956,7 +956,7 @@ Tcl_ScanObjCmd( sprintf(buf, "%lu", value); /* INTL: ISO digit */ Tcl_SetStringObj(objPtr, buf, -1); } else { - Tcl_SetLongObj(objPtr, value); + TclSetIntObj(objPtr, value); } } objs[objIndex++] = objPtr; diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index d255e97..86406c1 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -43,6 +43,7 @@ #undef TclpGetPid #undef TclSockMinimumBuffers #undef Tcl_SetIntObj +#undef Tcl_SetLongObj #undef TclpInetNtoa #undef TclWinGetServByName #undef TclWinGetSockOpt diff --git a/generic/tclZlib.c b/generic/tclZlib.c index dc124f7..994bcef 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -373,7 +373,7 @@ ConvertErrorToList( default: TclNewLiteralStringObj(objv[2], "UNKNOWN"); - TclNewWideObj(objv[3], code); + TclNewIntObj(objv[3], code); return Tcl_NewListObj(4, objv); } } -- cgit v0.12 From 1a988444125d7bee60784dbe4958d4a428c310b4 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Sun, 28 Jan 2018 18:21:09 +0000 Subject: Preparation to provide TclNRPackageObjectCmd: Eliminate the loop in PkgRequireCore so that TclNRAddCallback can be added at the needed spots. This checkin creates a crash in test package-3.12 . Pushing the work off the 8.7.* branch and onto a feature branch for now. --- generic/tclPkg.c | 553 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 277 insertions(+), 276 deletions(-) diff --git a/generic/tclPkg.c b/generic/tclPkg.c index 2b842b4..02f66f0 100644 --- a/generic/tclPkg.c +++ b/generic/tclPkg.c @@ -88,6 +88,8 @@ static Package * FindPackage(Tcl_Interp *interp, const char *name); static int PkgRequireCore(Tcl_Interp *interp, const char *name, int reqc, Tcl_Obj *const reqv[], void *clientDataPtr); +static int SelectPackage (Tcl_Interp *interp, const char *name, + Package *pkgPtr, int reqc, Tcl_Obj *const reqv[]); /* * Helper macros. @@ -417,343 +419,342 @@ PkgRequireCore( * available. */ void *clientDataPtr) { - Interp *iPtr = (Interp *) interp; Package *pkgPtr; - PkgAvail *availPtr, *bestPtr, *bestStablePtr; - char *availVersion, *bestVersion, *bestStableVersion; - /* Internal rep. of versions */ - int availStable, code, satisfies, pass; + int code, satisfies; char *script, *pkgVersionI; Tcl_DString command; + pkgPtr = FindPackage(interp, name); + if (pkgPtr->version == NULL) { + code = SelectPackage(interp, name, pkgPtr, reqc, reqv); + if (code != TCL_OK) { + return code; + } + if (pkgPtr->version == NULL) { + /* + * The package is not in the database. If there is a "package unknown" + * command, invoke it. + */ + + script = ((Interp *) interp)->packageUnknown; + if (script != NULL) { + Tcl_DStringInit(&command); + Tcl_DStringAppend(&command, script, -1); + Tcl_DStringAppendElement(&command, name); + AddRequirementsToDString(&command, reqc, reqv); + + code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), + Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); + Tcl_DStringFree(&command); + + if ((code != TCL_OK) && (code != TCL_ERROR)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad return code: %d", code)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); + code = TCL_ERROR; + } + if (code == TCL_ERROR) { + Tcl_AddErrorInfo(interp, + "\n (\"package unknown\" script)"); + return code; + } + Tcl_ResetResult(interp); + } + /* pkgPtr may now be invalid, so refresh it. */ + pkgPtr = FindPackage(interp, name); + code = SelectPackage(interp, name, pkgPtr, reqc, reqv); + if (code != TCL_OK) { + return code; + } + } + } + + if (pkgPtr->version == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't find package %s", name)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL); + AddRequirementsToResult(interp, reqc, reqv); + return TCL_ERROR; + } + /* - * It can take up to three passes to find the package: one pass to run the - * "package unknown" script, one to run the "package ifneeded" script for - * a specific version, and a final pass to lookup the package loaded by - * the "package ifneeded" script. + * Ensure that the provided version meets the current requirements. */ - for (pass=1 ;; pass++) { - pkgPtr = FindPackage(interp, name); - if (pkgPtr->version != NULL) { - break; - } + if (reqc != 0) { + CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL); + satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv); - /* - * Check whether we're already attempting to load some version of this - * package (circular dependency detection). - */ + ckfree(pkgVersionI); - if (pkgPtr->clientData != NULL) { + if (!satisfies) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "circular package dependency:" - " attempt to provide %s %s requires %s", - name, (char *) pkgPtr->clientData, name)); + "version conflict for package \"%s\": have %s, need", + name, pkgPtr->version)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", + NULL); AddRequirementsToResult(interp, reqc, reqv); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL); return TCL_ERROR; } + } - /* - * The package isn't yet present. Search the list of available - * versions and invoke the script for the best available version. We - * are actually locating the best, and the best stable version. One of - * them is then chosen based on the selection mode. - */ - - bestPtr = NULL; - bestStablePtr = NULL; - bestVersion = NULL; - bestStableVersion = NULL; + if (clientDataPtr) { + const void **ptr = (const void **) clientDataPtr; - for (availPtr = pkgPtr->availPtr; availPtr != NULL; - availPtr = availPtr->nextPtr) { - if (CheckVersionAndConvert(interp, availPtr->version, - &availVersion, &availStable) != TCL_OK) { - /* - * The provided version number has invalid syntax. This - * should not happen. This should have been caught by the - * 'package ifneeded' registering the package. - */ + *ptr = pkgPtr->clientData; + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(pkgPtr->version, -1)); + return TCL_OK; +} + +int SelectPackage (Tcl_Interp *interp, const char *name, Package *pkgPtr, int reqc, Tcl_Obj *const reqv[]) { + PkgAvail *availPtr, *bestPtr, *bestStablePtr; + char *availVersion, *bestVersion, *bestStableVersion; + /* Internal rep. of versions */ + char *script; + int availStable, code, satisfies; + Interp *iPtr = (Interp *) interp; - continue; - } + /* + * Check whether we're already attempting to load some version of this + * package (circular dependency detection). + */ - /* Check satisfaction of requirements before considering the current version further. */ - if (reqc > 0) { - satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv); - if (!satisfies) { - ckfree(availVersion); - availVersion = NULL; - continue; - } - } + if (pkgPtr->clientData != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "circular package dependency:" + " attempt to provide %s %s requires %s", + name, (char *) pkgPtr->clientData, name)); + AddRequirementsToResult(interp, reqc, reqv); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL); + return TCL_ERROR; + } - if (bestPtr != NULL) { - int res = CompareVersions(availVersion, bestVersion, NULL); + /* + * The package isn't yet present. Search the list of available + * versions and invoke the script for the best available version. We + * are actually locating the best, and the best stable version. One of + * them is then chosen based on the selection mode. + */ - /* - * Note: Used internal reps in the comparison! - */ + bestPtr = NULL; + bestStablePtr = NULL; + bestVersion = NULL; + bestStableVersion = NULL; - if (res > 0) { - /* - * The version of the package sought is better than the - * currently selected version. - */ - ckfree(bestVersion); - bestVersion = NULL; - goto newbest; - } - } else { - newbest: - /* We have found a version which is better than our max. */ + for (availPtr = pkgPtr->availPtr; availPtr != NULL; + availPtr = availPtr->nextPtr) { + if (CheckVersionAndConvert(interp, availPtr->version, + &availVersion, &availStable) != TCL_OK) { + /* + * The provided version number has invalid syntax. This + * should not happen. This should have been caught by the + * 'package ifneeded' registering the package. + */ - bestPtr = availPtr; - CheckVersionAndConvert(interp, bestPtr->version, &bestVersion, NULL); - } + continue; + } - if (!availStable) { + /* Check satisfaction of requirements before considering the current version further. */ + if (reqc > 0) { + satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv); + if (!satisfies) { ckfree(availVersion); availVersion = NULL; continue; } + } - if (bestStablePtr != NULL) { - int res = CompareVersions(availVersion, bestStableVersion, NULL); + if (bestPtr != NULL) { + int res = CompareVersions(availVersion, bestVersion, NULL); + + /* + * Note: Used internal reps in the comparison! + */ + if (res > 0) { /* - * Note: Used internal reps in the comparison! + * The version of the package sought is better than the + * currently selected version. */ - - if (res > 0) { - /* - * This stable version of the package sought is better - * than the currently selected stable version. - */ - ckfree(bestStableVersion); - bestStableVersion = NULL; - goto newstable; - } - } else { - newstable: - /* We have found a stable version which is better than our max stable. */ - bestStablePtr = availPtr; - CheckVersionAndConvert(interp, bestStablePtr->version, &bestStableVersion, NULL); + ckfree(bestVersion); + bestVersion = NULL; + goto newbest; } + } else { + newbest: + /* We have found a version which is better than our max. */ - ckfree(availVersion); - availVersion = NULL; - } /* end for */ - - /* - * Clean up memorized internal reps, if any. - */ - - if (bestVersion != NULL) { - ckfree(bestVersion); - bestVersion = NULL; + bestPtr = availPtr; + CheckVersionAndConvert(interp, bestPtr->version, &bestVersion, NULL); } - if (bestStableVersion != NULL) { - ckfree(bestStableVersion); - bestStableVersion = NULL; + if (!availStable) { + ckfree(availVersion); + availVersion = NULL; + continue; } - /* - * Now choose a version among the two best. For 'latest' we simply - * take (actually keep) the best. For 'stable' we take the best - * stable, if there is any, or the best if there is nothing stable. - */ - - if ((iPtr->packagePrefer == PKG_PREFER_STABLE) - && (bestStablePtr != NULL)) { - bestPtr = bestStablePtr; - } + if (bestStablePtr != NULL) { + int res = CompareVersions(availVersion, bestStableVersion, NULL); - if (bestPtr != NULL) { /* - * We found an ifneeded script for the package. Be careful while - * executing it: this could cause reentrancy, so (a) protect the - * script itself from deletion and (b) don't assume that bestPtr - * will still exist when the script completes. + * Note: Used internal reps in the comparison! */ - char *versionToProvide = bestPtr->version; - PkgFiles *pkgFiles; - PkgName *pkgName; - script = bestPtr->script; - - pkgPtr->clientData = versionToProvide; - Tcl_Preserve(versionToProvide); - Tcl_Preserve(script); - pkgFiles = TclInitPkgFiles(interp); - /* Push "ifneeded" package name in "tclPkgFiles" assocdata. */ - pkgName = ckalloc(sizeof(PkgName) + strlen(name)); - pkgName->nextPtr = pkgFiles->names; - strcpy(pkgName->name, name); - pkgFiles->names = pkgName; - if (bestPtr->pkgIndex) { - TclPkgFileSeen(interp, bestPtr->pkgIndex); - } - code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL); - /* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/ - pkgFiles->names = pkgName->nextPtr; - ckfree(pkgName); - Tcl_Release(script); - - pkgPtr = FindPackage(interp, name); - if (code == TCL_OK) { - Tcl_ResetResult(interp); - if (pkgPtr->version == NULL) { - code = TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "attempt to provide package %s %s failed:" - " no version of package %s provided", - name, versionToProvide, name)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED", - NULL); - } else { - char *pvi, *vi; - - if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi, - NULL) != TCL_OK) { - code = TCL_ERROR; - } else if (CheckVersionAndConvert(interp, - versionToProvide, &vi, NULL) != TCL_OK) { - ckfree(pvi); - code = TCL_ERROR; - } else { - int res = CompareVersions(pvi, vi, NULL); - - ckfree(pvi); - ckfree(vi); - if (res != 0) { - code = TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "attempt to provide package %s %s failed:" - " package %s %s provided instead", - name, versionToProvide, - name, pkgPtr->version)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", - "WRONGPROVIDE", NULL); - } - } - } - } else if (code != TCL_ERROR) { - Tcl_Obj *codePtr = Tcl_NewIntObj(code); - - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "attempt to provide package %s %s failed:" - " bad return code: %s", - name, versionToProvide, TclGetString(codePtr))); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); - TclDecrRefCount(codePtr); - code = TCL_ERROR; - } - - if (code == TCL_ERROR) { - Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( - "\n (\"package ifneeded %s %s\" script)", - name, versionToProvide)); - } - Tcl_Release(versionToProvide); - - if (code != TCL_OK) { + if (res > 0) { /* - * Take a non-TCL_OK code from the script as an indication the - * package wasn't loaded properly, so the package system - * should not remember an improper load. - * - * This is consistent with our returning NULL. If we're not - * willing to tell our caller we got a particular version, we - * shouldn't store that version for telling future callers - * either. + * This stable version of the package sought is better + * than the currently selected stable version. */ - - if (pkgPtr->version != NULL) { - ckfree(pkgPtr->version); - pkgPtr->version = NULL; - } - pkgPtr->clientData = NULL; - return code; + ckfree(bestStableVersion); + bestStableVersion = NULL; + goto newstable; } - - break; - } - - /* - * The package is not in the database. If there is a "package unknown" - * command, invoke it (but only on the first pass; after that, we - * should not get here in the first place). - */ - - if (pass > 1) { - break; + } else { + newstable: + /* We have found a stable version which is better than our max stable. */ + bestStablePtr = availPtr; + CheckVersionAndConvert(interp, bestStablePtr->version, &bestStableVersion, NULL); } - script = ((Interp *) interp)->packageUnknown; - if (script != NULL) { - Tcl_DStringInit(&command); - Tcl_DStringAppend(&command, script, -1); - Tcl_DStringAppendElement(&command, name); - AddRequirementsToDString(&command, reqc, reqv); + ckfree(availVersion); + availVersion = NULL; + } /* end for */ - code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), - Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); - Tcl_DStringFree(&command); + /* + * Clean up memorized internal reps, if any. + */ - if ((code != TCL_OK) && (code != TCL_ERROR)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad return code: %d", code)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); - code = TCL_ERROR; - } - if (code == TCL_ERROR) { - Tcl_AddErrorInfo(interp, - "\n (\"package unknown\" script)"); - return code; - } - Tcl_ResetResult(interp); - } + if (bestVersion != NULL) { + ckfree(bestVersion); + bestVersion = NULL; } - if (pkgPtr->version == NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't find package %s", name)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL); - AddRequirementsToResult(interp, reqc, reqv); - return TCL_ERROR; + if (bestStableVersion != NULL) { + ckfree(bestStableVersion); + bestStableVersion = NULL; } /* - * At this point we know that the package is present. Make sure that the - * provided version meets the current requirements. + * Now choose a version among the two best. For 'latest' we simply + * take (actually keep) the best. For 'stable' we take the best + * stable, if there is any, or the best if there is nothing stable. */ - if (reqc != 0) { - CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL); - satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv); + if ((iPtr->packagePrefer == PKG_PREFER_STABLE) + && (bestStablePtr != NULL)) { + bestPtr = bestStablePtr; + } - ckfree(pkgVersionI); + if (bestPtr != NULL) { + /* + * We found an ifneeded script for the package. Be careful while + * executing it: this could cause reentrancy, so (a) protect the + * script itself from deletion and (b) don't assume that bestPtr + * will still exist when the script completes. + */ + + char *versionToProvide = bestPtr->version; + PkgFiles *pkgFiles; + PkgName *pkgName; + script = bestPtr->script; + + pkgPtr->clientData = versionToProvide; + Tcl_Preserve(versionToProvide); + Tcl_Preserve(script); + pkgFiles = TclInitPkgFiles(interp); + /* Push "ifneeded" package name in "tclPkgFiles" assocdata. */ + pkgName = ckalloc(sizeof(PkgName) + strlen(name)); + pkgName->nextPtr = pkgFiles->names; + strcpy(pkgName->name, name); + pkgFiles->names = pkgName; + if (bestPtr->pkgIndex) { + TclPkgFileSeen(interp, bestPtr->pkgIndex); + } + code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL); + /* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/ + pkgFiles->names = pkgName->nextPtr; + ckfree(pkgName); + Tcl_Release(script); + + pkgPtr = FindPackage(interp, name); + if (code == TCL_OK) { + Tcl_ResetResult(interp); + if (pkgPtr->version == NULL) { + code = TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "attempt to provide package %s %s failed:" + " no version of package %s provided", + name, versionToProvide, name)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED", + NULL); + } else { + char *pvi, *vi; + + if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi, + NULL) != TCL_OK) { + code = TCL_ERROR; + } else if (CheckVersionAndConvert(interp, + versionToProvide, &vi, NULL) != TCL_OK) { + ckfree(pvi); + code = TCL_ERROR; + } else { + int res = CompareVersions(pvi, vi, NULL); + + ckfree(pvi); + ckfree(vi); + if (res != 0) { + code = TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "attempt to provide package %s %s failed:" + " package %s %s provided instead", + name, versionToProvide, + name, pkgPtr->version)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", + "WRONGPROVIDE", NULL); + } + } + } + } else if (code != TCL_ERROR) { + Tcl_Obj *codePtr = Tcl_NewIntObj(code); - if (!satisfies) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "version conflict for package \"%s\": have %s, need", - name, pkgPtr->version)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", - NULL); - AddRequirementsToResult(interp, reqc, reqv); - return TCL_ERROR; + "attempt to provide package %s %s failed:" + " bad return code: %s", + name, versionToProvide, TclGetString(codePtr))); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); + TclDecrRefCount(codePtr); + code = TCL_ERROR; } - } - if (clientDataPtr) { - const void **ptr = (const void **) clientDataPtr; + if (code == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"package ifneeded %s %s\" script)", + name, versionToProvide)); + } + Tcl_Release(versionToProvide); - *ptr = pkgPtr->clientData; + if (code != TCL_OK) { + /* + * Take a non-TCL_OK code from the script as an indication the + * package wasn't loaded properly, so the package system + * should not remember an improper load. + * + * This is consistent with our returning NULL. If we're not + * willing to tell our caller we got a particular version, we + * shouldn't store that version for telling future callers + * either. + */ + + if (pkgPtr->version != NULL) { + ckfree(pkgPtr->version); + pkgPtr->version = NULL; + } + pkgPtr->clientData = NULL; + return code; + } } - Tcl_SetObjResult(interp, Tcl_NewStringObj(pkgPtr->version, -1)); return TCL_OK; } -- cgit v0.12 From 77821adfe89e6c3507ef12250dec40cf04ff8a0e Mon Sep 17 00:00:00 2001 From: pooryorick Date: Wed, 31 Jan 2018 00:07:22 +0000 Subject: Fix segmentation fault triggered by test package-3.12. Adapt signature of PkgRequireCore to conform to Tcl_ObjCmdProc, and call it in Tcl_PkgRequireProc on an NRE trampoline via Tcl_NRCallObjProc. Additional callbacks still needed to fully NRE-enable [package require]. --- generic/tclInt.h | 1 + generic/tclPkg.c | 83 ++++++++++++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index a3bd8ba..20d340e 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2782,6 +2782,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRForObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRForeachCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRIfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRLmapCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclNRPackageObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRSourceObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRSubstObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRSwitchObjCmd; diff --git a/generic/tclPkg.c b/generic/tclPkg.c index 02f66f0..ce00fbf 100644 --- a/generic/tclPkg.c +++ b/generic/tclPkg.c @@ -65,6 +65,12 @@ typedef struct Package { const void *clientData; /* Client data. */ } Package; +typedef struct Require { + void * clientDataPtr; + const char *name; + Package *pkgPtr; +} Require; + /* * Prototypes for functions defined in this file: */ @@ -85,11 +91,10 @@ static void AddRequirementsToResult(Tcl_Interp *interp, int reqc, static void AddRequirementsToDString(Tcl_DString *dstring, int reqc, Tcl_Obj *const reqv[]); static Package * FindPackage(Tcl_Interp *interp, const char *name); -static int PkgRequireCore(Tcl_Interp *interp, const char *name, - int reqc, Tcl_Obj *const reqv[], - void *clientDataPtr); -static int SelectPackage (Tcl_Interp *interp, const char *name, - Package *pkgPtr, int reqc, Tcl_Obj *const reqv[]); +static int PkgRequireCore(ClientData clientData, Tcl_Interp *interp, + int reqc, Tcl_Obj *const reqv[]); +static int SelectPackage (Tcl_Interp *interp, Require *reqPtr, + int reqc, Tcl_Obj *const reqv[]); /* * Helper macros. @@ -402,35 +407,41 @@ Tcl_PkgRequireProc( void *clientDataPtr) { int code = CheckAllRequirements(interp, reqc, reqv); + Require require; if (code != TCL_OK) { return code; } - return PkgRequireCore(interp, name, reqc, reqv, clientDataPtr); + require.clientDataPtr = clientDataPtr; + require.name = name; + require.pkgPtr = NULL; + return Tcl_NRCallObjProc(interp, PkgRequireCore, &require, reqc, reqv); } int PkgRequireCore( + ClientData clientData, Tcl_Interp *interp, /* Interpreter in which package is now * available. */ - const char *name, /* Name of desired package. */ int reqc, /* Requirements constraining the desired * version. */ - Tcl_Obj *const reqv[], /* 0 means to use the latest version + Tcl_Obj *const reqv[] /* 0 means to use the latest version * available. */ - void *clientDataPtr) + ) { - Package *pkgPtr; int code, satisfies; - char *script, *pkgVersionI; Tcl_DString command; + Require *reqPtr = clientData; + char *script, *pkgVersionI; + const char *name = reqPtr->name /* Name of desired package. */; + void *clientDataPtr = reqPtr->clientDataPtr; - pkgPtr = FindPackage(interp, name); - if (pkgPtr->version == NULL) { - code = SelectPackage(interp, name, pkgPtr, reqc, reqv); + reqPtr->pkgPtr = FindPackage(interp, name); + if (reqPtr->pkgPtr->version == NULL) { + code = SelectPackage(interp, reqPtr, reqc, reqv); if (code != TCL_OK) { return code; } - if (pkgPtr->version == NULL) { + if (reqPtr->pkgPtr->version == NULL) { /* * The package is not in the database. If there is a "package unknown" * command, invoke it. @@ -459,17 +470,17 @@ PkgRequireCore( return code; } Tcl_ResetResult(interp); - } - /* pkgPtr may now be invalid, so refresh it. */ - pkgPtr = FindPackage(interp, name); - code = SelectPackage(interp, name, pkgPtr, reqc, reqv); - if (code != TCL_OK) { - return code; + /* pkgPtr may now be invalid, so refresh it. */ + reqPtr->pkgPtr = FindPackage(interp, name); + code = SelectPackage(interp, reqPtr, reqc, reqv); + if (code != TCL_OK) { + return code; + } } } } - if (pkgPtr->version == NULL) { + if (reqPtr->pkgPtr->version == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't find package %s", name)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL); @@ -482,7 +493,7 @@ PkgRequireCore( */ if (reqc != 0) { - CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL); + CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pkgVersionI, NULL); satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv); ckfree(pkgVersionI); @@ -490,7 +501,7 @@ PkgRequireCore( if (!satisfies) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "version conflict for package \"%s\": have %s, need", - name, pkgPtr->version)); + name, reqPtr->pkgPtr->version)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", NULL); AddRequirementsToResult(interp, reqc, reqv); @@ -501,18 +512,20 @@ PkgRequireCore( if (clientDataPtr) { const void **ptr = (const void **) clientDataPtr; - *ptr = pkgPtr->clientData; + *ptr = reqPtr->pkgPtr->clientData; } - Tcl_SetObjResult(interp, Tcl_NewStringObj(pkgPtr->version, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(reqPtr->pkgPtr->version, -1)); return TCL_OK; } -int SelectPackage (Tcl_Interp *interp, const char *name, Package *pkgPtr, int reqc, Tcl_Obj *const reqv[]) { +int SelectPackage (Tcl_Interp *interp, Require *reqPtr, int reqc, Tcl_Obj *const reqv[]) { PkgAvail *availPtr, *bestPtr, *bestStablePtr; char *availVersion, *bestVersion, *bestStableVersion; /* Internal rep. of versions */ char *script; int availStable, code, satisfies; + const char *name = reqPtr->name; + Package *pkgPtr = reqPtr->pkgPtr; Interp *iPtr = (Interp *) interp; /* @@ -678,10 +691,10 @@ int SelectPackage (Tcl_Interp *interp, const char *name, Package *pkgPtr, int re ckfree(pkgName); Tcl_Release(script); - pkgPtr = FindPackage(interp, name); + reqPtr->pkgPtr = FindPackage(interp, name); if (code == TCL_OK) { Tcl_ResetResult(interp); - if (pkgPtr->version == NULL) { + if (reqPtr->pkgPtr->version == NULL) { code = TCL_ERROR; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to provide package %s %s failed:" @@ -692,7 +705,7 @@ int SelectPackage (Tcl_Interp *interp, const char *name, Package *pkgPtr, int re } else { char *pvi, *vi; - if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi, + if (CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pvi, NULL) != TCL_OK) { code = TCL_ERROR; } else if (CheckVersionAndConvert(interp, @@ -710,7 +723,7 @@ int SelectPackage (Tcl_Interp *interp, const char *name, Package *pkgPtr, int re "attempt to provide package %s %s failed:" " package %s %s provided instead", name, versionToProvide, - name, pkgPtr->version)); + name, reqPtr->pkgPtr->version)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "WRONGPROVIDE", NULL); } @@ -747,11 +760,11 @@ int SelectPackage (Tcl_Interp *interp, const char *name, Package *pkgPtr, int re * either. */ - if (pkgPtr->version != NULL) { - ckfree(pkgPtr->version); - pkgPtr->version = NULL; + if (reqPtr->pkgPtr->version != NULL) { + ckfree(reqPtr->pkgPtr->version); + reqPtr->pkgPtr->version = NULL; } - pkgPtr->clientData = NULL; + reqPtr->pkgPtr->clientData = NULL; return code; } } -- cgit v0.12 From 98887219c2dcf8b1fd6debaf3c716f6a809d2a84 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Sat, 3 Feb 2018 18:15:06 +0000 Subject: Refine documentation for Tcl_NR* functions. --- doc/Eval.3 | 8 +- doc/NRE.3 | 260 ++++++++++++++++++++----------------------------------------- 2 files changed, 88 insertions(+), 180 deletions(-) diff --git a/doc/Eval.3 b/doc/Eval.3 index 191bace..e241794 100644 --- a/doc/Eval.3 +++ b/doc/Eval.3 @@ -176,10 +176,10 @@ it is faster to execute the script directly. .TP 23 \fBTCL_EVAL_GLOBAL\fR . -If this flag is set, the script is processed at global level. This -means that it is evaluated in the global namespace and its variable -context consists of global variables only (it ignores any Tcl -procedures that are active). +If this flag is set, the script is evaluated in the global namespace instead of +the current namespace and its variable context consists of global variables +only (it ignores any Tcl procedures that are active). +.\" TODO: document TCL_EVAL_INVOKE and TCL_EVAL_NOERR. .SH "MISCELLANEOUS DETAILS" .PP diff --git a/doc/NRE.3 b/doc/NRE.3 index ff0d108..6078a53 100644 --- a/doc/NRE.3 +++ b/doc/NRE.3 @@ -1,5 +1,6 @@ .\" .\" Copyright (c) 2008 by Kevin B. Kenny. +.\" Copyright (c) 2018 by Nathan Coulter. .\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -38,43 +39,39 @@ void .SH ARGUMENTS .AS Tcl_CmdDeleteProc *interp in .AP Tcl_Interp *interp in -Interpreter in which to create or evaluate a command. +The relevant Interpreter. .AP char *cmdName in -Name of a new command to create. +Name of the command to create. .AP Tcl_ObjCmdProc *proc in -Implementation of a command that will be called whenever \fIcmdName\fR -is invoked as a command in the unoptimized way. +Called in order to evaluate a command. Is often just a small wrapper that uses +\fBTcl_NRCallObjProc\fR to call \fInreProc\fR using a new trampoline. Behaves +in the same way as the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3) +(\fIq.v.\fR). .AP Tcl_ObjCmdProc *nreProc in -Implementation of a command that will be called whenever \fIcmdName\fR -is invoked and requested to conserve the C stack. +Called instead of \fIproc\fR when a trampoline is already in use. .AP ClientData clientData in -Arbitrary one-word value that will be passed to \fIproc\fR, \fInreProc\fR, -\fIdeleteProc\fR and \fIobjProc\fR. +Arbitrary one-word value passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR +and \fIobjProc\fR. .AP Tcl_CmdDeleteProc *deleteProc in/out -Procedure to call before \fIcmdName\fR is deleted from the interpreter. -This procedure allows for command-specific cleanup. If \fIdeleteProc\fR -is \fBNULL\fR, then no procedure is called before the command is deleted. +Called before \fIcmdName\fR is deleted from the interpreter, allowing for +command-specific cleanup. May be NULL. .AP int objc in -Count of parameters provided to the implementation of a command. +Number of items in \fIobjv\fR. .AP Tcl_Obj **objv in -Pointer to an array of Tcl values. Each value holds the value of a -single word in the command to execute. +Words in the command. .AP Tcl_Obj *objPtr in -Pointer to a Tcl_Obj whose value is a script or expression to execute. +A script or expression to evaluate. .AP int flags in -ORed combination of flag bits that specify additional options. -\fBTCL_EVAL_GLOBAL\fR is the only flag that is currently supported. -.\" TODO: This is a lie. But kbk didn't grasp TCL_EVAL_INVOKE and -.\" TCL_EVAL_NOERR well enough to document them. +As described for \fITcl_EvalObjv\fR. +.PP .AP Tcl_Command cmd in -Token for a command that is to be used instead of the currently -executing command. +Token to use instead of one derived from the first word of \fIobjv\fR in order +to evaluate a command. .AP Tcl_Obj *resultPtr out -Pointer to an unshared Tcl_Obj where the result of expression -evaluation is written. +Pointer to an unshared Tcl_Obj where the result of the evaluation is stored if +the return code is TCL_OK. .AP Tcl_NRPostProc *postProcPtr in -Pointer to a function that will be invoked when the command currently -executing in the interpreter designated by \fIinterp\fR completes. +A function to push. .AP ClientData data0 in .AP ClientData data1 in .AP ClientData data2 in @@ -84,98 +81,51 @@ to the function designated by \fIpostProcPtr\fR when it is invoked. .BE .SH DESCRIPTION .PP -This series of C functions provides an interface whereby commands that -are implemented in C can be evaluated, and invoke Tcl commands scripts -and scripts, without consuming space on the C stack. The non-recursive -evaluation is done by installing a \fItrampoline\fR, a small piece of -code that invokes a command or script, and then executes a series of -callbacks when the command or script returns. -.PP -The \fBTcl_NRCreateCommand\fR function creates a Tcl command in the -interpreter designated by \fIinterp\fR that is prepared to handle -nonrecursive evaluation with a trampoline. The \fIcmdName\fR argument -gives the name of the new command. If \fIcmdName\fR contains any -namespace qualifiers, then the new command is added to the specified -namespace; otherwise, it is added to the global namespace. \fIproc\fR -gives the procedure that will be called when the interpreter wishes to -evaluate the command in an unoptimized manner, and \fInreProc\fR is -the procedure that will be called when the interpreter wishes to -evaluate the command using a trampoline. \fIdeleteProc\fR is a -function that will be called before the command is deleted from the -interpreter. When any of the three functions is invoked, it is passed -the \fIclientData\fR parameter. -.PP -\fBTcl_NRCreateCommand\fR deletes any existing command -\fIname\fR already associated with the interpreter -(however see below for an exception where the existing command -is not deleted). -It returns a token that may be used to refer -to the command in subsequent calls to \fBTcl_GetCommandName\fR. -If \fBTcl_NRCreateCommand\fR is called for an interpreter that is in -the process of being deleted, then it does not create a new command, -does not delete any existing command of the same name, and returns NULL. -.PP -The \fIproc\fR and \fInreProc\fR function are expected to conform to -all the rules set forth for the \fIproc\fR argument to -\fBTcl_CreateObjCommand\fR(3) (\fIq.v.\fR). -.PP -When a command that is written to cope with evaluation via trampoline -is invoked without a trampoline on the stack, it will usually respond -to the invocation by creating a trampoline and calling the -trampoline-enabled implementation of the same command. This call is done by -means of \fBTcl_NRCallObjProc\fR. In the call to -\fBTcl_NRCallObjProc\fR, the \fIinterp\fR, \fIclientData\fR, -\fIobjc\fR and \fIobjv\fR parameters should be the same ones that were -passed to \fIproc\fR. The \fInreProc\fR parameter should designate the -trampoline-enabled implementation of the command. -.PP -\fBTcl_NREvalObj\fR arranges for the script contained in \fIobjPtr\fR -to be evaluated in the interpreter designated by \fIinterp\fR after -the current command (which must be trampoline-enabled) returns. It is -the method by which a command may invoke a script without consuming -space on the C stack. Similarly, \fBTcl_NREvalObjv\fR arranges to -invoke a single Tcl command whose words have already been separated -and substituted. The \fIobjc\fR and \fIobjv\fR parameters give the -words of the command to be evaluated when execution reaches the -trampoline. -.PP -\fBTcl_NRCmdSwap\fR allows for trampoline evaluation of a command whose -resolution is already known. The \fIcmd\fR parameter gives a -\fBTcl_Command\fR token (returned from \fBTcl_CreateObjCommand\fR or -\fBTcl_GetCommandFromObj\fR) identifying the command to be invoked in -the trampoline; this command must match the word in \fIobjv[0]\fR. -The remaining arguments are as for \fBTcl_NREvalObjv\fR. -.PP -\fBTcl_NREvalObj\fR, \fBTcl_NREvalObjv\fR and \fBTcl_NRCmdSwap\fR -all accept a \fIflags\fR parameter, which is an OR-ed-together set of -bits to control evaluation. At the present time, the only supported flag -available to callers is \fBTCL_EVAL_GLOBAL\fR. -.\" TODO: Again, this is a lie. Do we want to explain TCL_EVAL_INVOKE -.\" and TCL_EVAL_NOERR? -If the \fBTCL_EVAL_GLOBAL\fR flag is set, the script or command is -evaluated in the global namespace. If it is not set, it is evaluated -in the current namespace. -.PP -\fBTcl_NRExprObj\fR arranges for the expression contained in \fIobjPtr\fR -to be evaluated in the interpreter designated by \fIinterp\fR after -the current command (which must be trampoline-enabled) returns. It is -the method by which a command may evaluate a Tcl expression without consuming -space on the C stack. The argument \fIresultPtr\fR is a pointer to an -unshared Tcl_Obj where the result of expression evaluation is to be written. -If expression evaluation returns any code other than TCL_OK, the -\fIresultPtr\fR value is left untouched. -.PP -All of the routines return \fBTCL_OK\fR if command or expression invocation -has been scheduled successfully. If for any reason the scheduling cannot -be completed (for example, if the interpreter is unable to find -the requested command), they return \fBTCL_ERROR\fR with an -appropriate message left in the interpreter's result. -.PP -\fBTcl_NRAddCallback\fR arranges to have a C function called when the -current trampoline-enabled command in the Tcl interpreter designated -by \fIinterp\fR returns. The \fIpostProcPtr\fR argument is a pointer -to the callback function, which must have arguments and return value -consistent with the \fBTcl_NRPostProc\fR data type: +These functions provide an interface to the function stack that an interpreter +iterates through to evaluate commands. The routine behind a command is +implemented by an initial function and any additional functions that the +routine pushes onto the stack as it progresses. The interpreter itself pushes +functions onto the stack to react to the end of a routine and to exercise other +forms of control such as switching between in-progress stacks and the +evaluation of other scripts at additional levels without adding frames to the C +stack. To execute a routine, the initial function for the routine is called +and then a small bit of code called a \fItrampoline\fR iteratively takes +functions off the stack and calls them, using the value of the last call as the +value of the routine. +.PP +\fBTcl_NRCallObjProc\fR calls \fInreProc\fR using a new trampoline. +.PP +\fBTcl_NRCreateCommand\fR, an alternative to \fBTcl_CreateObjCommand\fR, +resolves \fIcmdName\fR, which may contain namespace qualifiers, relative to the +current namespace, creates a command by that name, and returns a token for the +command which may be used in subsequent calls to \fBTcl_GetCommandName\fR. +Except for a few cases noted below any existing command by the same name is +first deleted. If \fIinterp\fR is in the process of being deleted +\fBTcl_NRCreateCommand\fR does not create any command, does not delete any +command, and returns NULL. +.PP +\fBTcl_NREvalObj\fR pushes a function that is like \fBTcl_EvalObjEx\fR but +consumes no space on the C stack. +.PP +\fBTcl_NREvalObjv\fR pushes a function that is like \fBTcl_EvalObjv\fR but +consumes no space on the C stack. +.PP +\fBTcl_NRCmdSwap\fR is like \fBTcl_NREvalObjv\fR, but uses \fIcmd\fR, a token +previously returned by \fBTcl_CreateObjCommand\fR or +\fBTcl_GetCommandFromObj\fR, instead of resolving the first word of \fIobjv\fR. +. The name of this command must be the same as \fIobjv[0]\fR. +.PP +\fBTcl_NRExprObj\fR pushes a function that evaluates \fIobjPtr\fR as an +expression in the same manner as \fBTcl_ExprObj\fR but without consuming space +on the C stack. +.PP +All of the functions return \fBTCL_OK\fR if the evaluation of the script, +command, or expression has been scheduled successfully. Otherwise (for example +if the command name cannot be resolved), they return \fBTCL_ERROR\fR and store +a message as the interpreter's result. +.PP +\fBTcl_NRAddCallback\fR pushes \fIpostProcPtr\fR. The signature for +\fBTcl_NRPostProc\fR is: .PP .CS typedef int @@ -185,25 +135,13 @@ typedef int int \fIresult\fR); .CE .PP -When the trampoline invokes the callback function, the \fIdata\fR -parameter will point to an array containing the four one-word -quantities that were passed to \fBTcl_NRAddCallback\fR in the -\fIdata0\fR through \fIdata3\fR parameters. The Tcl interpreter will -be designated by the \fIinterp\fR parameter, and the \fIresult\fR -parameter will contain the result (\fBTCL_OK\fR, \fBTCL_ERROR\fR, -\fBTCL_RETURN\fR, \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR) that was -returned by the command evaluation. The callback function is expected, -in turn, either to return a \fIresult\fR to control further evaluation. -.PP -Multiple \fBTcl_NRAddCallback\fR invocations may request multiple -callbacks, which may be to the same or different callback -functions. If multiple callbacks are requested, they are executed in -last-in, first-out order, that is, the most recently requested -callback is executed first. +\fIdata\fR is a pointer to an array containing \fIdata0\fR through \fIdata3\fR. +\fIresult\fR is the value returned by the previous function implementing part +the routine. .SH EXAMPLE .PP -The usual pattern for Tcl commands that invoke other Tcl commands -is something like: +The following command uses \fBTcl_EvalObjEx\fR, which consumes space on the C +stack, to evalute a script: .PP .CS int @@ -228,28 +166,17 @@ int \fITheCmdOldObjProc\fR, clientData, TheCmdDeleteProc); .CE .PP -To enable a command like this one for trampoline-based evaluation, -it must be split into three pieces: -.IP \(bu -A non-trampoline implementation, \fITheCmdNewObjProc\fR, -which will simply create a trampoline -and invoke the trampoline-based implementation. -.IP \(bu -A trampoline-enabled implementation, \fITheCmdNRObjProc\fR. This -function will perform the initialization, request that the trampoline -call the postprocessing routine after command evaluation, and finally, -request that the trampoline call the inner command. -.IP \(bu -A postprocessing routine, \fITheCmdPostProc\fR. This function will -perform the postprocessing formerly done after the return from the -inner command in \fITheCmdObjProc\fR. -.PP -The non-trampoline implementation is simple and stylized, containing -a single statement: +To avoid consuming space on the C stack, \fITheCmdOldObjProc\fR is renamed to +\fITheCmdNRObjProc\fR and the postprocessing step is split into a separate +function, \fITheCmdPostProc\fR, which is pushed onto the function stack. +\fITcl_EvalObjEx\fR is replaced with \fITcl_NREvalObj\fR, which uses a +trampoline instead of consuming space on the C stack. A new version of +\fITheCmdOldObjProc\fR is just a a wrapper that uses \fBTcl_NRCallObjProc\fR to +call \fITheCmdNRObjProc\fR: .PP .CS int -\fITheCmdNewObjProc\fR( +\fITheCmdOldObjProc\fR( ClientData clientData, Tcl_Interp *interp, int objc, @@ -260,9 +187,6 @@ int } .CE .PP -The trampoline-enabled implementation requests postprocessing, -and returns to the trampoline requesting command evaluation. -.PP .CS int \fITheCmdNRObjProc\fR @@ -284,9 +208,6 @@ int } .CE .PP -The postprocessing procedure does whatever the original command did -upon return from the inner evaluation. -.PP .CS int \fITheCmdNRPostProc\fR( @@ -303,26 +224,13 @@ int } .CE .PP -If \fItheCommand\fR is a command that results in multiple commands or -scripts being evaluated, its postprocessing routine may schedule -additional postprocessing and then request another command evaluation -by means of \fBTcl_NREvalObj\fR or one of the other evaluation -routines. Looping and sequencing constructs may be implemented in this way. -.PP -Finally, to install a trampoline-enabled command in the interpreter, -\fBTcl_NRCreateCommand\fR is used in place of -\fBTcl_CreateObjCommand\fR. It accepts two command procedures instead -of one. The first is for use when no trampoline is yet on the stack, -and the second is for use when there is already a trampoline in place. +Any function comprising a routine can push other functions, making it possible +implement looping and sequencing constructs using the function stack. .PP -.CS -\fBTcl_NRCreateCommand\fR(interp, "theCommand", - \fITheCmdNewObjProc\fR, \fITheCmdNRObjProc\fR, clientData, - TheCmdDeleteProc); -.CE .SH "SEE ALSO" Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3) .SH KEYWORDS stackless, nonrecursive, execute, command, global, value, result, script .SH COPYRIGHT -Copyright (c) 2008 by Kevin B. Kenny +Copyright (c) 2008 by Kevin B. Kenny. +Copyright (c) 2018 by Nathan Coulter. -- cgit v0.12 From da7f77f96f74cf57e80421226d7bf1e93d776f58 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 5 Feb 2018 13:33:21 +0000 Subject: Improved overflow prevention. --- generic/tclStringObj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index ae75e44..8437555 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -140,8 +140,8 @@ GrowStringBuffer( objPtr->bytes = NULL; } if (flag == 0 || stringPtr->allocated > 0) { - attempt = 2 * needed; - if (attempt >= 0) { + if (needed <= INT_MAX / 2) { + attempt = 2 * needed; ptr = attemptckrealloc(objPtr->bytes, attempt + 1); } if (ptr == NULL) { -- cgit v0.12 From 3be49723fced40ef581ccd12dbeb35b8cf346b12 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 5 Feb 2018 13:41:26 +0000 Subject: Improved overflow prevention. --- generic/tclStringObj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 8437555..c3a0192 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -190,8 +190,8 @@ GrowUnicodeBuffer( * Subsequent appends - apply the growth algorithm. */ - attempt = 2 * needed; - if (attempt >= 0 && attempt <= STRING_MAXCHARS) { + if (needed <= STRING_MAXCHARS / 2) { + attempt = 2 * needed; ptr = stringAttemptRealloc(stringPtr, attempt); } if (ptr == NULL) { -- cgit v0.12 From 836fa11775ae940ca572c7c330afbae5a7632d5b Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 5 Feb 2018 16:10:02 +0000 Subject: Revise TclStringRepeat() interface so that in place operations are done only by caller request. Establish a re-usable pattern. --- generic/tclCmdMZ.c | 9 +++++---- generic/tclInt.h | 15 +++++++++++++-- generic/tclStringObj.c | 31 +++++++++++++++---------------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 1fc2d17..e0344ef 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2294,11 +2294,12 @@ StringReptCmd( return TCL_OK; } - if (TCL_OK != TclStringRepeat(interp, objv[1], count, &resultPtr)) { - return TCL_ERROR; + resultPtr = TclStringRepeat(interp, objv[1], count, TCL_STRING_IN_PLACE); + if (resultPtr) { + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; } - Tcl_SetObjResult(interp, resultPtr); - return TCL_OK; + return TCL_ERROR; } /* diff --git a/generic/tclInt.h b/generic/tclInt.h index a3bd8ba..cee1d3a 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3201,8 +3201,6 @@ MODULE_SCOPE int TclStringMatch(const char *str, int strLen, MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, Tcl_Obj *patternObj, int flags); MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr); -MODULE_SCOPE int TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, - int count, Tcl_Obj **objPtrPtr); MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes, int numBytes, int flags, int line, struct CompileEnv *envPtr); @@ -4008,6 +4006,19 @@ MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, struct CompileEnv *envPtr); /* + * Routines that provide the [string] ensemble functionality. Possible + * candidates for public interface. + */ + +MODULE_SCOPE Tcl_Obj * TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, + int count, int flags); + +/* Flag values for the [string] ensemble functions. */ + +#define TCL_STRING_MATCH_NOCASE TCL_MATCH_NOCASE /* (1<<0) in tcl.h */ +#define TCL_STRING_IN_PLACE (1<<1) + +/* * Functions defined in generic/tclVar.c and currently exported only for use * by the bytecode compiler and engine. Some of these could later be placed in * the public interface. diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index c3a0192..8bb76c1 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2708,23 +2708,24 @@ TclGetStringStorage( * Performs the [string repeat] function. * * Results: - * A standard Tcl result. + * A (Tcl_Obj *) pointing to the result value, or NULL in case of an + * error. * * Side effects: - * Writes to *objPtrPtr the address of Tcl_Obj that is concatenation - * of count copies of the value in objPtr. + * On error, when interp is not NULL, error information is left in it. * *--------------------------------------------------------------------------- */ -int +Tcl_Obj * TclStringRepeat( Tcl_Interp *interp, Tcl_Obj *objPtr, int count, - Tcl_Obj **objPtrPtr) + int flags) { Tcl_Obj *objResultPtr; + int inPlace = flags & TCL_STRING_IN_PLACE; int length = 0, unichar = 0, done = 1; int binary = TclIsPureByteArray(objPtr); @@ -2759,8 +2760,7 @@ TclStringRepeat( if (length == 0) { /* Any repeats of empty is empty. */ - *objPtrPtr = objPtr; - return TCL_OK; + return objPtr; } if (count > INT_MAX/length) { @@ -2769,13 +2769,13 @@ TclStringRepeat( "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } if (binary) { /* Efficiently produce a pure byte array result */ - objResultPtr = Tcl_IsShared(objPtr) ? Tcl_DuplicateObj(objPtr) - : objPtr; + objResultPtr = (!inPlace || Tcl_IsShared(objPtr)) ? + Tcl_DuplicateObj(objPtr) : objPtr; Tcl_SetByteArrayLength(objResultPtr, count*length); /* PANIC? */ Tcl_SetByteArrayLength(objResultPtr, length); @@ -2788,7 +2788,7 @@ TclStringRepeat( (count - done) * length); } else if (unichar) { /* Efficiently produce a pure Tcl_UniChar array result */ - if (Tcl_IsShared(objPtr)) { + if (!inPlace || Tcl_IsShared(objPtr)) { objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length); } else { TclInvalidateStringRep(objPtr); @@ -2803,7 +2803,7 @@ TclStringRepeat( (Tcl_WideUInt)STRING_SIZE(count*length))); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } Tcl_SetObjLength(objResultPtr, length); while (count - done > done) { @@ -2814,7 +2814,7 @@ TclStringRepeat( (count - done) * length); } else { /* Efficiently concatenate string reps */ - if (Tcl_IsShared(objPtr)) { + if (!inPlace || Tcl_IsShared(objPtr)) { objResultPtr = Tcl_NewStringObj(Tcl_GetString(objPtr), length); } else { TclFreeIntRep(objPtr); @@ -2827,7 +2827,7 @@ TclStringRepeat( count*length)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } Tcl_SetObjLength(objResultPtr, length); while (count - done > done) { @@ -2837,8 +2837,7 @@ TclStringRepeat( Tcl_AppendToObj(objResultPtr, Tcl_GetString(objResultPtr), (count - done) * length); } - *objPtrPtr = objResultPtr; - return TCL_OK; + return objResultPtr; } /* -- cgit v0.12 From ca5e7c5b63ce1355c653763e82f8e75f7a38d333 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 5 Feb 2018 16:34:28 +0000 Subject: Revise the TclStringCat() interface to follow a common pattern. --- generic/tclCmdIL.c | 3 +-- generic/tclCmdMZ.c | 15 +++------------ generic/tclDictObj.c | 9 ++++++--- generic/tclExecute.c | 6 +++--- generic/tclInt.h | 5 ++--- generic/tclStringObj.c | 35 ++++++++++++++++------------------- 6 files changed, 31 insertions(+), 42 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 77b8434..fa32340 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -2193,8 +2193,7 @@ Tcl_JoinObjCmd( (void) Tcl_GetStringFromObj(joinObjPtr, &length); if (length == 0) { - TclStringCatObjv(interp, /* inPlace */ 0, listLen, elemPtrs, - &resObjPtr); + resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0); } else { int i; diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index e0344ef..f9e404b 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2847,7 +2847,6 @@ StringCatCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int code; Tcl_Obj *objResultPtr; if (objc < 2) { @@ -2857,23 +2856,15 @@ StringCatCmd( */ return TCL_OK; } - if (objc == 2) { - /* - * Other trivial case, single arg, just return it. - */ - Tcl_SetObjResult(interp, objv[1]); - return TCL_OK; - } - code = TclStringCatObjv(interp, /* inPlace */ 1, objc-1, objv+1, - &objResultPtr); + objResultPtr = TclStringCat(interp, objc-1, objv+1, TCL_STRING_IN_PLACE); - if (code == TCL_OK) { + if (objResultPtr) { Tcl_SetObjResult(interp, objResultPtr); return TCL_OK; } - return code; + return TCL_ERROR; } /* diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index 3b983e3..a0f6491 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -2309,9 +2309,12 @@ DictAppendCmd( if (objc == 4) { appendObjPtr = objv[3]; - } else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1, - objc-3, objv+3, &appendObjPtr)) { - return TCL_ERROR; + } else { + appendObjPtr = TclStringCat(interp, objc-3, objv+3, + TCL_STRING_IN_PLACE); + if (appendObjPtr == NULL) { + return TCL_ERROR; + } } } diff --git a/generic/tclExecute.c b/generic/tclExecute.c index f2cda0c..a30ec89 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -2682,9 +2682,9 @@ TEBCresume( case INST_STR_CONCAT1: opnd = TclGetUInt1AtPtr(pc+1); - - if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1, - opnd, &OBJ_AT_DEPTH(opnd-1), &objResultPtr)) { + objResultPtr = TclStringCat(interp, opnd, &OBJ_AT_DEPTH(opnd-1), + TCL_STRING_IN_PLACE); + if (objResultPtr == NULL) { TRACE_ERROR(interp); goto gotError; } diff --git a/generic/tclInt.h b/generic/tclInt.h index cee1d3a..6cb9955 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3189,9 +3189,6 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, int numBytes); -MODULE_SCOPE int TclStringCatObjv(Tcl_Interp *interp, int inPlace, - int objc, Tcl_Obj *const objv[], - Tcl_Obj **objPtrPtr); MODULE_SCOPE int TclStringFind(Tcl_Obj *needle, Tcl_Obj *haystack, int start); MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack, @@ -4010,6 +4007,8 @@ MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, * candidates for public interface. */ +MODULE_SCOPE Tcl_Obj * TclStringCat(Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[], int flags); MODULE_SCOPE Tcl_Obj * TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, int count, int flags); diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 8bb76c1..46162ff 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2843,40 +2843,39 @@ TclStringRepeat( /* *--------------------------------------------------------------------------- * - * TclStringCatObjv -- + * TclStringCat -- * * Performs the [string cat] function. * * Results: - * A standard Tcl result. + * A (Tcl_Obj *) pointing to the result value, or NULL in case of an + * error. * * Side effects: - * Writes to *objPtrPtr the address of Tcl_Obj that is concatenation - * of all objc values in objv. + * On error, when interp is not NULL, error information is left in it. * *--------------------------------------------------------------------------- */ -int -TclStringCatObjv( +Tcl_Obj * +TclStringCat( Tcl_Interp *interp, - int inPlace, int objc, Tcl_Obj * const objv[], - Tcl_Obj **objPtrPtr) + int flags) { Tcl_Obj *objResultPtr, * const *ov; int oc, length = 0, binary = 1; int allowUniChar = 1, requestUniChar = 0; int first = objc - 1; /* Index of first value possibly not empty */ int last = 0; /* Index of last value possibly not empty */ + int inPlace = flags & TCL_STRING_IN_PLACE; /* assert ( objc >= 0 ) */ if (objc <= 1) { /* Only one or no objects; return first or empty */ - *objPtrPtr = objc ? objv[0] : Tcl_NewObj(); - return TCL_OK; + return objc ? objv[0] : Tcl_NewObj(); } /* assert ( objc >= 2 ) */ @@ -3053,8 +3052,7 @@ TclStringCatObjv( if (last <= first /*|| length == 0 */) { /* Only one non-empty value or zero length; return first */ /* NOTE: (length == 0) implies (last <= first) */ - *objPtrPtr = objv[first]; - return TCL_OK; + return objv[first]; } objv += first; objc = (last - first + 1); @@ -3108,7 +3106,7 @@ TclStringCatObjv( (Tcl_WideUInt)STRING_SIZE(length))); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } dst = Tcl_GetUnicode(objResultPtr) + start; } else { @@ -3125,7 +3123,7 @@ TclStringCatObjv( (Tcl_WideUInt)STRING_SIZE(length))); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } dst = Tcl_GetUnicode(objResultPtr); } @@ -3156,7 +3154,7 @@ TclStringCatObjv( length)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } dst = Tcl_GetString(objResultPtr) + start; @@ -3172,7 +3170,7 @@ TclStringCatObjv( length)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } dst = Tcl_GetString(objResultPtr); } @@ -3187,8 +3185,7 @@ TclStringCatObjv( } } } - *objPtrPtr = objResultPtr; - return TCL_OK; + return objResultPtr; overflow: if (interp) { @@ -3196,7 +3193,7 @@ TclStringCatObjv( "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return TCL_ERROR; + return NULL; } /* -- cgit v0.12 From 2567185fd23306471a28bd33da7ddea94b0b44bc Mon Sep 17 00:00:00 2001 From: pooryorick Date: Tue, 6 Feb 2018 11:16:51 +0000 Subject: Add remaining wrapper to the NR functions, remaining calls to TCL_NRAddCallback, and a test for a package require script that yields. --- generic/tclBasic.c | 4 +- generic/tclPkg.c | 436 +++++++++++++++++++++++++++++++++-------------------- tests/package.test | 12 ++ 3 files changed, 288 insertions(+), 164 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index fa54551..366fd1f 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -238,7 +238,7 @@ static const CmdInfo builtInCmds[] = { {"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE}, {"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE}, - {"package", Tcl_PackageObjCmd, NULL, NULL, CMD_IS_SAFE}, + {"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE}, {"proc", Tcl_ProcObjCmd, NULL, NULL, CMD_IS_SAFE}, {"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE}, {"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE}, @@ -4480,6 +4480,8 @@ TclNRRunCallbacks( (void) Tcl_GetObjResult(interp); } + /* This is the trampoline. */ + while (TOP_CB(interp) != rootPtr) { callbackPtr = TOP_CB(interp); procPtr = callbackPtr->procPtr; diff --git a/generic/tclPkg.c b/generic/tclPkg.c index ce00fbf..6c5b827 100644 --- a/generic/tclPkg.c +++ b/generic/tclPkg.c @@ -69,8 +69,14 @@ typedef struct Require { void * clientDataPtr; const char *name; Package *pkgPtr; + char *versionToProvide; } Require; +typedef struct RequireProcArgs { + const char *name; + void *clientDataPtr; +} RequireProcArgs; + /* * Prototypes for functions defined in this file: */ @@ -91,10 +97,15 @@ static void AddRequirementsToResult(Tcl_Interp *interp, int reqc, static void AddRequirementsToDString(Tcl_DString *dstring, int reqc, Tcl_Obj *const reqv[]); static Package * FindPackage(Tcl_Interp *interp, const char *name); -static int PkgRequireCore(ClientData clientData, Tcl_Interp *interp, - int reqc, Tcl_Obj *const reqv[]); -static int SelectPackage (Tcl_Interp *interp, Require *reqPtr, - int reqc, Tcl_Obj *const reqv[]); +static int PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result); +static int TclNRPkgRequireProc(ClientData clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]); +static int SelectPackage(ClientData data[], Tcl_Interp *interp, int result); +static int SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result); +static int TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result); /* * Helper macros. @@ -406,80 +417,116 @@ Tcl_PkgRequireProc( * available. */ void *clientDataPtr) { + RequireProcArgs args; + args.name = name; + args.clientDataPtr = clientDataPtr; + return Tcl_NRCallObjProc(interp, TclNRPkgRequireProc, (void *)&args, reqc, reqv); +} + +static int +TclNRPkgRequireProc( + ClientData clientData, + Tcl_Interp *interp, + int reqc, + Tcl_Obj *const reqv[]) { + RequireProcArgs *args = clientData; + Tcl_NRAddCallback(interp, PkgRequireCore, (void *)args->name, INT2PTR(reqc), (void *)reqv, args->clientDataPtr); + return TCL_OK; +} + +static int +PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result) +{ + const char *name = data[0]; + int reqc = PTR2INT(data[1]); + Tcl_Obj *const *reqv = data[2]; int code = CheckAllRequirements(interp, reqc, reqv); - Require require; + Require *reqPtr; if (code != TCL_OK) { return code; } - require.clientDataPtr = clientDataPtr; - require.name = name; - require.pkgPtr = NULL; - return Tcl_NRCallObjProc(interp, PkgRequireCore, &require, reqc, reqv); + reqPtr = ckalloc(sizeof(Require)); + Tcl_NRAddCallback(interp, PkgRequireCoreCleanup, reqPtr, NULL, NULL, NULL); + reqPtr->clientDataPtr = data[3]; + reqPtr->name = name; + reqPtr->pkgPtr = FindPackage(interp, name); + if (reqPtr->pkgPtr->version == NULL) { + Tcl_NRAddCallback(interp, SelectPackage, reqPtr, INT2PTR(reqc), (void *)reqv, PkgRequireCoreStep1); + } else { + Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL); + } + return TCL_OK; } -int -PkgRequireCore( - ClientData clientData, - Tcl_Interp *interp, /* Interpreter in which package is now - * available. */ - int reqc, /* Requirements constraining the desired - * version. */ - Tcl_Obj *const reqv[] /* 0 means to use the latest version - * available. */ - ) -{ - int code, satisfies; +static int +PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result) { Tcl_DString command; - Require *reqPtr = clientData; - char *script, *pkgVersionI; + char *script; + Require *reqPtr = data[0]; + int reqc = PTR2INT(data[1]); + Tcl_Obj **const reqv = data[2]; const char *name = reqPtr->name /* Name of desired package. */; - void *clientDataPtr = reqPtr->clientDataPtr; - - reqPtr->pkgPtr = FindPackage(interp, name); if (reqPtr->pkgPtr->version == NULL) { - code = SelectPackage(interp, reqPtr, reqc, reqv); - if (code != TCL_OK) { - return code; - } - if (reqPtr->pkgPtr->version == NULL) { - /* - * The package is not in the database. If there is a "package unknown" - * command, invoke it. - */ + /* + * The package is not in the database. If there is a "package unknown" + * command, invoke it. + */ - script = ((Interp *) interp)->packageUnknown; - if (script != NULL) { - Tcl_DStringInit(&command); - Tcl_DStringAppend(&command, script, -1); - Tcl_DStringAppendElement(&command, name); - AddRequirementsToDString(&command, reqc, reqv); - - code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), - Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); - Tcl_DStringFree(&command); - - if ((code != TCL_OK) && (code != TCL_ERROR)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad return code: %d", code)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); - code = TCL_ERROR; - } - if (code == TCL_ERROR) { - Tcl_AddErrorInfo(interp, - "\n (\"package unknown\" script)"); - return code; - } - Tcl_ResetResult(interp); - /* pkgPtr may now be invalid, so refresh it. */ - reqPtr->pkgPtr = FindPackage(interp, name); - code = SelectPackage(interp, reqPtr, reqc, reqv); - if (code != TCL_OK) { - return code; - } - } - } + script = ((Interp *) interp)->packageUnknown; + if (script == NULL) { + Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL); + } else { + Tcl_DStringInit(&command); + Tcl_DStringAppend(&command, script, -1); + Tcl_DStringAppendElement(&command, name); + AddRequirementsToDString(&command, reqc, reqv); + + Tcl_NRAddCallback(interp, PkgRequireCoreStep2, reqPtr, INT2PTR(reqc), (void *)reqv, NULL); + Tcl_NREvalObj(interp, + Tcl_NewStringObj(Tcl_DStringValue(&command), Tcl_DStringLength(&command)), + TCL_EVAL_GLOBAL + ); + Tcl_DStringFree(&command); + } + return TCL_OK; + } else { + Tcl_NRAddCallback(interp, PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL); } + return TCL_OK; +} +static int +PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result) { + Require *reqPtr = data[0]; + int reqc = PTR2INT(data[1]); + Tcl_Obj **const reqv = data[2]; + const char *name = reqPtr->name /* Name of desired package. */; + if ((result != TCL_OK) && (result != TCL_ERROR)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad return code: %d", result)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); + result = TCL_ERROR; + } + if (result == TCL_ERROR) { + Tcl_AddErrorInfo(interp, + "\n (\"package unknown\" script)"); + return result; + } + Tcl_ResetResult(interp); + /* pkgPtr may now be invalid, so refresh it. */ + reqPtr->pkgPtr = FindPackage(interp, name); + Tcl_NRAddCallback(interp, SelectPackage, reqPtr, INT2PTR(reqc), (void *)reqv, PkgRequireCoreFinal); + return TCL_OK; +} + +static int +PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result) { + Require *reqPtr = data[0]; + int reqc = PTR2INT(data[1]), satisfies; + Tcl_Obj **const reqv = data[2]; + char *pkgVersionI; + void *clientDataPtr = reqPtr->clientDataPtr; + const char *name = reqPtr->name /* Name of desired package. */; if (reqPtr->pkgPtr->version == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't find package %s", name)); @@ -517,13 +564,23 @@ PkgRequireCore( Tcl_SetObjResult(interp, Tcl_NewStringObj(reqPtr->pkgPtr->version, -1)); return TCL_OK; } + +static int +PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result) { + ckfree(data[0]); + return result; +} + -int SelectPackage (Tcl_Interp *interp, Require *reqPtr, int reqc, Tcl_Obj *const reqv[]) { +static int +SelectPackage(ClientData data[], Tcl_Interp *interp, int result) { PkgAvail *availPtr, *bestPtr, *bestStablePtr; char *availVersion, *bestVersion, *bestStableVersion; /* Internal rep. of versions */ - char *script; - int availStable, code, satisfies; + int availStable, satisfies; + Require *reqPtr = data[0]; + int reqc = PTR2INT(data[1]); + Tcl_Obj **const reqv = data[2]; const char *name = reqPtr->name; Package *pkgPtr = reqPtr->pkgPtr; Interp *iPtr = (Interp *) interp; @@ -660,7 +717,9 @@ int SelectPackage (Tcl_Interp *interp, Require *reqPtr, int reqc, Tcl_Obj *const bestPtr = bestStablePtr; } - if (bestPtr != NULL) { + if (bestPtr == NULL) { + Tcl_NRAddCallback(interp, data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL); + } else { /* * We found an ifneeded script for the package. Be careful while * executing it: this could cause reentrancy, so (a) protect the @@ -669,105 +728,118 @@ int SelectPackage (Tcl_Interp *interp, Require *reqPtr, int reqc, Tcl_Obj *const */ char *versionToProvide = bestPtr->version; - PkgFiles *pkgFiles; - PkgName *pkgName; - script = bestPtr->script; - - pkgPtr->clientData = versionToProvide; Tcl_Preserve(versionToProvide); - Tcl_Preserve(script); - pkgFiles = TclInitPkgFiles(interp); - /* Push "ifneeded" package name in "tclPkgFiles" assocdata. */ - pkgName = ckalloc(sizeof(PkgName) + strlen(name)); - pkgName->nextPtr = pkgFiles->names; - strcpy(pkgName->name, name); - pkgFiles->names = pkgName; + pkgPtr->clientData = versionToProvide; if (bestPtr->pkgIndex) { TclPkgFileSeen(interp, bestPtr->pkgIndex); } - code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL); - /* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/ - pkgFiles->names = pkgName->nextPtr; - ckfree(pkgName); - Tcl_Release(script); + reqPtr->versionToProvide = versionToProvide; + Tcl_NRAddCallback(interp, SelectPackageFinal, reqPtr, INT2PTR(reqc), (void *)reqv, data[3]); + Tcl_NREvalObj(interp, Tcl_NewStringObj(bestPtr->script, -1), TCL_EVAL_GLOBAL); + } + return TCL_OK; +} + +static int +SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result) { + Require *reqPtr = data[0]; + int reqc = PTR2INT(data[1]); + Tcl_Obj **const reqv = data[2]; + const char *name = reqPtr->name; + char *versionToProvide = reqPtr->versionToProvide; - reqPtr->pkgPtr = FindPackage(interp, name); - if (code == TCL_OK) { - Tcl_ResetResult(interp); - if (reqPtr->pkgPtr->version == NULL) { - code = TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "attempt to provide package %s %s failed:" - " no version of package %s provided", - name, versionToProvide, name)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED", - NULL); - } else { - char *pvi, *vi; - - if (CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pvi, - NULL) != TCL_OK) { - code = TCL_ERROR; - } else if (CheckVersionAndConvert(interp, - versionToProvide, &vi, NULL) != TCL_OK) { - ckfree(pvi); - code = TCL_ERROR; - } else { - int res = CompareVersions(pvi, vi, NULL); - - ckfree(pvi); - ckfree(vi); - if (res != 0) { - code = TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "attempt to provide package %s %s failed:" - " package %s %s provided instead", - name, versionToProvide, - name, reqPtr->pkgPtr->version)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", - "WRONGPROVIDE", NULL); - } - } - } - } else if (code != TCL_ERROR) { - Tcl_Obj *codePtr = Tcl_NewIntObj(code); + PkgFiles *pkgFiles; + PkgName *pkgName; + + pkgFiles = TclInitPkgFiles(interp); + /* Push "ifneeded" package name in "tclPkgFiles" assocdata. */ + pkgName = ckalloc(sizeof(PkgName) + strlen(name)); + pkgName->nextPtr = pkgFiles->names; + strcpy(pkgName->name, name); + pkgFiles->names = pkgName; + + /* Pop the "ifneeded" package name from "tclPkgFiles" assocdata*/ + pkgFiles->names = pkgName->nextPtr; + ckfree(pkgName); + reqPtr->pkgPtr = FindPackage(interp, name); + if (result == TCL_OK) { + Tcl_ResetResult(interp); + if (reqPtr->pkgPtr->version == NULL) { + result = TCL_ERROR; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to provide package %s %s failed:" - " bad return code: %s", - name, versionToProvide, TclGetString(codePtr))); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); - TclDecrRefCount(codePtr); - code = TCL_ERROR; - } + " no version of package %s provided", + name, versionToProvide, name)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED", + NULL); + } else { + char *pvi, *vi; - if (code == TCL_ERROR) { - Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( - "\n (\"package ifneeded %s %s\" script)", - name, versionToProvide)); + if (CheckVersionAndConvert(interp, reqPtr->pkgPtr->version, &pvi, + NULL) != TCL_OK) { + result = TCL_ERROR; + } else if (CheckVersionAndConvert(interp, + versionToProvide, &vi, NULL) != TCL_OK) { + ckfree(pvi); + result = TCL_ERROR; + } else { + int res = CompareVersions(pvi, vi, NULL); + + ckfree(pvi); + ckfree(vi); + if (res != 0) { + result = TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "attempt to provide package %s %s failed:" + " package %s %s provided instead", + name, versionToProvide, + name, reqPtr->pkgPtr->version)); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", + "WRONGPROVIDE", NULL); + } + } } - Tcl_Release(versionToProvide); + } else if (result != TCL_ERROR) { + Tcl_Obj *codePtr = Tcl_NewIntObj(result); - if (code != TCL_OK) { - /* - * Take a non-TCL_OK code from the script as an indication the - * package wasn't loaded properly, so the package system - * should not remember an improper load. - * - * This is consistent with our returning NULL. If we're not - * willing to tell our caller we got a particular version, we - * shouldn't store that version for telling future callers - * either. - */ + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "attempt to provide package %s %s failed:" + " bad return code: %s", + name, versionToProvide, TclGetString(codePtr))); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); + TclDecrRefCount(codePtr); + result = TCL_ERROR; + } - if (reqPtr->pkgPtr->version != NULL) { - ckfree(reqPtr->pkgPtr->version); - reqPtr->pkgPtr->version = NULL; - } - reqPtr->pkgPtr->clientData = NULL; - return code; + if (result == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"package ifneeded %s %s\" script)", + name, versionToProvide)); + } + Tcl_Release(versionToProvide); + + if (result != TCL_OK) { + /* + * Take a non-TCL_OK code from the script as an indication the + * package wasn't loaded properly, so the package system + * should not remember an improper load. + * + * This is consistent with our returning NULL. If we're not + * willing to tell our caller we got a particular version, we + * shouldn't store that version for telling future callers + * either. + */ + + if (reqPtr->pkgPtr->version != NULL) { + ckfree(reqPtr->pkgPtr->version); + reqPtr->pkgPtr->version = NULL; } + reqPtr->pkgPtr->clientData = NULL; + return result; } + + Tcl_NRAddCallback(interp, data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL); return TCL_OK; } @@ -874,10 +946,19 @@ Tcl_PkgPresentEx( * *---------------------------------------------------------------------- */ +int +Tcl_PackageObjCmd( + ClientData dummy, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + return Tcl_NRCallObjProc(interp, TclNRPackageObjCmd, NULL, objc, objv); +} /* ARGSUSED */ int -Tcl_PackageObjCmd( +TclNRPackageObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ @@ -894,7 +975,7 @@ Tcl_PackageObjCmd( PKG_VERSIONS, PKG_VSATISFIES }; Interp *iPtr = (Interp *) interp; - int optionIndex, exact, i, satisfies; + int optionIndex, exact, i, newobjc, satisfies; PkgAvail *availPtr, *prevPtr; Package *pkgPtr; Tcl_HashEntry *hPtr; @@ -903,6 +984,7 @@ Tcl_PackageObjCmd( const char *version; const char *argv2, *argv3, *argv4; char *iva = NULL, *ivb = NULL; + Tcl_Obj *objvListPtr, **newObjvPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); @@ -1148,7 +1230,6 @@ Tcl_PackageObjCmd( argv2 = TclGetString(objv[2]); if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) { Tcl_Obj *ov; - int res; if (objc != 5) { goto requireSyntax; @@ -1165,20 +1246,42 @@ Tcl_PackageObjCmd( */ ov = Tcl_NewStringObj(version, -1); + Tcl_IncrRefCount(ov); Tcl_AppendStringsToObj(ov, "-", version, NULL); version = NULL; argv3 = TclGetString(objv[3]); + Tcl_IncrRefCount(objv[3]); - Tcl_IncrRefCount(ov); - res = Tcl_PkgRequireProc(interp, argv3, 1, &ov, NULL); - TclDecrRefCount(ov); - return res; + objvListPtr = Tcl_NewListObj(0, NULL); + Tcl_IncrRefCount(objvListPtr); + Tcl_ListObjAppendElement(interp, objvListPtr, ov); + Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr); + + Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL, NULL); + Tcl_NRAddCallback(interp, PkgRequireCore, (void *)argv3, INT2PTR(newobjc), newObjvPtr, NULL); + return TCL_OK; } else { + int i, newobjc = objc-3; + Tcl_Obj *const *newobjv = objv + 3; if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) { return TCL_ERROR; } + objvListPtr = Tcl_NewListObj(0, NULL); + Tcl_IncrRefCount(objvListPtr); + Tcl_IncrRefCount(objv[2]); + for (i = 0; i < newobjc; i++) { - return Tcl_PkgRequireProc(interp, argv2, objc-3, objv+3, NULL); + /* + * Tcl_Obj structures may have come from another interpreter, + * so duplicate them. + */ + + Tcl_ListObjAppendElement(interp, objvListPtr, Tcl_DuplicateObj(newobjv[i])); + } + Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr); + Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[2], objvListPtr, NULL, NULL); + Tcl_NRAddCallback(interp, PkgRequireCore, (void *)argv2, INT2PTR(newobjc), newObjvPtr, NULL); + return TCL_OK; } break; case PKG_UNKNOWN: { @@ -1318,6 +1421,13 @@ Tcl_PackageObjCmd( } return TCL_OK; } + +static int +TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result) { + TclDecrRefCount((Tcl_Obj *)data[0]); + TclDecrRefCount((Tcl_Obj *)data[1]); + return result; +} /* *---------------------------------------------------------------------- diff --git a/tests/package.test b/tests/package.test index bb938b8..2843701 100644 --- a/tests/package.test +++ b/tests/package.test @@ -625,6 +625,18 @@ test pkg-3.53 {Tcl_PkgRequire procedure, picking best stable version} -constrain package require t set x } -result {1.1} +test package-3.54 {Tcl_PkgRequire procedure, coroutine support} -setup { + package forget t +} -body { + coroutine coro1 apply {{} { + package ifneeded t 2.1 { + yield + package provide t 2.1 + } + package require t 2.1 + }} + list [catch {coro1} msg] $msg +} -match glob -result {0 2.1} test package-4.1 {Tcl_PackageCmd procedure} -returnCodes error -body { -- cgit v0.12 From 25fcbf685dbd09f24d7d45c8c6b90ed3c33eab17 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 6 Feb 2018 17:26:40 +0000 Subject: Rename TclStringFind to TclStringFirst. Repair its operations on bytearrays. Stop trying to operate on utf-8 until we nail that down better. --- generic/tclCmdMZ.c | 10 +------- generic/tclExecute.c | 2 +- generic/tclInt.h | 4 ++-- generic/tclStringObj.c | 63 +++++++++++++++++++++++--------------------------- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index f9e404b..5d49d2a 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1335,16 +1335,8 @@ StringFirstCmd( if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &start)) { return TCL_ERROR; } - - if (start < 0) { - start = 0; - } - if (start >= size) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); - return TCL_OK; - } } - Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFind(objv[1], + Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFirst(objv[1], objv[2], start))); return TCL_OK; } diff --git a/generic/tclExecute.c b/generic/tclExecute.c index a30ec89..679b57a 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5715,7 +5715,7 @@ TEBCresume( NEXT_INST_V(1, 3, 1); case INST_STR_FIND: - match = TclStringFind(OBJ_UNDER_TOS, OBJ_AT_TOS, 0); + match = TclStringFirst(OBJ_UNDER_TOS, OBJ_AT_TOS, 0); TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); diff --git a/generic/tclInt.h b/generic/tclInt.h index 6cb9955..f288a3a 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3189,8 +3189,6 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, int numBytes); -MODULE_SCOPE int TclStringFind(Tcl_Obj *needle, Tcl_Obj *haystack, - int start); MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack, int last); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, @@ -4009,6 +4007,8 @@ MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, MODULE_SCOPE Tcl_Obj * TclStringCat(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); +MODULE_SCOPE int TclStringFirst(Tcl_Obj *needle, Tcl_Obj *haystack, + int start); MODULE_SCOPE Tcl_Obj * TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, int count, int flags); diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 46162ff..bb72acd 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3199,7 +3199,7 @@ TclStringCat( /* *--------------------------------------------------------------------------- * - * TclStringFind -- + * TclStringFirst -- * * Implements the [string first] operation. * @@ -3215,20 +3215,20 @@ TclStringCat( */ int -TclStringFind( +TclStringFirst( Tcl_Obj *needle, Tcl_Obj *haystack, int start) { int lh, ln = Tcl_GetCharLength(needle); + if (start < 0) { + start = 0; + } if (ln == 0) { - /* - * We don't find empty substrings. Bizarre! - * - * TODO: When we one day make this a true substring - * finder, change this to "return 0" - */ + /* We don't find empty substrings. Bizarre! + * Whenever this routine is turned into a proper substring + * finder, change to `return start` after limits imposed. */ return -1; } @@ -3236,51 +3236,46 @@ TclStringFind( unsigned char *end, *try, *bh; unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); + /* Find bytes in bytes */ bh = Tcl_GetByteArrayFromObj(haystack, &lh); end = bh + lh; try = bh + start; while (try + ln <= end) { - try = memchr(try, bn[0], end - try); - + /* + * Look for the leading byte of the needle in the haystack + * starting at try and stopping when there's not enough room + * for the needle left. + */ + try = memchr(try, bn[0], (end + 1 - ln) - try); if (try == NULL) { + /* Leading byte not found -> needle cannot be found. */ return -1; } + /* Leading byte found, check rest of needle. */ if (0 == memcmp(try+1, bn+1, ln-1)) { + /* Checks! Return the successful index. */ return (try - bh); } + /* Rest of needle match failed; Iterate to continue search. */ try++; } return -1; } /* - * Check if we have two strings of single-byte characters. If we have, we - * can use strstr() to do the search. Note that we can sometimes have - * multibyte characters when the string could be minimally represented - * using single byte characters; we can't assume that a mismatch here - * means no match. + * TODO: It might be nice to support some cases where it is not + * necessary to shimmer to &tclStringType to compute the result, + * and instead operate just on the objPtr->bytes values directly. + * However, we also do not want the answer to change based on the + * code pathway, or if it does we want that to be for some values + * we explicitly decline to support. Getting there will involve + * locking down in practice more firmly just what encodings produce + * what supported results for the objPtr->bytes values. For now, + * do only the well-defined Tcl_UniChar array search. */ - lh = Tcl_GetCharLength(haystack); - if (haystack->bytes && (lh == haystack->length) && needle->bytes - && (ln == needle->length)) { - /* - * Both haystack and needle are all single-byte chars. - */ - - char *found = strstr(haystack->bytes + start, needle->bytes); - - if (found) { - return (found - haystack->bytes); - } else { - return -1; - } - } else { - /* - * Do the search on the unicode representation for simplicity. - */ - + { Tcl_UniChar *try, *end, *uh; Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln); -- cgit v0.12 From 99ca63a80a648b2e65a9b54be78022e5cd161307 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 6 Feb 2018 18:33:41 +0000 Subject: TclStringLast fixed. --- generic/tclCmdMZ.c | 8 -------- generic/tclStringObj.c | 48 ++++++++++-------------------------------------- 2 files changed, 10 insertions(+), 46 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 5d49d2a..03b254d 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1380,14 +1380,6 @@ StringLastCmd( if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &last)) { return TCL_ERROR; } - - if (last < 0) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); - return TCL_OK; - } - if (last >= size) { - last = size - 1; - } } Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringLast(objv[1], objv[2], last))); diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index bb72acd..4481818 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3323,24 +3323,24 @@ TclStringLast( * We don't find empty substrings. Bizarre! * * TODO: When we one day make this a true substring - * finder, change this to "return 0" + * finder, change this to "return last", after limitation. */ return -1; } - if (ln > last + 1) { + lh = Tcl_GetCharLength(haystack); + if (last >= lh) { + last = lh - 1; + } + + if (last < ln - 1) { return -1; } if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) { - unsigned char *try, *bh; + unsigned char *try, *bh = Tcl_GetByteArrayFromObj(haystack, &lh); unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); - bh = Tcl_GetByteArrayFromObj(haystack, &lh); - - if (last + 1 > lh) { - last = lh - 1; - } try = bh + last + 1 - ln; while (try >= bh) { if ((*try == bn[0]) @@ -3352,38 +3352,10 @@ TclStringLast( return -1; } - lh = Tcl_GetCharLength(haystack); - if (last + 1 > lh) { - last = lh - 1; - } - if (haystack->bytes && (lh == haystack->length)) { - /* haystack is all single-byte chars */ - - if (needle->bytes && (ln == needle->length)) { - /* needle is also all single-byte chars */ - - char *try = haystack->bytes + last + 1 - ln; - while (try >= haystack->bytes) { - if ((*try == needle->bytes[0]) - && (0 == memcmp(try+1, needle->bytes + 1, ln - 1))) { - return (try - haystack->bytes); - } - try--; - } - return -1; - } else { - /* - * Cannot find substring with a multi-byte char inside - * a string with no multi-byte chars. - */ - return -1; - } - } else { - Tcl_UniChar *try, *uh; + { + Tcl_UniChar *try, *uh = Tcl_GetUnicodeFromObj(haystack, &lh); Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln); - uh = Tcl_GetUnicodeFromObj(haystack, &lh); - try = uh + last + 1 - ln; while (try >= uh) { if ((*try == un[0]) -- cgit v0.12 From fde3c52d294c62edfd6aa2735c4244bd1b763b83 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 6 Feb 2018 19:10:45 +0000 Subject: Rework TclStringReverse to consistent standard form. --- generic/tclCmdMZ.c | 2 +- generic/tclInt.h | 6 +++--- generic/tclStringObj.c | 20 +++++++++++--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 03b254d..ed4312e 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2382,7 +2382,7 @@ StringRevCmd( return TCL_ERROR; } - Tcl_SetObjResult(interp, TclStringObjReverse(objv[1])); + Tcl_SetObjResult(interp, TclStringReverse(objv[1], TCL_STRING_IN_PLACE)); return TCL_OK; } diff --git a/generic/tclInt.h b/generic/tclInt.h index f288a3a..f8149be 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3189,13 +3189,10 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, int numBytes); -MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack, - int last); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, Tcl_Obj *patternObj, int flags); -MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr); MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes, int numBytes, int flags, int line, struct CompileEnv *envPtr); @@ -4009,8 +4006,11 @@ MODULE_SCOPE Tcl_Obj * TclStringCat(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); MODULE_SCOPE int TclStringFirst(Tcl_Obj *needle, Tcl_Obj *haystack, int start); +MODULE_SCOPE int TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack, + int last); MODULE_SCOPE Tcl_Obj * TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, int count, int flags); +MODULE_SCOPE Tcl_Obj * TclStringReverse(Tcl_Obj *objPtr, int flags); /* Flag values for the [string] ensemble functions. */ diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 4481818..9526f7e 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3371,14 +3371,14 @@ TclStringLast( /* *--------------------------------------------------------------------------- * - * TclStringObjReverse -- + * TclStringReverse -- * * Implements the [string reverse] operation. * * Results: - * An unshared Tcl value which is the [string reverse] of the argument - * supplied. When sharing rules permit, the returned value might be the - * argument with modifications done in place. + * A Tcl value which is the [string reverse] of the argument supplied. + * When sharing rules permit and the caller requests, the returned value + * might be the argument with modifications done in place. * * Side effects: * May allocate a new Tcl_Obj. @@ -3409,17 +3409,19 @@ ReverseBytes( } Tcl_Obj * -TclStringObjReverse( - Tcl_Obj *objPtr) +TclStringReverse( + Tcl_Obj *objPtr, + int flags) { String *stringPtr; Tcl_UniChar ch = 0; + int inPlace = flags & TCL_STRING_IN_PLACE; if (TclIsPureByteArray(objPtr)) { int numBytes; unsigned char *from = Tcl_GetByteArrayFromObj(objPtr, &numBytes); - if (Tcl_IsShared(objPtr)) { + if (!inPlace || Tcl_IsShared(objPtr)) { objPtr = Tcl_NewByteArrayObj(NULL, numBytes); } ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, NULL), from, numBytes); @@ -3433,7 +3435,7 @@ TclStringObjReverse( Tcl_UniChar *from = Tcl_GetUnicode(objPtr); Tcl_UniChar *src = from + stringPtr->numChars; - if (Tcl_IsShared(objPtr)) { + if (!inPlace || Tcl_IsShared(objPtr)) { Tcl_UniChar *to; /* @@ -3462,7 +3464,7 @@ TclStringObjReverse( int numBytes = objPtr->length; char *to, *from = objPtr->bytes; - if (Tcl_IsShared(objPtr)) { + if (!inPlace || Tcl_IsShared(objPtr)) { objPtr = Tcl_NewObj(); Tcl_SetObjLength(objPtr, numBytes); } -- cgit v0.12