From f3896e51875d3696de089804ab5e205403ee842a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 4 Nov 2022 11:11:18 +0000 Subject: New functions Tcl_NewWideUIntObj()/Tcl_SetWideUIntObj() (still experimental) --- doc/IntObj.3 | 29 +++++++++++++--------- generic/tcl.decls | 8 ++++++ generic/tclClock.c | 4 +-- generic/tclCmdMZ.c | 2 +- generic/tclDecls.h | 11 +++++++++ generic/tclLink.c | 4 +-- generic/tclObj.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ generic/tclStubInit.c | 2 ++ generic/tclTest.c | 2 +- 9 files changed, 113 insertions(+), 17 deletions(-) diff --git a/doc/IntObj.3 b/doc/IntObj.3 index d640dbb..5577cc9 100644 --- a/doc/IntObj.3 +++ b/doc/IntObj.3 @@ -8,7 +8,7 @@ .so man.macros .BS .SH NAME -Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers +Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers .SH SYNOPSIS .nf \fB#include \fR @@ -22,12 +22,17 @@ Tcl_Obj * Tcl_Obj * \fBTcl_NewWideIntObj\fR(\fIwideValue\fR) .sp +Tcl_Obj * +\fBTcl_NewWideUIntObj\fR(\fIuwideValue\fR) +.sp \fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR) .sp \fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR) .sp \fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR) .sp +\fBTcl_SetWideUIntObj\fR(\fIobjPtr, uwideValue\fR) +.sp int \fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) .sp @@ -66,6 +71,8 @@ Integer value used to initialize or set a Tcl value. Long integer value used to initialize or set a Tcl value. .AP Tcl_WideInt wideValue in Wide integer value used to initialize or set a Tcl value. +.AP Tcl_WideUInt uwideValue in +Unsigned wide integer value used to initialize or set a Tcl value. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, and \fBTcl_SetBignumObj\fR, this points to the value in which to store an @@ -107,18 +114,18 @@ The \fBmp_int\fR type is a multiple-precision integer type defined by the LibTomMath multiple-precision integer library. .PP The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR, -and \fBTcl_NewBignumObj\fR routines each create and return a new -Tcl value initialized to the integral value of the argument. The -returned Tcl value is unshared. +\fBTcl_NewWideIntObj\fR, and \fBTcl_NewBignumObj\fR routines each create +and return a new Tcl value initialized to the integral value of the +argument. The returned Tcl value is unshared. .PP The \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, -and \fBTcl_SetBignumObj\fR routines each set the value of an existing -Tcl value pointed to by \fIobjPtr\fR to the integral value provided -by the other argument. The \fIobjPtr\fR argument must point to an -unshared Tcl value. Any attempt to set the value of a shared Tcl value -violates Tcl's copy-on-write policy. Any existing string representation -or internal representation in the unshared Tcl value will be freed -as a consequence of setting the new value. +\fBTcl_SetWideIntObj\fR, and \fBTcl_SetBignumObj\fR routines each set +the value of an existing Tcl value pointed to by \fIobjPtr\fR to the +integral value provided by the other argument. The \fIobjPtr\fR +argument must point to an unshared Tcl value. Any attempt to set the +value of a shared Tcl value violates Tcl's copy-on-write policy. Any +existing string representation or internal representation in the unshared +Tcl value will be freed as a consequence of setting the new value. .PP The \fBTcl_GetIntForIndex\fR routine attempts to retrieve an index value from the Tcl value \fIobjPtr\fR. If the attempt succeeds, diff --git a/generic/tcl.decls b/generic/tcl.decls index 994af13..f3d8924 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -2552,6 +2552,14 @@ declare 683 { int Tcl_GetEncodingNulLength(Tcl_Encoding encoding) } +# TIP #648 +declare 684 { + Tcl_Obj *Tcl_NewWideUIntObj(Tcl_WideUInt wideValue) +} +declare 685 { + void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, Tcl_WideUInt uwideValue) +} + # ----- BASELINE -- FOR -- 8.7.0 ----- # ############################################################################## diff --git a/generic/tclClock.c b/generic/tclClock.c index a9ba70c..72605ca 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -1810,7 +1810,7 @@ ClockMillisecondsObjCmd( return TCL_ERROR; } Tcl_GetTime(&now); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) + Tcl_SetObjResult(interp, Tcl_NewWideUIntObj( now.sec * 1000 + now.usec / 1000)); return TCL_OK; } @@ -1998,7 +1998,7 @@ ClockSecondsObjCmd( return TCL_ERROR; } Tcl_GetTime(&now); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec)); + Tcl_SetObjResult(interp, Tcl_NewWideUIntObj(now.sec)); return TCL_OK; } diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index b063689..3f42438 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -4099,7 +4099,7 @@ Tcl_TimeObjCmd( * Use int obj since we know time is not fractional. [Bug 1202178] */ - objs[0] = Tcl_NewWideIntObj((count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec); + objs[0] = Tcl_NewWideUIntObj((count <= 0) ? 0 : (Tcl_WideUInt)totalMicroSec); } else { objs[0] = Tcl_NewDoubleObj(totalMicroSec/count); } diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 8cb77b8..f7523fd 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -2038,6 +2038,11 @@ EXTERN int Tcl_RemoveChannelMode(Tcl_Interp *interp, Tcl_Channel chan, int mode); /* 683 */ EXTERN int Tcl_GetEncodingNulLength(Tcl_Encoding encoding); +/* 684 */ +EXTERN Tcl_Obj * Tcl_NewWideUIntObj(Tcl_WideUInt wideValue); +/* 685 */ +EXTERN void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, + Tcl_WideUInt uwideValue); typedef struct { const struct TclPlatStubs *tclPlatStubs; @@ -2757,6 +2762,8 @@ typedef struct TclStubs { int (*tcl_GetNumber) (Tcl_Interp *interp, const char *bytes, size_t numBytes, void **clientDataPtr, int *typePtr); /* 681 */ int (*tcl_RemoveChannelMode) (Tcl_Interp *interp, Tcl_Channel chan, int mode); /* 682 */ int (*tcl_GetEncodingNulLength) (Tcl_Encoding encoding); /* 683 */ + Tcl_Obj * (*tcl_NewWideUIntObj) (Tcl_WideUInt wideValue); /* 684 */ + void (*tcl_SetWideUIntObj) (Tcl_Obj *objPtr, Tcl_WideUInt uwideValue); /* 685 */ } TclStubs; extern const TclStubs *tclStubsPtr; @@ -4155,6 +4162,10 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_RemoveChannelMode) /* 682 */ #define Tcl_GetEncodingNulLength \ (tclStubsPtr->tcl_GetEncodingNulLength) /* 683 */ +#define Tcl_NewWideUIntObj \ + (tclStubsPtr->tcl_NewWideUIntObj) /* 684 */ +#define Tcl_SetWideUIntObj \ + (tclStubsPtr->tcl_SetWideUIntObj) /* 685 */ #endif /* defined(USE_TCL_STUBS) */ diff --git a/generic/tclLink.c b/generic/tclLink.c index 0d57d44..7775cf8 100644 --- a/generic/tclLink.c +++ b/generic/tclLink.c @@ -1456,7 +1456,7 @@ ObjValue( memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes); objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *)); for (i=0; i < linkPtr->numElems; i++) { - TclNewIntObj(objv[i], (Tcl_WideInt) + objv[i] = Tcl_NewWideUIntObj( linkPtr->lastValue.uwPtr[i]); } resultObj = Tcl_NewListObj(linkPtr->numElems, objv); @@ -1464,7 +1464,7 @@ ObjValue( return resultObj; } linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt); - return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw); + return Tcl_NewWideUIntObj(linkPtr->lastValue.uw); case TCL_LINK_STRING: p = LinkedVar(char *); diff --git a/generic/tclObj.c b/generic/tclObj.c index ce8e610..806f910 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3219,6 +3219,34 @@ Tcl_NewWideIntObj( /* *---------------------------------------------------------------------- * + * Tcl_NewWideUIntObj -- + * + * Results: + * The newly created object is returned. This object will have an invalid + * string representation. The returned object has ref count 0. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj * +Tcl_NewWideUIntObj( + Tcl_WideUInt uwideValue) + /* Wide integer used to initialize the new + * object. */ +{ + Tcl_Obj *objPtr; + + TclNewObj(objPtr); + Tcl_SetWideUIntObj(objPtr, uwideValue); + return objPtr; +} + +/* + *---------------------------------------------------------------------- + * * Tcl_DbNewWideIntObj -- * * If a client is compiled with TCL_MEM_DEBUG defined, calls to @@ -3312,6 +3340,46 @@ Tcl_SetWideIntObj( TclSetIntObj(objPtr, wideValue); } + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetWideUIntObj -- + * + * Modify an object to be a wide integer object or a bignum object + * and to have the specified unsigned wide integer value. + * + * Results: + * None. + * + * Side effects: + * The object's old string rep, if any, is freed. Also, any old internal + * rep is freed. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetWideUIntObj( + Tcl_Obj *objPtr, /* Object w. internal rep to init. */ + Tcl_WideUInt uwideValue) + /* Wide integer used to initialize the + * object's value. */ +{ + if (Tcl_IsShared(objPtr)) { + Tcl_Panic("%s called with shared object", "Tcl_SetWideUIntObj"); + } + + if (uwideValue > WIDE_MAX) { + mp_int bignumValue; + if (mp_init_i64(&bignumValue, uwideValue) != MP_OKAY) { + Tcl_Panic("%s called with shared object", "Tcl_SetWideUIntObj"); + } + TclSetBignumInternalRep(objPtr, &bignumValue); + } { + TclSetIntObj(objPtr, (Tcl_WideInt)uwideValue); + } +} /* *---------------------------------------------------------------------- diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 1ffe916..8c72144 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -2050,6 +2050,8 @@ const TclStubs tclStubs = { Tcl_GetNumber, /* 681 */ Tcl_RemoveChannelMode, /* 682 */ Tcl_GetEncodingNulLength, /* 683 */ + Tcl_NewWideUIntObj, /* 684 */ + Tcl_SetWideUIntObj, /* 685 */ }; /* !END!: Do not edit above this line. */ diff --git a/generic/tclTest.c b/generic/tclTest.c index c9bad56..878e51f 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -3119,7 +3119,7 @@ TestlinkCmd( Tcl_DecrRefCount(tmp); Tcl_PrintDouble(NULL, (double)floatVar, buffer); Tcl_AppendElement(interp, buffer); - tmp = Tcl_NewWideIntObj((Tcl_WideInt)uwideVar); + tmp = Tcl_NewWideUIntObj(uwideVar); Tcl_AppendElement(interp, Tcl_GetString(tmp)); Tcl_DecrRefCount(tmp); } else if (strcmp(argv[1], "set") == 0) { -- cgit v0.12 From 3b7f710d06680e498bd8d451f6c47cb6c78918f7 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 9 Nov 2022 22:18:01 +0000 Subject: New functions Tcl_NewSizeObj/Tcl_SetSizeObj --- generic/tclDecls.h | 8 ++++++++ generic/tclInt.decls | 2 +- generic/tclIntDecls.h | 6 +++--- generic/tclListObj.c | 8 +++----- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 9344d68..d802789 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4431,6 +4431,14 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_StringMatch #define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0) +#if TCL_MAJOR_VERSION > 8 +# define Tcl_NewSizeObj(value) (((value) == TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideUIntObj(value)) +# define Tcl_SetSizeObj(objPtr, value) (((value) == TCL_INDEX_NONE) ? Tcl_SetWideIntObj(objPtr, -1) : Tcl_SetWideUIntObj(objPtr, value)) +#else +# define Tcl_NewSizeObj Tcl_NewIntObj +# define Tcl_SetSizeObj Tcl_SetIntObj +#endif + #if TCL_UTF_MAX < 4 # undef Tcl_UniCharToUtfDString # define Tcl_UniCharToUtfDString Tcl_Char16ToUtfDString diff --git a/generic/tclInt.decls b/generic/tclInt.decls index c0e0e06..b3e352a 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -701,7 +701,7 @@ declare 258 { # TIP 625: for unit testing - create list objects with span declare 260 { - Tcl_Obj *TclListTestObj(int length, int leadingSpace, int endSpace) + Tcl_Obj *TclListTestObj(Tcl_Size length, Tcl_Size leadingSpace, Tcl_Size endSpace) } # TIP 625: for unit testing - check list invariants diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index 3da8567..4c8d897 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -660,8 +660,8 @@ EXTERN Tcl_Obj * TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* Slot 259 is reserved */ /* 260 */ -EXTERN Tcl_Obj * TclListTestObj(int length, int leadingSpace, - int endSpace); +EXTERN Tcl_Obj * TclListTestObj(Tcl_Size length, + Tcl_Size leadingSpace, Tcl_Size endSpace); /* 261 */ EXTERN void TclListObjValidate(Tcl_Interp *interp, Tcl_Obj *listObj); @@ -930,7 +930,7 @@ typedef struct TclIntStubs { void (*tclStaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 257 */ Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 258 */ void (*reserved259)(void); - Tcl_Obj * (*tclListTestObj) (int length, int leadingSpace, int endSpace); /* 260 */ + Tcl_Obj * (*tclListTestObj) (Tcl_Size length, Tcl_Size leadingSpace, Tcl_Size endSpace); /* 260 */ void (*tclListObjValidate) (Tcl_Interp *interp, Tcl_Obj *listObj); /* 261 */ } TclIntStubs; diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 8ee0f48..6950d9d 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -3514,10 +3514,8 @@ UpdateStringOfList( *------------------------------------------------------------------------ */ Tcl_Obj * -TclListTestObj (int length, int leadingSpace, int endSpace) +TclListTestObj (Tcl_Size length, Tcl_Size leadingSpace, Tcl_Size endSpace) { - if (length < 0) - length = 0; if (leadingSpace < 0) leadingSpace = 0; if (endSpace < 0) @@ -3538,9 +3536,9 @@ TclListTestObj (int length, int leadingSpace, int endSpace) ListRepInit(capacity, NULL, 0, &listRep); ListStore *storePtr = listRep.storePtr; - int i; + Tcl_Size i; for (i = 0; i < length; ++i) { - storePtr->slots[i + leadingSpace] = Tcl_NewIntObj(i); + storePtr->slots[i + leadingSpace] = Tcl_NewSizeObj(i); Tcl_IncrRefCount(storePtr->slots[i + leadingSpace]); } storePtr->firstUsed = leadingSpace; -- cgit v0.12 From 9dd0e900483a5b0cca9e68966d34dffa814b43e2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 10 Nov 2022 15:21:13 +0000 Subject: If value is out-of-range (e.g. on 32-bit system >= 2^32-1), Tcl_NewSizeObj() will result in a '-1' object as well --- generic/tclDecls.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index d802789..b9d2347 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4432,8 +4432,8 @@ extern const TclStubs *tclStubsPtr; #define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0) #if TCL_MAJOR_VERSION > 8 -# define Tcl_NewSizeObj(value) (((value) == TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideUIntObj(value)) -# define Tcl_SetSizeObj(objPtr, value) (((value) == TCL_INDEX_NONE) ? Tcl_SetWideIntObj(objPtr, -1) : Tcl_SetWideUIntObj(objPtr, value)) +# define Tcl_NewSizeObj(value) (((value) >= TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideUIntObj(value)) +# define Tcl_SetSizeObj(objPtr, value) (((value) >= TCL_INDEX_NONE) ? Tcl_SetWideIntObj(objPtr, -1) : Tcl_SetWideUIntObj(objPtr, value)) #else # define Tcl_NewSizeObj Tcl_NewIntObj # define Tcl_SetSizeObj Tcl_SetIntObj -- cgit v0.12 From 29f4c762f29d31c1d2184e4bdb515038ec1d5d27 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 10 Nov 2022 17:28:15 +0000 Subject: Update doc --- doc/IntObj.3 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/IntObj.3 b/doc/IntObj.3 index 5577cc9..7ca7f75 100644 --- a/doc/IntObj.3 +++ b/doc/IntObj.3 @@ -8,7 +8,7 @@ .so man.macros .BS .SH NAME -Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers +Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_NewSizeObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_NewWideUIntObj, Tcl_NewSizeObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers .SH SYNOPSIS .nf \fB#include \fR @@ -25,6 +25,9 @@ Tcl_Obj * Tcl_Obj * \fBTcl_NewWideUIntObj\fR(\fIuwideValue\fR) .sp +Tcl_Obj * +\fBTcl_NewSizeObj\fR(\fIsizeValue\fR) +.sp \fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR) .sp \fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR) @@ -33,6 +36,8 @@ Tcl_Obj * .sp \fBTcl_SetWideUIntObj\fR(\fIobjPtr, uwideValue\fR) .sp +\fBTcl_SetSizeObj\fR(\fIobjPtr, sizeValue\fR) +.sp int \fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) .sp @@ -73,8 +78,12 @@ Long integer value used to initialize or set a Tcl value. Wide integer value used to initialize or set a Tcl value. .AP Tcl_WideUInt uwideValue in Unsigned wide integer value used to initialize or set a Tcl value. +.AP Tcl_Size sizeValue in +\fTcl_Size\f integer value used to initialize or set a Tcl value. +In Tcl 8.x, \fTcl_Size\f is actually the same as int. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, +\fBTcl_SetWideUIntObj\fR, \fBTcl_SetSizeObj\fR, and \fBTcl_SetBignumObj\fR, this points to the value in which to store an integral value. For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR, \fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and -- cgit v0.12 From ee898100a16badc57acbcc0bac4f211b9253d1e9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 10 Nov 2022 17:44:56 +0000 Subject: Tcl_NewSizeObj -> Tcl_NewIndexObj --- doc/IntObj.3 | 24 ++++++++++++------------ generic/tclDecls.h | 8 ++++---- generic/tclListObj.c | 7 +------ 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/doc/IntObj.3 b/doc/IntObj.3 index 7ca7f75..cfae9a0 100644 --- a/doc/IntObj.3 +++ b/doc/IntObj.3 @@ -8,7 +8,7 @@ .so man.macros .BS .SH NAME -Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_NewSizeObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_NewWideUIntObj, Tcl_NewSizeObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers +Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_NewIndexObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_SetWideUIntObj, Tcl_SetIndexObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers .SH SYNOPSIS .nf \fB#include \fR @@ -26,7 +26,7 @@ Tcl_Obj * \fBTcl_NewWideUIntObj\fR(\fIuwideValue\fR) .sp Tcl_Obj * -\fBTcl_NewSizeObj\fR(\fIsizeValue\fR) +\fBTcl_NewIndexObj\fR(\fIindexValue\fR) .sp \fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR) .sp @@ -36,7 +36,7 @@ Tcl_Obj * .sp \fBTcl_SetWideUIntObj\fR(\fIobjPtr, uwideValue\fR) .sp -\fBTcl_SetSizeObj\fR(\fIobjPtr, sizeValue\fR) +\fBTcl_SetIndexObj\fR(\fIobjPtr, indexValue\fR) .sp int \fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) @@ -78,12 +78,12 @@ Long integer value used to initialize or set a Tcl value. Wide integer value used to initialize or set a Tcl value. .AP Tcl_WideUInt uwideValue in Unsigned wide integer value used to initialize or set a Tcl value. -.AP Tcl_Size sizeValue in -\fTcl_Size\f integer value used to initialize or set a Tcl value. +.AP Tcl_Size indexValue in +\fTcl_Size\f value used to initialize or set a Tcl value. In Tcl 8.x, \fTcl_Size\f is actually the same as int. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, -\fBTcl_SetWideUIntObj\fR, \fBTcl_SetSizeObj\fR, +\fBTcl_SetWideUIntObj\fR, \fBTcl_SetIndexObj\fR, and \fBTcl_SetBignumObj\fR, this points to the value in which to store an integral value. For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR, \fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and @@ -123,14 +123,14 @@ The \fBmp_int\fR type is a multiple-precision integer type defined by the LibTomMath multiple-precision integer library. .PP The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR, -\fBTcl_NewWideIntObj\fR, and \fBTcl_NewBignumObj\fR routines each create -and return a new Tcl value initialized to the integral value of the -argument. The returned Tcl value is unshared. +\fBTcl_NewWideUIntObj\fR, \fBTcl_NewIndexObj\fR, and \fBTcl_NewBignumObj\fR +routines each create and return a new Tcl value initialized to the +integral value of the argument. The returned Tcl value is unshared. .PP The \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, -\fBTcl_SetWideIntObj\fR, and \fBTcl_SetBignumObj\fR routines each set -the value of an existing Tcl value pointed to by \fIobjPtr\fR to the -integral value provided by the other argument. The \fIobjPtr\fR +\fBTcl_SetWideUIntObj\fR, \fBTcl_SetIndexObj\fR, and \fBTcl_SetBignumObj\fR +routines each set the value of an existing Tcl value pointed to by \fIobjPtr\fR +to the integral value provided by the other argument. The \fIobjPtr\fR argument must point to an unshared Tcl value. Any attempt to set the value of a shared Tcl value violates Tcl's copy-on-write policy. Any existing string representation or internal representation in the unshared diff --git a/generic/tclDecls.h b/generic/tclDecls.h index b9d2347..6fcd08d 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4432,11 +4432,11 @@ extern const TclStubs *tclStubsPtr; #define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0) #if TCL_MAJOR_VERSION > 8 -# define Tcl_NewSizeObj(value) (((value) >= TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideUIntObj(value)) -# define Tcl_SetSizeObj(objPtr, value) (((value) >= TCL_INDEX_NONE) ? Tcl_SetWideIntObj(objPtr, -1) : Tcl_SetWideUIntObj(objPtr, value)) +# define Tcl_NewIndexObj(value) (((value) >= TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideUIntObj(value)) +# define Tcl_SetIndexObj(objPtr, value) (((value) >= TCL_INDEX_NONE) ? Tcl_SetWideIntObj(objPtr, -1) : Tcl_SetWideUIntObj(objPtr, value)) #else -# define Tcl_NewSizeObj Tcl_NewIntObj -# define Tcl_SetSizeObj Tcl_SetIntObj +# define Tcl_NewIndexObj Tcl_NewIntObj +# define Tcl_SetIndexObj Tcl_SetIntObj #endif #if TCL_UTF_MAX < 4 diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 6950d9d..f016224 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -3516,11 +3516,6 @@ UpdateStringOfList( Tcl_Obj * TclListTestObj (Tcl_Size length, Tcl_Size leadingSpace, Tcl_Size endSpace) { - if (leadingSpace < 0) - leadingSpace = 0; - if (endSpace < 0) - endSpace = 0; - ListRep listRep; Tcl_Size capacity; Tcl_Obj *listObj; @@ -3538,7 +3533,7 @@ TclListTestObj (Tcl_Size length, Tcl_Size leadingSpace, Tcl_Size endSpace) ListStore *storePtr = listRep.storePtr; Tcl_Size i; for (i = 0; i < length; ++i) { - storePtr->slots[i + leadingSpace] = Tcl_NewSizeObj(i); + storePtr->slots[i + leadingSpace] = Tcl_NewIndexObj(i); Tcl_IncrRefCount(storePtr->slots[i + leadingSpace]); } storePtr->firstUsed = leadingSpace; -- cgit v0.12 From 0a5df8ec7faf67b198d81d81ff4efe575614db00 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 11 Nov 2022 22:26:03 +0000 Subject: Fix for Tcl_SetWideUIntObj --- generic/tclClock.c | 2 +- generic/tclCmdMZ.c | 2 +- generic/tclObj.c | 2 +- generic/tclScan.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 72605ca..d64348e 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -1810,7 +1810,7 @@ ClockMillisecondsObjCmd( return TCL_ERROR; } Tcl_GetTime(&now); - Tcl_SetObjResult(interp, Tcl_NewWideUIntObj( + Tcl_SetObjResult(interp, Tcl_NewWideUIntObj((Tcl_WideUInt) now.sec * 1000 + now.usec / 1000)); return TCL_OK; } diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 3f42438..ff466d9 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -3775,7 +3775,7 @@ TclNRSwitchObjCmd( TclNewIndexObj(rangeObjAry[0], info.matches[j].start); TclNewIndexObj(rangeObjAry[1], info.matches[j].end-1); } else { - TclNewIndexObj(rangeObjAry[1], TCL_INDEX_NONE); + TclNewIntObj(rangeObjAry[1], -1); rangeObjAry[0] = rangeObjAry[1]; } diff --git a/generic/tclObj.c b/generic/tclObj.c index 7871692..0d56eec 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3371,7 +3371,7 @@ Tcl_SetWideUIntObj( if (uwideValue > WIDE_MAX) { mp_int bignumValue; - if (mp_init_i64(&bignumValue, uwideValue) != MP_OKAY) { + if (mp_init_u64(&bignumValue, uwideValue) != MP_OKAY) { Tcl_Panic("%s called with shared object", "Tcl_SetWideUIntObj"); } TclSetBignumInternalRep(objPtr, &bignumValue); diff --git a/generic/tclScan.c b/generic/tclScan.c index 6bc914d..c0cf49f 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -1090,7 +1090,7 @@ Tcl_ScanObjCmd( if (code == TCL_OK) { if (underflow && (nconversions == 0)) { if (numVars) { - TclNewIndexObj(objPtr, TCL_INDEX_NONE); + TclNewIntObj(objPtr, -1); } else { if (objPtr) { Tcl_SetListObj(objPtr, 0, NULL); -- cgit v0.12 From 3c61afae6735dd0fd14a8ec428464827a8cc68cd Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 11 Nov 2022 22:48:53 +0000 Subject: Fix panic message --- generic/tclObj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclObj.c b/generic/tclObj.c index 0d56eec..4639731 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3372,7 +3372,7 @@ Tcl_SetWideUIntObj( if (uwideValue > WIDE_MAX) { mp_int bignumValue; if (mp_init_u64(&bignumValue, uwideValue) != MP_OKAY) { - Tcl_Panic("%s called with shared object", "Tcl_SetWideUIntObj"); + Tcl_Panic("%s: memory overflow", "Tcl_SetWideUIntObj"); } TclSetBignumInternalRep(objPtr, &bignumValue); } { -- cgit v0.12 From f923243cbbea98e1a1bb5a08072c64d60f5a65e2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 8 Mar 2024 15:15:51 +0000 Subject: Add Tcl_GetAlias/Tcl_GetAliasObj to TIP #616 --- doc/CrtAlias.3 | 12 ++++++++-- generic/tcl.decls | 16 ++++++++++--- generic/tclDecls.h | 65 ++++++++++++++++++++++++++++++++++++++------------- generic/tclInterp.c | 8 +++---- generic/tclStubInit.c | 42 +++++++++++++++++++++++++++++---- 5 files changed, 114 insertions(+), 29 deletions(-) diff --git a/doc/CrtAlias.3 b/doc/CrtAlias.3 index fba6253..879e07c 100644 --- a/doc/CrtAlias.3 +++ b/doc/CrtAlias.3 @@ -87,16 +87,24 @@ command is defined for an alias. .AP "const char" **targetCmdPtr out Pointer to location to store the address of the name of the target command for an alias. -.AP int *argcPtr out +.AP "Tcl_Size \&| int" *argcPtr out Pointer to location to store count of additional arguments to be passed to the alias. The location is in storage owned by the caller. +If it points to a variable which type is not \fBTcl_Size\fR, a compiler +warning will be generated. If your extensions is compiled with -DTCL_8_API, +this function will return TCL_ERROR for aliases with more than INT_MAX +value arguments, otherwise expect it to crash. .AP "const char" ***argvPtr out Pointer to location to store a vector of strings, the additional arguments to pass to an alias. The location is in storage owned by the caller, the vector of strings is owned by the called function. -.AP int *objcPtr out +.AP "Tcl_Size \&| int" *objcPtr out Pointer to location to store count of additional value arguments to be passed to the alias. The location is in storage owned by the caller. +If it points to a variable which type is not \fBTcl_Size\fR, a compiler +warning will be generated. If your extensions is compiled with -DTCL_8_API, +this function will return TCL_ERROR for aliases with more than INT_MAX +value arguments, otherwise expect it to crash .AP Tcl_Obj ***objvPtr out Pointer to location to store a vector of Tcl_Obj structures, the additional arguments to pass to an alias command. The location is in storage diff --git a/generic/tcl.decls b/generic/tcl.decls index 5f82a1c..bdc581c 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -463,6 +463,11 @@ declare 142 { declare 143 { void Tcl_Finalize(void) } +declare 144 { + int Tcl_GetAlias(Tcl_Interp *interp, const char *childCmd, + Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, + Tcl_Size *argcPtr, const char ***argvPtr) +} declare 145 { Tcl_HashEntry *Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr) @@ -470,15 +475,20 @@ declare 145 { declare 146 { int Tcl_Flush(Tcl_Channel chan) } +declare 147 { + int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd, + Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, + Tcl_Size *objcPtr, Tcl_Obj ***objvPtr) +} declare 148 { - int Tcl_GetAlias(Tcl_Interp *interp, const char *childCmd, + int TclGetAlias(Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *argcPtr, const char ***argvPtr) } declare 149 { - int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd, + int TclGetAliasObj(Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, - int *objcPtr, Tcl_Obj ***objv) + int *objcPtr, Tcl_Obj ***objvPtr) } declare 150 { void *Tcl_GetAssocData(Tcl_Interp *interp, const char *name, diff --git a/generic/tclDecls.h b/generic/tclDecls.h index a2b0ec1..307699b 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -420,25 +420,34 @@ EXTERN int Tcl_ExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr, EXTERN int Tcl_ExprString(Tcl_Interp *interp, const char *expr); /* 143 */ EXTERN void Tcl_Finalize(void); -/* Slot 144 is reserved */ +/* 144 */ +EXTERN int Tcl_GetAlias(Tcl_Interp *interp, + const char *childCmd, + Tcl_Interp **targetInterpPtr, + const char **targetCmdPtr, Tcl_Size *argcPtr, + const char ***argvPtr); /* 145 */ EXTERN Tcl_HashEntry * Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 146 */ EXTERN int Tcl_Flush(Tcl_Channel chan); -/* Slot 147 is reserved */ -/* 148 */ -EXTERN int Tcl_GetAlias(Tcl_Interp *interp, +/* 147 */ +EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, + const char **targetCmdPtr, Tcl_Size *objcPtr, + Tcl_Obj ***objvPtr); +/* 148 */ +EXTERN int TclGetAlias(Tcl_Interp *interp, const char *childCmd, + Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *argcPtr, const char ***argvPtr); /* 149 */ -EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp, +EXTERN int TclGetAliasObj(Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, - Tcl_Obj ***objv); + Tcl_Obj ***objvPtr); /* 150 */ EXTERN void * Tcl_GetAssocData(Tcl_Interp *interp, const char *name, @@ -2023,12 +2032,12 @@ typedef struct TclStubs { int (*tcl_ExprObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 141 */ int (*tcl_ExprString) (Tcl_Interp *interp, const char *expr); /* 142 */ void (*tcl_Finalize) (void); /* 143 */ - void (*reserved144)(void); + int (*tcl_GetAlias) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, Tcl_Size *argcPtr, const char ***argvPtr); /* 144 */ Tcl_HashEntry * (*tcl_FirstHashEntry) (Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 145 */ int (*tcl_Flush) (Tcl_Channel chan); /* 146 */ - void (*reserved147)(void); - int (*tcl_GetAlias) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *argcPtr, const char ***argvPtr); /* 148 */ - int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 149 */ + int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); /* 147 */ + int (*tclGetAlias) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *argcPtr, const char ***argvPtr); /* 148 */ + int (*tclGetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 149 */ void * (*tcl_GetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr); /* 150 */ Tcl_Channel (*tcl_GetChannel) (Tcl_Interp *interp, const char *chanName, int *modePtr); /* 151 */ Tcl_Size (*tcl_GetChannelBufferSize) (Tcl_Channel chan); /* 152 */ @@ -2854,16 +2863,18 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_ExprString) /* 142 */ #define Tcl_Finalize \ (tclStubsPtr->tcl_Finalize) /* 143 */ -/* Slot 144 is reserved */ +#define Tcl_GetAlias \ + (tclStubsPtr->tcl_GetAlias) /* 144 */ #define Tcl_FirstHashEntry \ (tclStubsPtr->tcl_FirstHashEntry) /* 145 */ #define Tcl_Flush \ (tclStubsPtr->tcl_Flush) /* 146 */ -/* Slot 147 is reserved */ -#define Tcl_GetAlias \ - (tclStubsPtr->tcl_GetAlias) /* 148 */ #define Tcl_GetAliasObj \ - (tclStubsPtr->tcl_GetAliasObj) /* 149 */ + (tclStubsPtr->tcl_GetAliasObj) /* 147 */ +#define TclGetAlias \ + (tclStubsPtr->tclGetAlias) /* 148 */ +#define TclGetAliasObj \ + (tclStubsPtr->tclGetAliasObj) /* 149 */ #define Tcl_GetAssocData \ (tclStubsPtr->tcl_GetAssocData) /* 150 */ #define Tcl_GetChannel \ @@ -4159,7 +4170,7 @@ extern const TclStubs *tclStubsPtr; #endif #ifdef USE_TCL_STUBS - /* Protect those 10 functions, make them useless through the stub table */ + /* Protect those 12 functions, make them useless through the stub table */ # undef TclGetStringFromObj # undef TclGetBytesFromObj # undef TclGetUnicodeFromObj @@ -4170,6 +4181,8 @@ extern const TclStubs *tclStubsPtr; # undef TclSplitPath # undef TclFSSplitPath # undef TclParseArgsObjv +# undef TclGetAlias +# undef TclGetAliasObj #endif #if TCL_MAJOR_VERSION < 9 @@ -4216,6 +4229,12 @@ extern const TclStubs *tclStubsPtr; # undef Tcl_ParseArgsObjv # define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) \ tclStubsPtr->tclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) +# undef Tcl_GetAlias +# define Tcl_GetAlias(interp, childCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr) \ + tclStubsPtr->tclGetAlias((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (argcPtr), (argvPtr)) +# undef Tcl_GetAliasObj +# define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) \ + tclStubsPtr->tclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv)) #elif defined(TCL_8_API) # undef Tcl_GetByteArrayFromObj # undef Tcl_GetBytesFromObj @@ -4228,6 +4247,8 @@ extern const TclStubs *tclStubsPtr; # undef Tcl_SplitPath # undef Tcl_FSSplitPath # undef Tcl_ParseArgsObjv +# undef Tcl_GetAlias +# undef Tcl_GetAliasObj # if !defined(USE_TCL_STUBS) # define Tcl_GetByteArrayFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \ TclGetBytesFromObj(NULL, (objPtr), (sizePtr)) : \ @@ -4262,6 +4283,12 @@ extern const TclStubs *tclStubsPtr; # define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) <= sizeof(int) ? \ TclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) : \ (Tcl_ParseArgsObjv)((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv))) +# define Tcl_GetAlias(interp, childCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr) (sizeof(*(argcPtr)) <= sizeof(int) ? \ + TclGetAlias((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (argcPtr), (argvPtr)) : \ + (Tcl_GetAlias)((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (Tcl_Size *)(void *)(argcPtr), (argvPtr))) +# define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) (sizeof(*(objcPtr)) <= sizeof(int) ? \ + TclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv)) : \ + (Tcl_GetAliasObj)((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (Tcl_Size *)(void *)(objcPtr), (objv))) # elif !defined(BUILD_tcl) # define Tcl_GetByteArrayFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \ tclStubsPtr->tclGetBytesFromObj(NULL, (objPtr), (sizePtr)) : \ @@ -4296,6 +4323,12 @@ extern const TclStubs *tclStubsPtr; # define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) <= sizeof(int) ? \ tclStubsPtr->tclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) : \ tclStubsPtr->tcl_ParseArgsObjv((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv))) +# define Tcl_GetAlias(interp, childCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr) (sizeof(*(argcPtr)) <= sizeof(int) ? \ + tclStubsPtr->tclGetAlias((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (argcPtr), (argvPtr)) : \ + tclStubsPtr->tcl_GetAlias((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (Tcl_Size *)(void *)(argcPtr), (argvPtr))) +# define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) (sizeof(*(objcPtr)) <= sizeof(int) ? \ + tclStubsPtr->tclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv)) : \ + tclStubsPtr->tcl_GetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (Tcl_Size *)(void *)(objcPtr), (objv))) # endif /* defined(USE_TCL_STUBS) */ #else /* !defined(TCL_8_API) */ # undef Tcl_GetByteArrayFromObj diff --git a/generic/tclInterp.c b/generic/tclInterp.c index fa6cf80..5d949cf 100644 --- a/generic/tclInterp.c +++ b/generic/tclInterp.c @@ -1296,13 +1296,13 @@ Tcl_GetAlias( Tcl_Interp **targetInterpPtr, /* (Return) target interpreter. */ const char **targetNamePtr, /* (Return) name of target command. */ - int *argcPtr, /* (Return) count of addnl args. */ + Tcl_Size *argcPtr, /* (Return) count of addnl args. */ const char ***argvPtr) /* (Return) additional arguments. */ { InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; Tcl_HashEntry *hPtr; Alias *aliasPtr; - int i, objc; + Tcl_Size i, objc; Tcl_Obj **objv; hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName); @@ -1358,13 +1358,13 @@ Tcl_GetAliasObj( Tcl_Interp **targetInterpPtr, /* (Return) target interpreter. */ const char **targetNamePtr, /* (Return) name of target command. */ - int *objcPtr, /* (Return) count of addnl args. */ + Tcl_Size *objcPtr, /* (Return) count of addnl args. */ Tcl_Obj ***objvPtr) /* (Return) additional args. */ { InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; Tcl_HashEntry *hPtr; Alias *aliasPtr; - int objc; + Tcl_Size objc; Tcl_Obj **objv; hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName); diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 9072796..58b0465 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -98,6 +98,8 @@ # define TclSplitPath 0 # define TclFSSplitPath 0 # define TclParseArgsObjv 0 +# define TclGetAlias 0 +# define TclGetAliasObj 0 #else /* !defined(TCL_NO_DEPRECATED) */ int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, void *objcPtr, Tcl_Obj ***objvPtr) { @@ -192,6 +194,38 @@ int TclParseArgsObjv(Tcl_Interp *interp, *(int *)objcPtr = (int)n; return result; } +int TclGetAlias(Tcl_Interp *interp, const char *childCmd, + Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, + int *argcPtr, const char ***argvPtr) { + Tcl_Size n = TCL_INDEX_NONE; + int result = Tcl_GetAlias(interp, childCmd, targetInterpPtr, targetCmdPtr, &n, argvPtr); + if (argcPtr) { + if ((sizeof(int) != sizeof(size_t)) && (result == TCL_OK) && (n > INT_MAX)) { + if (interp) { + Tcl_AppendResult(interp, "List too large to be processed", NULL); + } + return TCL_ERROR; + } + *argcPtr = (int)n; + } + return result; +} +int TclGetAliasObj(Tcl_Interp *interp, const char *childCmd, + Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, + int *objcPtr, Tcl_Obj ***objv) { + Tcl_Size n = TCL_INDEX_NONE; + int result = Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, &n, objv); + if (objcPtr) { + if ((sizeof(int) != sizeof(size_t)) && (result == TCL_OK) && (n > INT_MAX)) { + if (interp) { + Tcl_AppendResult(interp, "List too large to be processed", NULL); + } + return TCL_ERROR; + } + *objcPtr = (int)n; + } + return result; +} #endif /* !defined(TCL_NO_DEPRECATED) */ #define TclBN_mp_add mp_add @@ -939,12 +973,12 @@ const TclStubs tclStubs = { Tcl_ExprObj, /* 141 */ Tcl_ExprString, /* 142 */ Tcl_Finalize, /* 143 */ - 0, /* 144 */ + Tcl_GetAlias, /* 144 */ Tcl_FirstHashEntry, /* 145 */ Tcl_Flush, /* 146 */ - 0, /* 147 */ - Tcl_GetAlias, /* 148 */ - Tcl_GetAliasObj, /* 149 */ + Tcl_GetAliasObj, /* 147 */ + TclGetAlias, /* 148 */ + TclGetAliasObj, /* 149 */ Tcl_GetAssocData, /* 150 */ Tcl_GetChannel, /* 151 */ Tcl_GetChannelBufferSize, /* 152 */ -- cgit v0.12 From 64a533d813ee5b78c1511eac31f82e02b8568ba9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 20 Mar 2024 09:33:21 +0000 Subject: TIP #690 implementation: Make "clock scan -valid 1" the default --- generic/tclClock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 6c6ac94..96bef63 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -244,7 +244,7 @@ TclClockInit( memset(&data->lastTZOffsCache, 0, sizeof(data->lastTZOffsCache)); - data->defFlags = 0; + data->defFlags = CLF_VALIDATE; /* * Install the commands. -- cgit v0.12 From adefac1ced296669d4d00fdede83f1266b587af7 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 21 Mar 2024 10:20:09 +0000 Subject: Unneeded line --- generic/tclStubInit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index b6f8738..41b7554 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -98,7 +98,6 @@ # define TclSplitPath 0 # define TclFSSplitPath 0 # define TclParseArgsObjv 0 -# define TclGetAlias 0 # define TclGetAliasObj 0 #else /* !defined(TCL_NO_DEPRECATED) */ int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, -- cgit v0.12 From 4a8b2951b55d370a933169b796863d52e58d9c9e Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 24 Mar 2024 16:27:50 +0000 Subject: Change Tcl_ExternalToUtfDStringEx and Tcl_UtfToExternalDStringEx to ignore START/END flags as stated in documentation instead of raising an error. --- generic/tclEncoding.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 1b99754..674d021 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1177,18 +1177,6 @@ Tcl_ExternalToUtfDStringEx( /* DO FIRST - Must always be initialized before returning */ Tcl_DStringInit(dstPtr); - if (flags & (TCL_ENCODING_START|TCL_ENCODING_END)) { - /* TODO - what other flags are illegal? - See TIP 656 */ - Tcl_SetObjResult( - interp, - Tcl_NewStringObj( - "Parameter error: TCL_ENCODING_{START,STOP} bits set in flags.", - TCL_INDEX_NONE)); - Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALFLAGS", (void *)NULL); - errno = EINVAL; - return TCL_ERROR; - } - dst = Tcl_DStringValue(dstPtr); dstLen = dstPtr->spaceAvl - 1; @@ -1203,6 +1191,7 @@ Tcl_ExternalToUtfDStringEx( srcLen = encodingPtr->lengthProc(src); } + flags &= ~TCL_ENCODING_END; flags |= TCL_ENCODING_START; if (encodingPtr->toUtfProc == UtfToUtfProc) { flags |= ENCODING_INPUT; @@ -1505,18 +1494,6 @@ Tcl_UtfToExternalDStringEx( /* DO FIRST - must always be initialized on return */ Tcl_DStringInit(dstPtr); - if (flags & (TCL_ENCODING_START|TCL_ENCODING_END)) { - /* TODO - what other flags are illegal? - See TIP 656 */ - Tcl_SetObjResult( - interp, - Tcl_NewStringObj( - "Parameter error: TCL_ENCODING_{START,STOP} bits set in flags.", - TCL_INDEX_NONE)); - Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALFLAGS", (void *)NULL); - errno = EINVAL; - return TCL_ERROR; - } - dst = Tcl_DStringValue(dstPtr); dstLen = dstPtr->spaceAvl - 1; @@ -1531,6 +1508,7 @@ Tcl_UtfToExternalDStringEx( srcLen = strlen(src); } + flags &= ~TCL_ENCODING_END; flags |= TCL_ENCODING_START; while (1) { int srcChunkLen, srcChunkRead; -- cgit v0.12 From 6e4ef7af0d7d94a74983de89b85a772777c282f8 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 27 Mar 2024 15:46:06 +0000 Subject: Tests for [edb4b065f49] crash. --- tests/string.test | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/string.test b/tests/string.test index 26cd8a7..1a0ac05 100644 --- a/tests/string.test +++ b/tests/string.test @@ -228,6 +228,15 @@ test string-2.36.$noComp {string compare, binary neq unequal length} { test string-2.37.$noComp {string compare with -length >= 2^32} { run {string compare -length 4294967296 ab abde} } -1 +test string-bug-edb4b065f4-1 {string compare empty string against byte array} { + string compare "" [binary decode hex 00] +} -1 +test string-bug-edb4b065f4-2 {string compare -length empty string against byte array} { + string compare -length 1 "" [binary decode hex 00] +} -1 +test string-bug-edb4b065f4-3 {string compare -nocase empty string against byte array} { + string compare -nocase "" [binary decode hex 00] +} -1 # only need a few tests on equal, since it uses the same code as # string compare, but just modifies the return output -- cgit v0.12 From c60347e32076ccad4ce1fddfbe5612be5d0b2020 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 27 Mar 2024 16:14:38 +0000 Subject: Proposed fix for [edb4b065f4] --- generic/tclStringObj.c | 4 ++-- tests/string.test | 52 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 5fe6ef7..ee2eaae 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3717,7 +3717,7 @@ TclStringCmp( if (empty > 0) { switch (TclCheckEmptyString(value2Ptr)) { case -1: - s1 = 0; + s1 = ""; s1len = 0; s2 = TclGetStringFromObj(value2Ptr, &s2len); break; @@ -3732,7 +3732,7 @@ TclStringCmp( } else if (TclCheckEmptyString(value2Ptr) > 0) { switch (empty) { case -1: - s2 = 0; + s2 = ""; s2len = 0; s1 = TclGetStringFromObj(value1Ptr, &s1len); break; diff --git a/tests/string.test b/tests/string.test index 1a0ac05..4ae200b 100644 --- a/tests/string.test +++ b/tests/string.test @@ -228,15 +228,30 @@ test string-2.36.$noComp {string compare, binary neq unequal length} { test string-2.37.$noComp {string compare with -length >= 2^32} { run {string compare -length 4294967296 ab abde} } -1 -test string-bug-edb4b065f4-1 {string compare empty string against byte array} { - string compare "" [binary decode hex 00] +test string-2.38.$noComp {string compare empty string against byte array} { + # Bug edb4b065f4 + run {string compare "" [binary decode hex 00]} } -1 -test string-bug-edb4b065f4-2 {string compare -length empty string against byte array} { - string compare -length 1 "" [binary decode hex 00] +test string-2.38.$noComp {string compare -length empty string against byte array} { + # Bug edb4b065f4 + run {string compare -length 1 "" [binary decode hex 00]} } -1 -test string-bug-edb4b065f4-3 {string compare -nocase empty string against byte array} { - string compare -nocase "" [binary decode hex 00] +test string-2.38.$noComp {string compare -nocase empty string against byte array} { + # Bug edb4b065f4 + run {string compare -nocase "" [binary decode hex 00]} } -1 +test string-2.38.$noComp {string compare empty string against byte array} { + # Bug edb4b065f4 + run {string compare [binary decode hex 00] ""} +} 1 +test string-2.38.$noComp {string compare -length empty string against byte array} { + # Bug edb4b065f4 + run {string compare -length 1 [binary decode hex 00] ""} +} 1 +test string-2.38.$noComp {string compare -nocase empty string against byte array} { + # Bug edb4b065f4 + run {string compare -nocase [binary decode hex 00] ""} +} 1 # only need a few tests on equal, since it uses the same code as # string compare, but just modifies the return output @@ -383,6 +398,31 @@ test string-3.43.$noComp {string equal, big -length} { test string-3.44.$noComp {string equal, bigger -length} -body { run {string equal -length 18446744073709551616 abc def} } -returnCodes 1 -result {integer value too large to represent} +test string-3.45.$noComp {string equal empty string against byte array} { + # Bug edb4b065f4 + run {string equal "" [binary decode hex 00]} +} 0 +test string-3.45.$noComp {string equal -length empty string against byte array} { + # Bug edb4b065f4 + run {string equal -length 1 "" [binary decode hex 00]} +} 0 +test string-3.45.$noComp {string equal -nocase empty string against byte array} { + # Bug edb4b065f4 + run {string equal -nocase "" [binary decode hex 00]} +} 0 +test string-3.45.$noComp {string equal empty string against byte array} { + # Bug edb4b065f4 + run {string equal [binary decode hex 00] ""} +} 0 +test string-3.45.$noComp {string equal -length empty string against byte array} { + # Bug edb4b065f4 + run {string equal -length 1 [binary decode hex 00] ""} +} 0 +test string-3.45.$noComp {string equal -nocase empty string against byte array} { + # Bug edb4b065f4 + run {string equal -nocase [binary decode hex 00] ""} +} 0 + test string-4.1.$noComp {string first, not enough args} { list [catch {run {string first a}} msg] $msg -- cgit v0.12 From 615c4be9ca12ae3c5e726b007b5a8dd111d2c08e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 27 Mar 2024 20:54:34 +0000 Subject: Libtommath 1.3 --- libtommath/CMakeLists.txt | 311 ++++++++++++++++++++++++++++++++ libtommath/appveyor.yml | 40 ++-- libtommath/bn_deprecated.c | 61 ++++++- libtommath/bn_mp_div.c | 4 +- libtommath/bn_mp_div_3.c | 63 ------- libtommath/bn_mp_div_d.c | 4 +- libtommath/bn_mp_expt_n.c | 53 ++++++ libtommath/bn_mp_expt_u32.c | 46 ----- libtommath/bn_mp_get_ll.c | 7 - libtommath/bn_mp_get_mag_ull.c | 7 - libtommath/bn_mp_init_ll.c | 7 - libtommath/bn_mp_init_ull.c | 7 - libtommath/bn_mp_log_n.c | 29 +++ libtommath/bn_mp_log_u32.c | 180 ------------------ libtommath/bn_mp_mul.c | 6 +- libtommath/bn_mp_prime_rand.c | 5 +- libtommath/bn_mp_root_n.c | 141 +++++++++++++++ libtommath/bn_mp_root_u32.c | 139 -------------- libtommath/bn_mp_set_double.c | 4 +- libtommath/bn_mp_set_ll.c | 7 - libtommath/bn_mp_set_ull.c | 7 - libtommath/bn_mp_sqrt.c | 73 -------- libtommath/bn_s_mp_balance_mul.c | 4 +- libtommath/bn_s_mp_div_3.c | 63 +++++++ libtommath/bn_s_mp_log.c | 81 +++++++++ libtommath/bn_s_mp_log_2expt.c | 12 ++ libtommath/bn_s_mp_log_d.c | 65 +++++++ libtommath/bn_s_mp_mul_high_digs_fast.c | 4 +- libtommath/bn_s_mp_rand_jenkins.c | 4 +- libtommath/bn_s_mp_toom_mul.c | 6 +- libtommath/changes.txt | 8 +- libtommath/helper.pl | 40 +++- libtommath/libtommath.pc.in | 9 +- libtommath/libtommath_VS2008.sln | 2 +- libtommath/libtommath_VS2008.vcproj | 50 ++--- libtommath/makefile | 56 +++--- libtommath/makefile.mingw | 62 ++++--- libtommath/makefile.msvc | 50 ++--- libtommath/makefile.shared | 53 +++--- libtommath/makefile.unix | 52 +++--- libtommath/makefile_include.mk | 6 +- libtommath/sources.cmake | 167 +++++++++++++++++ libtommath/tommath.def | 19 +- libtommath/tommath.h | 58 +++--- libtommath/tommath_class.h | 113 ++++++------ libtommath/tommath_private.h | 12 +- libtommath/win64-arm/libtommath.dll | Bin 69120 -> 70144 bytes libtommath/win64/libtommath.dll | Bin 81408 -> 81408 bytes macosx/Tcl.xcodeproj/project.pbxproj | 16 +- unix/Makefile.in | 27 ++- win/Makefile.in | 4 +- win/makefile.vc | 4 +- 52 files changed, 1352 insertions(+), 896 deletions(-) create mode 100644 libtommath/CMakeLists.txt delete mode 100644 libtommath/bn_mp_div_3.c create mode 100644 libtommath/bn_mp_expt_n.c delete mode 100644 libtommath/bn_mp_expt_u32.c delete mode 100644 libtommath/bn_mp_get_ll.c delete mode 100644 libtommath/bn_mp_get_mag_ull.c delete mode 100644 libtommath/bn_mp_init_ll.c delete mode 100644 libtommath/bn_mp_init_ull.c create mode 100644 libtommath/bn_mp_log_n.c delete mode 100644 libtommath/bn_mp_log_u32.c create mode 100644 libtommath/bn_mp_root_n.c delete mode 100644 libtommath/bn_mp_root_u32.c delete mode 100644 libtommath/bn_mp_set_ll.c delete mode 100644 libtommath/bn_mp_set_ull.c create mode 100644 libtommath/bn_s_mp_div_3.c create mode 100644 libtommath/bn_s_mp_log.c create mode 100644 libtommath/bn_s_mp_log_2expt.c create mode 100644 libtommath/bn_s_mp_log_d.c create mode 100644 libtommath/sources.cmake diff --git a/libtommath/CMakeLists.txt b/libtommath/CMakeLists.txt new file mode 100644 index 0000000..0b84e79 --- /dev/null +++ b/libtommath/CMakeLists.txt @@ -0,0 +1,311 @@ +# SPDX-License-Identifier: Unlicense +# +# LibTomMath, a free open source portable number theoretic multiple-precision +# integer (MPI) library written entirely in C. +# + +cmake_minimum_required(VERSION 3.10) + +project(libtommath + VERSION 1.3.0 + DESCRIPTION "A free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C." + HOMEPAGE_URL "https://www.libtom.net/LibTomMath" + LANGUAGES C) + +# package release version +# bump if re-releasing the same VERSION + patches +# set to 1 if releasing a new VERSION +set(PACKAGE_RELEASE_VERSION 1) + +#----------------------------------------------------------------------------- +# Include cmake modules +#----------------------------------------------------------------------------- +include(GNUInstallDirs) +include(CheckIPOSupported) +include(CMakePackageConfigHelpers) +# default is "No tests" +option(BUILD_TESTING "" OFF) +include(CTest) +include(sources.cmake) + +#----------------------------------------------------------------------------- +# Options +#----------------------------------------------------------------------------- +option(BUILD_SHARED_LIBS "Build shared library and only the shared library if \"ON\", default is static" OFF) + +#----------------------------------------------------------------------------- +# Add support for ccache if desired +#----------------------------------------------------------------------------- +find_program(CCACHE ccache) + +if(CCACHE) + option(ENABLE_CCACHE "Enable ccache." ON) +endif() + +# use ccache if installed +if(CCACHE AND ENABLE_CCACHE) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE}) +endif() + +#----------------------------------------------------------------------------- +# Compose CFLAGS +#----------------------------------------------------------------------------- + +# Some information ported from makefile_include.mk + + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE "Release") +endif() + +# We only differentiate between MSVC and GCC-compatible compilers +if(MSVC) + set(LTM_C_FLAGS -W3) +elseif(WATCOM) + set(LTM_C_FLAGS -fo=.obj -oaxt -3r -w3) +else() + set(LTM_C_FLAGS -Wall -Wsign-compare -Wextra -Wshadow + -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align + -Wstrict-prototypes -Wpointer-arith -Wsystem-headers) + set(CMAKE_C_FLAGS_DEBUG "-g3") + set(CMAKE_C_FLAGS_RELEASE "-O3 -funroll-loops -fomit-frame-pointer") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g3 -O2") + set(CMAKE_C_FLAGS_MINSIZEREL "-Os") +endif() + +# What compiler do we have and what are their...uhm... peculiarities +if(CMAKE_C_COMPILER_ID MATCHES "(C|c?)lang") + list(APPEND LTM_C_FLAGS -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header) + # Clang requires at least '-O1' for dead code elimination + set(CMAKE_C_FLAGS_DEBUG "-O1 ${CMAKE_C_FLAGS_DEBUG}") +endif() +if(CMAKE_C_COMPILER MATCHES "mingw") + list(APPEND LTM_C_FLAGS -Wno-shadow -Wno-expansion-to-defined -Wno-declaration-after-statement -Wno-bad-function-cast) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + list(APPEND LTM_C_FLAGS -Wno-nullability-completeness) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") + list(APPEND LTM_C_FLAGS -no-undefined) +endif() + +# TODO: coverage (lgcov) + +# If the user set the environment variables at generate-time, append them +# in order to allow overriding our defaults. +# ${LTM_CFLAGS} means the user passed it via sth like: +# $ cmake -DLTM_CFLAGS="foo" +list(APPEND LTM_C_FLAGS ${LTM_CFLAGS}) +list(APPEND LTM_LD_FLAGS ${LTM_LDFLAGS}) + +#----------------------------------------------------------------------------- +# library target +#----------------------------------------------------------------------------- +add_library(${PROJECT_NAME} + ${SOURCES} + ${HEADERS} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) + +target_compile_options(${PROJECT_NAME} BEFORE PRIVATE + ${LTM_C_FLAGS} +) +target_link_options(${PROJECT_NAME} BEFORE PRIVATE + ${LTM_LD_FLAGS} +) + +set(PUBLIC_HEADERS tommath.h) +set(C89 False CACHE BOOL "(Usually maintained automatically) Enable when the library is in c89 mode to package the correct header files on install") +if(C89) + list(APPEND PUBLIC_HEADERS tommath_c89.h) +endif() + +set_target_properties(${PROJECT_NAME} PROPERTIES + OUTPUT_NAME tommath + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER "${PUBLIC_HEADERS}" +) + +option(COMPILE_LTO "Build with LTO enabled") +if(COMPILE_LTO) + check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) + if(COMPILER_SUPPORTS_LTO) + set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(SEND_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.") + endif() +endif() + +#----------------------------------------------------------------------------- +# demo target +#----------------------------------------------------------------------------- + +if(BUILD_TESTING) + enable_testing() + add_subdirectory(demo) +endif() + +#----------------------------------------------------------------------------- +# Install/export targets and files +#----------------------------------------------------------------------------- +set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +set(PROJECT_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake") +set(PROJECT_CONFIG_FILE "${PROJECT_NAME}-config.cmake") +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") + +install(TARGETS ${PROJECT_NAME} + EXPORT ${TARGETS_EXPORT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +# Install libtommath.pc for pkg-config if we build a shared library +if(BUILD_SHARED_LIBS) + # Let the user override the default directory of the pkg-config file (usually this shouldn't be required to be changed) + set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Folder where to install .pc files") + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR} + ) +endif() + +# generate package version file +write_basic_package_version_file( + ${PROJECT_VERSION_FILE} + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +# install version file +install(FILES ${PROJECT_VERSION_FILE} + DESTINATION ${CONFIG_INSTALL_DIR} +) + +# build directory package config +export(EXPORT ${TARGETS_EXPORT_NAME} + FILE ${PROJECT_CONFIG_FILE} +) + +# installed package config +install(EXPORT ${TARGETS_EXPORT_NAME} + DESTINATION ${CONFIG_INSTALL_DIR} + FILE ${PROJECT_CONFIG_FILE} +) + +# add to CMake registry +export(PACKAGE ${PROJECT_NAME}) + +#--------------------------------------------------------------------------------------- +# Create release packages +#--------------------------------------------------------------------------------------- + +# determine distribution and architecture +find_program(LSB_RELEASE lsb_release) +find_program(SYSCTL sysctl) +find_program(UNAME uname) + +if(UNAME) + execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +elseif(SYSCTL) + execute_process(COMMAND sysctl -b hw.machine_arch OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +else() + string(TOLOWER ${CMAKE_SYSTEM_NAME} MACHINE_ARCH) +endif() + +if(LSB_RELEASE) + execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE LINUX_DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND lsb_release -sc OUTPUT_VARIABLE LINUX_DISTRO_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE LINUX_DISTRO_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + + string(TOLOWER ${LINUX_DISTRO} LINUX_DISTRO) + if(LINUX_DISTRO_CODENAME STREQUAL "n/a") + set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_VERSION}/) + else() + set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_CODENAME}/) + endif() +else() + set(DISTRO_PACK_PATH ${CMAKE_SYSTEM_NAME}/) +endif() + +# make sure untagged versions get a different package name +execute_process(COMMAND git describe --exact-match --tags ERROR_QUIET RESULT_VARIABLE REPO_HAS_TAG) +if(REPO_HAS_TAG EQUAL 0) + set(PACKAGE_NAME_SUFFIX "") +else() + set(PACKAGE_NAME_SUFFIX "-git") + message(STATUS "Use -git suffix") +endif() + +# default CPack generators +set(CPACK_GENERATOR TGZ STGZ) + +# extra CPack generators +if(LINUX_DISTRO STREQUAL "debian" OR LINUX_DISTRO STREQUAL "ubuntu" OR LINUX_DISTRO STREQUAL "linuxmint") + list(APPEND CPACK_GENERATOR DEB) +elseif(LINUX_DISTRO STREQUAL "fedora" OR LINUX_DISTRO STREQUAL "opensuse" OR LINUX_DISTRO STREQUAL "centos") + list(APPEND CPACK_GENERATOR RPM) +elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + list(APPEND CPACK_GENERATOR FREEBSD) +endif() + +set(LTM_DEBIAN_SHARED_PACKAGE_NAME "${PROJECT_NAME}${PACKAGE_NAME_SUFFIX}${PROJECT_VERSION_MAJOR}") + +# general CPack config +set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages/${DISTRO_PACK_PATH}) +message(STATUS "CPack: packages will be generated under ${CPACK_PACKAGE_DIRECTORY}") +if(BUILD_SHARED_LIBS) + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}") + set(CPACK_DEBIAN_PACKAGE_NAME "${LTM_DEBIAN_SHARED_PACKAGE_NAME}") +else() + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}-devel") + set(CPACK_DEBIAN_LIBRARIES_PACKAGE_NAME "${PROJECT_NAME}${PACKAGE_NAME_SUFFIX}-dev") +endif() +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LibTomMath") +set(CPACK_PACKAGE_VENDOR "libtom projects") +set(CPACK_PACKAGE_CONTACT "libtom@googlegroups.com") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(PACKAGE_NAME_TRAILER ${CPACK_PACKAGE_VERSION}-${PACKAGE_RELEASE_VERSION}_${MACHINE_ARCH}) +set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PACKAGE_NAME_TRAILER}) + +# deb specific CPack config +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) +set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) +set(CPACK_DEBIAN_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION}) +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +if(BUILD_SHARED_LIBS) + set(CPACK_DEBIAN_PACKAGE_SECTION "libs") +else() + set(CPACK_DEBIAN_PACKAGE_SECTION "devel") + set(CPACK_DEBIAN_PACKAGE_DEPENDS ${LTM_DEBIAN_SHARED_PACKAGE_NAME}) + set(CPACK_DEB_COMPONENT_INSTALL ON) + set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + set(CPACK_COMPONENTS_ALL Libraries) +endif() + +# rpm specific CPack config +set(CPACK_RPM_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION}) +set(CPACK_RPM_PACKAGE_ARCHITECTURE ${MACHINE_ARCH}) +set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}") +set(CPACK_RPM_PACKAGE_LICENSE "The Unlicense") + +# FreeBSD specific CPack config +set(CPACK_FREEBSD_PACKAGE_MAINTAINER "gahr@FreeBSD.org") +set(CPACK_FREEBSD_PACKAGE_ORIGIN "math/libtommath") +set(CPACK_FREEBSD_PACKAGE_CATEGORIES "math") + +include(CPack) diff --git a/libtommath/appveyor.yml b/libtommath/appveyor.yml index 0a8e075..e235491 100644 --- a/libtommath/appveyor.yml +++ b/libtommath/appveyor.yml @@ -1,20 +1,20 @@ -version: 1.2.1-{build} -branches: - only: - - master - - develop - - /^release/ - - /^travis/ -image: -- Visual Studio 2019 -- Visual Studio 2017 -- Visual Studio 2015 -build_script: -- cmd: >- - if "Visual Studio 2019"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" - if "Visual Studio 2017"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" - if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 - if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 - nmake -f makefile.msvc all -test_script: -- cmd: test.exe +version: 1.3.0-{build} +branches: + only: + - master + - develop + - /^release/ + - /^travis/ +image: +- Visual Studio 2019 +- Visual Studio 2017 +- Visual Studio 2015 +build_script: +- cmd: >- + if "Visual Studio 2019"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2017"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 + nmake -f makefile.msvc all +test_script: +- cmd: test.exe diff --git a/libtommath/bn_deprecated.c b/libtommath/bn_deprecated.c index 2056b20..fc19092 100644 --- a/libtommath/bn_deprecated.c +++ b/libtommath/bn_deprecated.c @@ -74,6 +74,12 @@ mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) return s_mp_balance_mul(a, b, c); } #endif +#ifdef BN_MP_DIV_3_C +mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) +{ + return s_mp_div_3(a, c, d); +} +#endif #ifdef BN_MP_EXPTMOD_FAST_C mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) { @@ -184,51 +190,88 @@ unsigned long mp_get_long(const mp_int *a) #ifdef BN_MP_GET_LONG_LONG_C unsigned long long mp_get_long_long(const mp_int *a) { - return mp_get_mag_ull(a); + return (unsigned long long)mp_get_mag_u64(a); } #endif +#ifdef BN_MP_GET_LL_C +MP_GET_SIGNED(mp_get_ll, mp_get_mag_u64, long long, uint64_t) +#endif +#ifdef BN_MP_GET_MAG_ULL_C +MP_GET_MAG(mp_get_mag_ull, unsigned long long) +#endif +#ifdef BN_MP_INIT_LL_C +MP_INIT_INT(mp_init_ll, mp_set_i64, long long) +#endif +#ifdef BN_MP_SET_LL_C +MP_SET_SIGNED(mp_set_ll, mp_set_i64, long long, long long) +#endif +#ifdef BN_MP_INIT_ULL_C +MP_INIT_INT(mp_init_ull, mp_set_u64, unsigned long long) +#endif +#ifdef BN_MP_SET_ULL_C +MP_SET_UNSIGNED(mp_set_ull, unsigned long long) +#endif #ifdef BN_MP_PRIME_IS_DIVISIBLE_C mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result) { return s_mp_prime_is_divisible(a, result); } #endif +#ifdef BN_MP_LOG_U32_C +mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) +{ + mp_err e; + int c_; + if (base > MP_MIN(MP_DIGIT_MAX, INT_MAX)) { + return MP_VAL; + } + e = mp_log_n(a, (int)base, &c_); + *c = (uint32_t)c_; + return e; +} +#endif #ifdef BN_MP_EXPT_D_EX_C mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) { (void)fast; - if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) { return MP_VAL; } - return mp_expt_u32(a, (uint32_t)b, c); + return mp_expt_n(a, (int)b, c); } #endif #ifdef BN_MP_EXPT_D_C mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) { - if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) { return MP_VAL; } - return mp_expt_u32(a, (uint32_t)b, c); + return mp_expt_n(a, (int)b, c); } #endif #ifdef BN_MP_N_ROOT_EX_C mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) { (void)fast; - if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) { return MP_VAL; } - return mp_root_u32(a, (uint32_t)b, c); + return mp_root_n(a, (int)b, c); } #endif #ifdef BN_MP_N_ROOT_C mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) { - if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) { return MP_VAL; } - return mp_root_u32(a, (uint32_t)b, c); + return mp_root_n(a, (int)b, c); +} +#endif +#ifdef BN_MP_ROOT_U32_C +mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) +{ + return mp_root_n(a, (int)b, c); } #endif #ifdef BN_MP_UNSIGNED_BIN_SIZE_C diff --git a/libtommath/bn_mp_div.c b/libtommath/bn_mp_div.c index bca227d..71de55b 100644 --- a/libtommath/bn_mp_div.c +++ b/libtommath/bn_mp_div.c @@ -31,7 +31,7 @@ mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) } /* init our temps */ - if ((err = mp_init_multi(&ta, &tb, &tq, &q, (void *)NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) { return err; } @@ -64,7 +64,7 @@ mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n; } LBL_ERR: - mp_clear_multi(&ta, &tb, &tq, &q, (void *)NULL); + mp_clear_multi(&ta, &tb, &tq, &q, NULL); return err; } diff --git a/libtommath/bn_mp_div_3.c b/libtommath/bn_mp_div_3.c deleted file mode 100644 index 3a23fdf..0000000 --- a/libtommath/bn_mp_div_3.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_DIV_3_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* divide by three (based on routine from MPI and the GMP manual) */ -mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) -{ - mp_int q; - mp_word w, t; - mp_digit b; - mp_err err; - int ix; - - /* b = 2**MP_DIGIT_BIT / 3 */ - b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3; - - if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { - return err; - } - - q.used = a->used; - q.sign = a->sign; - w = 0; - for (ix = a->used - 1; ix >= 0; ix--) { - w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; - - if (w >= 3u) { - /* multiply w by [1/3] */ - t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT; - - /* now subtract 3 * [w/3] from w, to get the remainder */ - w -= t+t+t; - - /* fixup the remainder as required since - * the optimization is not exact. - */ - while (w >= 3u) { - t += 1u; - w -= 3u; - } - } else { - t = 0; - } - q.dp[ix] = (mp_digit)t; - } - - /* [optional] store the remainder */ - if (d != NULL) { - *d = (mp_digit)w; - } - - /* [optional] store the quotient */ - if (c != NULL) { - mp_clamp(&q); - mp_exch(&q, c); - } - mp_clear(&q); - - return err; -} - -#endif diff --git a/libtommath/bn_mp_div_d.c b/libtommath/bn_mp_div_d.c index b9d718b..24a2c19 100644 --- a/libtommath/bn_mp_div_d.c +++ b/libtommath/bn_mp_div_d.c @@ -44,8 +44,8 @@ mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) } /* three? */ - if (MP_HAS(MP_DIV_3) && (b == 3u)) { - return mp_div_3(a, c, d); + if (MP_HAS(S_MP_DIV_3) && (b == 3u)) { + return s_mp_div_3(a, c, d); } /* no easy answer [c'est la vie]. Just division */ diff --git a/libtommath/bn_mp_expt_n.c b/libtommath/bn_mp_expt_n.c new file mode 100644 index 0000000..19c0225 --- /dev/null +++ b/libtommath/bn_mp_expt_n.c @@ -0,0 +1,53 @@ +#include "tommath_private.h" +#ifdef BN_MP_EXPT_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef BN_MP_EXPT_U32_C +mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) +{ + if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) { + return MP_VAL; + } + return mp_expt_n(a, (int)b, c); +} +#endif + +/* calculate c = a**b using a square-multiply algorithm */ +mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + mp_int g; + + if ((err = mp_init_copy(&g, a)) != MP_OKAY) { + return err; + } + + /* set initial result */ + mp_set(c, 1uL); + + while (b > 0) { + /* if the bit is set multiply */ + if ((b & 1) != 0) { + if ((err = mp_mul(c, &g, c)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* square */ + if (b > 1) { + if ((err = mp_sqr(&g, &g)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* shift to next bit */ + b >>= 1; + } + +LBL_ERR: + mp_clear(&g); + return err; +} + +#endif diff --git a/libtommath/bn_mp_expt_u32.c b/libtommath/bn_mp_expt_u32.c deleted file mode 100644 index 2ab67ba..0000000 --- a/libtommath/bn_mp_expt_u32.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_EXPT_U32_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* calculate c = a**b using a square-multiply algorithm */ -mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) -{ - mp_err err; - - mp_int g; - - if ((err = mp_init_copy(&g, a)) != MP_OKAY) { - return err; - } - - /* set initial result */ - mp_set(c, 1uL); - - while (b > 0u) { - /* if the bit is set multiply */ - if ((b & 1u) != 0u) { - if ((err = mp_mul(c, &g, c)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* square */ - if (b > 1u) { - if ((err = mp_sqr(&g, &g)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* shift to next bit */ - b >>= 1; - } - - err = MP_OKAY; - -LBL_ERR: - mp_clear(&g); - return err; -} - -#endif diff --git a/libtommath/bn_mp_get_ll.c b/libtommath/bn_mp_get_ll.c deleted file mode 100644 index 2687534..0000000 --- a/libtommath/bn_mp_get_ll.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_GET_LL_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -MP_GET_SIGNED(mp_get_ll, mp_get_mag_ull, long long, unsigned long long) -#endif diff --git a/libtommath/bn_mp_get_mag_ull.c b/libtommath/bn_mp_get_mag_ull.c deleted file mode 100644 index 63a2741..0000000 --- a/libtommath/bn_mp_get_mag_ull.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_GET_MAG_ULL_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -MP_GET_MAG(mp_get_mag_ull, unsigned long long) -#endif diff --git a/libtommath/bn_mp_init_ll.c b/libtommath/bn_mp_init_ll.c deleted file mode 100644 index dc7c4a4..0000000 --- a/libtommath/bn_mp_init_ll.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_INIT_LL_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -MP_INIT_INT(mp_init_ll, mp_set_ll, long long) -#endif diff --git a/libtommath/bn_mp_init_ull.c b/libtommath/bn_mp_init_ull.c deleted file mode 100644 index 84110c0..0000000 --- a/libtommath/bn_mp_init_ull.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_INIT_ULL_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -MP_INIT_INT(mp_init_ull, mp_set_ull, unsigned long long) -#endif diff --git a/libtommath/bn_mp_log_n.c b/libtommath/bn_mp_log_n.c new file mode 100644 index 0000000..d866fa0 --- /dev/null +++ b/libtommath/bn_mp_log_n.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef BN_MP_LOG_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_log_n(const mp_int *a, int base, int *c) +{ + if (mp_isneg(a) || mp_iszero(a) || (base < 2) || (unsigned)base > (unsigned)MP_DIGIT_MAX) { + return MP_VAL; + } + + if (MP_HAS(S_MP_LOG_2EXPT) && MP_IS_2EXPT((mp_digit)base)) { + *c = s_mp_log_2expt(a, (mp_digit)base); + return MP_OKAY; + } + + if (MP_HAS(S_MP_LOG_D) && (a->used == 1)) { + *c = s_mp_log_d((mp_digit)base, a->dp[0]); + return MP_OKAY; + } + + if (MP_HAS(S_MP_LOG)) { + return s_mp_log(a, (mp_digit)base, c); + } + + return MP_VAL; +} + +#endif diff --git a/libtommath/bn_mp_log_u32.c b/libtommath/bn_mp_log_u32.c deleted file mode 100644 index b86d789..0000000 --- a/libtommath/bn_mp_log_u32.c +++ /dev/null @@ -1,180 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_LOG_U32_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* Compute log_{base}(a) */ -static mp_word s_pow(mp_word base, mp_word exponent) -{ - mp_word result = 1u; - while (exponent != 0u) { - if ((exponent & 1u) == 1u) { - result *= base; - } - exponent >>= 1; - base *= base; - } - - return result; -} - -static mp_digit s_digit_ilogb(mp_digit base, mp_digit n) -{ - mp_word bracket_low = 1u, bracket_mid, bracket_high, N; - mp_digit ret, high = 1u, low = 0uL, mid; - - if (n < base) { - return 0uL; - } - if (n == base) { - return 1uL; - } - - bracket_high = (mp_word) base ; - N = (mp_word) n; - - while (bracket_high < N) { - low = high; - bracket_low = bracket_high; - high <<= 1; - bracket_high *= bracket_high; - } - - while (((mp_digit)(high - low)) > 1u) { - mid = (low + high) >> 1; - bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low)); - - if (N < bracket_mid) { - high = mid ; - bracket_high = bracket_mid ; - } - if (N > bracket_mid) { - low = mid ; - bracket_low = bracket_mid ; - } - if (N == bracket_mid) { - return (mp_digit) mid; - } - } - - if (bracket_high == N) { - ret = high; - } else { - ret = low; - } - - return ret; -} - -/* TODO: output could be "int" because the output of mp_radix_size is int, too, - as is the output of mp_bitcount. - With the same problem: max size is INT_MAX * MP_DIGIT not INT_MAX only! -*/ -mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) -{ - mp_err err; - mp_ord cmp; - uint32_t high, low, mid; - mp_int bracket_low, bracket_high, bracket_mid, t, bi_base; - - err = MP_OKAY; - - if (a->sign == MP_NEG) { - return MP_VAL; - } - - if (MP_IS_ZERO(a)) { - return MP_VAL; - } - - if (base < 2u) { - return MP_VAL; - } - - /* A small shortcut for bases that are powers of two. */ - if ((base & (base - 1u)) == 0u) { - int y, bit_count; - for (y=0; (y < 7) && ((base & 1u) == 0u); y++) { - base >>= 1; - } - bit_count = mp_count_bits(a) - 1; - *c = (uint32_t)(bit_count/y); - return MP_OKAY; - } - - if (a->used == 1) { - *c = (uint32_t)s_digit_ilogb(base, a->dp[0]); - return err; - } - - cmp = mp_cmp_d(a, base); - if ((cmp == MP_LT) || (cmp == MP_EQ)) { - *c = cmp == MP_EQ; - return err; - } - - if ((err = - mp_init_multi(&bracket_low, &bracket_high, - &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) { - return err; - } - - low = 0u; - mp_set(&bracket_low, 1uL); - high = 1u; - - mp_set(&bracket_high, base); - - /* - A kind of Giant-step/baby-step algorithm. - Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/ - The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped - for small n. - */ - while (mp_cmp(&bracket_high, a) == MP_LT) { - low = high; - if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) { - goto LBL_ERR; - } - high <<= 1; - if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) { - goto LBL_ERR; - } - } - mp_set(&bi_base, base); - - while ((high - low) > 1u) { - mid = (high + low) >> 1; - - if ((err = mp_expt_u32(&bi_base, (uint32_t)(mid - low), &t)) != MP_OKAY) { - goto LBL_ERR; - } - if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) { - goto LBL_ERR; - } - cmp = mp_cmp(a, &bracket_mid); - if (cmp == MP_LT) { - high = mid; - mp_exch(&bracket_mid, &bracket_high); - } - if (cmp == MP_GT) { - low = mid; - mp_exch(&bracket_mid, &bracket_low); - } - if (cmp == MP_EQ) { - *c = mid; - goto LBL_END; - } - } - - *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low; - -LBL_END: -LBL_ERR: - mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid, - &t, &bi_base, NULL); - return err; -} - - -#endif diff --git a/libtommath/bn_mp_mul.c b/libtommath/bn_mp_mul.c index c40feac..561913a 100644 --- a/libtommath/bn_mp_mul.c +++ b/libtommath/bn_mp_mul.c @@ -12,14 +12,12 @@ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) digs = a->used + b->used + 1; mp_sign neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - if (a == b) { - return mp_sqr(a,c); - } else if (MP_HAS(S_MP_BALANCE_MUL) && + if (MP_HAS(S_MP_BALANCE_MUL) && /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger * to make some sense, but it depends on architecture, OS, position of the * stars... so YMMV. - * Using it to cut the input into slices small enough for s_mp_mul_digs_fast + * Using it to cut the input into slices small enough for fast_s_mp_mul_digs * was actually slower on the author's machine, but YMMV. */ (min_len >= MP_KARATSUBA_MUL_CUTOFF) && diff --git a/libtommath/bn_mp_prime_rand.c b/libtommath/bn_mp_prime_rand.c index 4530e9a..b931569 100644 --- a/libtommath/bn_mp_prime_rand.c +++ b/libtommath/bn_mp_prime_rand.c @@ -36,7 +36,10 @@ mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_pr } /* calc the byte size */ - bsize = (size>>3) + ((size&7)?1:0); + bsize = (size>>3); + if (size&7) { + bsize++; + } /* we need a buffer of bsize bytes */ tmp = (unsigned char *) MP_MALLOC((size_t)bsize); diff --git a/libtommath/bn_mp_root_n.c b/libtommath/bn_mp_root_n.c new file mode 100644 index 0000000..5b92ff5 --- /dev/null +++ b/libtommath/bn_mp_root_n.c @@ -0,0 +1,141 @@ +#include "tommath_private.h" +#ifdef BN_MP_ROOT_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* find the n'th root of an integer + * + * Result found such that (c)**b <= a and (c+1)**b > a + * + * This algorithm uses Newton's approximation + * x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where + * each step involves a fair bit. + */ +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) +{ + mp_int t1, t2, t3, a_; + int ilog2; + mp_err err; + + if (b < 0 || (unsigned)b > (unsigned)MP_DIGIT_MAX) { + return MP_VAL; + } + + /* input must be positive if b is even */ + if (((b & 1) == 0) && mp_isneg(a)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { + return err; + } + + /* if a is negative fudge the sign but keep track */ + a_ = *a; + a_.sign = MP_ZPOS; + + /* Compute seed: 2^(log_2(n)/b + 2)*/ + ilog2 = mp_count_bits(a); + + /* + If "b" is larger than INT_MAX it is also larger than + log_2(n) because the bit-length of the "n" is measured + with an int and hence the root is always < 2 (two). + */ + if (b > INT_MAX/2) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + + /* "b" is smaller than INT_MAX, we can cast safely */ + if (ilog2 < b) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + ilog2 = ilog2 / b; + if (ilog2 == 0) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + /* Start value must be larger than root */ + ilog2 += 2; + if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR; + do { + /* t1 = t2 */ + if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((err = mp_expt_n(&t1, b - 1, &t3)) != MP_OKAY) goto LBL_ERR; + + /* numerator */ + /* t2 = t1**b */ + if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1**b - a */ + if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR; + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((err = mp_mul_d(&t3, (mp_digit)b, &t3)) != MP_OKAY) goto LBL_ERR; + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR; + + /* + Number of rounds is at most log_2(root). If it is more it + got stuck, so break out of the loop and do the rest manually. + */ + if (ilog2-- == 0) { + break; + } + } while (mp_cmp(&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + /* Loop beneath can overshoot by one if found root is smaller than actual root */ + for (;;) { + mp_ord cmp; + if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + cmp = mp_cmp(&t2, &a_); + if (cmp == MP_EQ) { + err = MP_OKAY; + goto LBL_ERR; + } + if (cmp == MP_LT) { + if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + /* correct overshoot from above or from recurrence */ + for (;;) { + if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + if (mp_cmp(&t2, &a_) == MP_GT) { + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + + /* set the result */ + mp_exch(&t1, c); + + /* set the sign of the result */ + c->sign = a->sign; + +LBL_ERR: + mp_clear_multi(&t1, &t2, &t3, NULL); + return err; +} + +#endif diff --git a/libtommath/bn_mp_root_u32.c b/libtommath/bn_mp_root_u32.c deleted file mode 100644 index ba65549..0000000 --- a/libtommath/bn_mp_root_u32.c +++ /dev/null @@ -1,139 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_ROOT_U32_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -/* find the n'th root of an integer - * - * Result found such that (c)**b <= a and (c+1)**b > a - * - * This algorithm uses Newton's approximation - * x[i+1] = x[i] - f(x[i])/f'(x[i]) - * which will find the root in log(N) time where - * each step involves a fair bit. - */ -mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) -{ - mp_int t1, t2, t3, a_; - mp_ord cmp; - int ilog2; - mp_err err; - - /* input must be positive if b is even */ - if (((b & 1u) == 0u) && (a->sign == MP_NEG)) { - return MP_VAL; - } - - if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { - return err; - } - - /* if a is negative fudge the sign but keep track */ - a_ = *a; - a_.sign = MP_ZPOS; - - /* Compute seed: 2^(log_2(n)/b + 2)*/ - ilog2 = mp_count_bits(a); - - /* - If "b" is larger than INT_MAX it is also larger than - log_2(n) because the bit-length of the "n" is measured - with an int and hence the root is always < 2 (two). - */ - if (b > (uint32_t)(INT_MAX/2)) { - mp_set(c, 1uL); - c->sign = a->sign; - err = MP_OKAY; - goto LBL_ERR; - } - - /* "b" is smaller than INT_MAX, we can cast safely */ - if (ilog2 < (int)b) { - mp_set(c, 1uL); - c->sign = a->sign; - err = MP_OKAY; - goto LBL_ERR; - } - ilog2 = ilog2 / ((int)b); - if (ilog2 == 0) { - mp_set(c, 1uL); - c->sign = a->sign; - err = MP_OKAY; - goto LBL_ERR; - } - /* Start value must be larger than root */ - ilog2 += 2; - if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR; - do { - /* t1 = t2 */ - if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR; - - /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ - - /* t3 = t1**(b-1) */ - if ((err = mp_expt_u32(&t1, b - 1u, &t3)) != MP_OKAY) goto LBL_ERR; - - /* numerator */ - /* t2 = t1**b */ - if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR; - - /* t2 = t1**b - a */ - if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR; - - /* denominator */ - /* t3 = t1**(b-1) * b */ - if ((err = mp_mul_d(&t3, b, &t3)) != MP_OKAY) goto LBL_ERR; - - /* t3 = (t1**b - a)/(b * t1**(b-1)) */ - if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR; - - if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR; - - /* - Number of rounds is at most log_2(root). If it is more it - got stuck, so break out of the loop and do the rest manually. - */ - if (ilog2-- == 0) { - break; - } - } while (mp_cmp(&t1, &t2) != MP_EQ); - - /* result can be off by a few so check */ - /* Loop beneath can overshoot by one if found root is smaller than actual root */ - for (;;) { - if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; - cmp = mp_cmp(&t2, &a_); - if (cmp == MP_EQ) { - err = MP_OKAY; - goto LBL_ERR; - } - if (cmp == MP_LT) { - if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; - } else { - break; - } - } - /* correct overshoot from above or from recurrence */ - for (;;) { - if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; - if (mp_cmp(&t2, &a_) == MP_GT) { - if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; - } else { - break; - } - } - - /* set the result */ - mp_exch(&t1, c); - - /* set the sign of the result */ - c->sign = a->sign; - - err = MP_OKAY; - -LBL_ERR: - mp_clear_multi(&t1, &t2, &t3, NULL); - return err; -} - -#endif diff --git a/libtommath/bn_mp_set_double.c b/libtommath/bn_mp_set_double.c index 7f1ab75..a42fc70 100644 --- a/libtommath/bn_mp_set_double.c +++ b/libtommath/bn_mp_set_double.c @@ -16,7 +16,7 @@ mp_err mp_set_double(mp_int *a, double b) cast.dbl = b; exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu); - frac = (cast.bits & (((uint64_t)1 << 52) - (uint64_t)1)) | ((uint64_t)1 << 52); + frac = (cast.bits & ((1uLL << 52) - 1uLL)) | (1uLL << 52); if (exp == 0x7FF) { /* +-inf, NaN */ return MP_VAL; @@ -30,7 +30,7 @@ mp_err mp_set_double(mp_int *a, double b) return err; } - if (((cast.bits >> 63) != 0u) && !MP_IS_ZERO(a)) { + if (((cast.bits >> 63) != 0uLL) && !MP_IS_ZERO(a)) { a->sign = MP_NEG; } diff --git a/libtommath/bn_mp_set_ll.c b/libtommath/bn_mp_set_ll.c deleted file mode 100644 index 3e2324f..0000000 --- a/libtommath/bn_mp_set_ll.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_SET_LL_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -MP_SET_SIGNED(mp_set_ll, mp_set_ull, long long, unsigned long long) -#endif diff --git a/libtommath/bn_mp_set_ull.c b/libtommath/bn_mp_set_ull.c deleted file mode 100644 index 8fbc1bd..0000000 --- a/libtommath/bn_mp_set_ull.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tommath_private.h" -#ifdef BN_MP_SET_ULL_C -/* LibTomMath, multiple-precision integer library -- Tom St Denis */ -/* SPDX-License-Identifier: Unlicense */ - -MP_SET_UNSIGNED(mp_set_ull, unsigned long long) -#endif diff --git a/libtommath/bn_mp_sqrt.c b/libtommath/bn_mp_sqrt.c index dcf28fd..82d6824 100644 --- a/libtommath/bn_mp_sqrt.c +++ b/libtommath/bn_mp_sqrt.c @@ -3,24 +3,11 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ -#ifndef NO_FLOATING_POINT -#include -#include -#if (MP_DIGIT_BIT != 28) || (FLT_RADIX != 2) || (DBL_MANT_DIG != 53) || (DBL_MAX_EXP != 1024) -#define NO_FLOATING_POINT -#endif -#endif - /* this function is less generic than mp_n_root, simpler and faster */ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) { mp_err err; mp_int t1, t2; -#ifndef NO_FLOATING_POINT - int i, j, k; - volatile double d; - mp_digit dig; -#endif /* must be positive */ if (arg->sign == MP_NEG) { @@ -33,64 +20,6 @@ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) return MP_OKAY; } -#ifndef NO_FLOATING_POINT - - i = (arg->used / 2) - 1; - j = 2 * i; - if ((err = mp_init_size(&t1, i+2)) != MP_OKAY) { - return err; - } - - if ((err = mp_init(&t2)) != MP_OKAY) { - goto E2; - } - - for (k = 0; k < i; ++k) { - t1.dp[k] = (mp_digit) 0; - } - - /* Estimate the square root using the hardware floating point unit. */ - - d = 0.0; - for (k = arg->used-1; k >= j; --k) { - d = ldexp(d, MP_DIGIT_BIT) + (double)(arg->dp[k]); - } - - /* - * At this point, d is the nearest floating point number to the most - * significant 1 or 2 mp_digits of arg. Extract its square root. - */ - - d = sqrt(d); - - /* dig is the most significant mp_digit of the square root */ - - dig = (mp_digit) ldexp(d, -MP_DIGIT_BIT); - - /* - * If the most significant digit is nonzero, find the next digit down - * by subtracting MP_DIGIT_BIT times thie most significant digit. - * Subtract one from the result so that our initial estimate is always - * low. - */ - - if (dig) { - t1.used = i+2; - d -= ldexp((double) dig, MP_DIGIT_BIT); - if (d >= 1.0) { - t1.dp[i+1] = dig; - t1.dp[i] = ((mp_digit) d) - 1; - } else { - t1.dp[i+1] = dig-1; - t1.dp[i] = MP_DIGIT_MAX; - } - } else { - t1.used = i+1; - t1.dp[i] = ((mp_digit) d) - 1; - } - -#else - if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { return err; } @@ -102,8 +31,6 @@ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) /* First approx. (not very bad for large arg) */ mp_rshd(&t1, t1.used/2); -#endif - /* t1 > 0 */ if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { goto E1; diff --git a/libtommath/bn_s_mp_balance_mul.c b/libtommath/bn_s_mp_balance_mul.c index 557cc1d..7ece5d7 100644 --- a/libtommath/bn_s_mp_balance_mul.c +++ b/libtommath/bn_s_mp_balance_mul.c @@ -19,7 +19,7 @@ mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) { return err; } - if ((err = mp_init_multi(&tmp, &r, (void *)NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) { mp_clear(&a0); return err; } @@ -75,7 +75,7 @@ mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) mp_exch(&r,c); LBL_ERR: - mp_clear_multi(&a0, &tmp, &r, (void *)NULL); + mp_clear_multi(&a0, &tmp, &r,NULL); return err; } #endif diff --git a/libtommath/bn_s_mp_div_3.c b/libtommath/bn_s_mp_div_3.c new file mode 100644 index 0000000..e0aeefc --- /dev/null +++ b/libtommath/bn_s_mp_div_3.c @@ -0,0 +1,63 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_DIV_3_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* divide by three (based on routine from MPI and the GMP manual) */ +mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w, t; + mp_digit b; + mp_err err; + int ix; + + /* b = 2**MP_DIGIT_BIT / 3 */ + b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3; + + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; + + if (w >= 3u) { + /* multiply w by [1/3] */ + t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT; + + /* now subtract 3 * [w/3] from w, to get the remainder */ + w -= t+t+t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3u) { + t += 1u; + w -= 3u; + } + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + /* [optional] store the remainder */ + if (d != NULL) { + *d = (mp_digit)w; + } + + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return err; +} + +#endif diff --git a/libtommath/bn_s_mp_log.c b/libtommath/bn_s_mp_log.c new file mode 100644 index 0000000..a75212a --- /dev/null +++ b/libtommath/bn_s_mp_log.c @@ -0,0 +1,81 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_LOG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err s_mp_log(const mp_int *a, mp_digit base, int *c) +{ + mp_err err; + int high, low; + mp_int bracket_low, bracket_high, bracket_mid, t, bi_base; + + mp_ord cmp = mp_cmp_d(a, base); + if ((cmp == MP_LT) || (cmp == MP_EQ)) { + *c = cmp == MP_EQ; + return MP_OKAY; + } + + if ((err = + mp_init_multi(&bracket_low, &bracket_high, + &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) { + return err; + } + + low = 0; + mp_set(&bracket_low, 1uL); + high = 1; + + mp_set(&bracket_high, base); + + /* + A kind of Giant-step/baby-step algorithm. + Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/ + The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped + for small n. + */ + while (mp_cmp(&bracket_high, a) == MP_LT) { + low = high; + if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) { + goto LBL_END; + } + high <<= 1; + if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) { + goto LBL_END; + } + } + mp_set(&bi_base, base); + + while ((high - low) > 1) { + int mid = (high + low) >> 1; + + if ((err = mp_expt_n(&bi_base, mid - low, &t)) != MP_OKAY) { + goto LBL_END; + } + if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) { + goto LBL_END; + } + cmp = mp_cmp(a, &bracket_mid); + if (cmp == MP_LT) { + high = mid; + mp_exch(&bracket_mid, &bracket_high); + } + if (cmp == MP_GT) { + low = mid; + mp_exch(&bracket_mid, &bracket_low); + } + if (cmp == MP_EQ) { + *c = mid; + goto LBL_END; + } + } + + *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low; + +LBL_END: + mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid, + &t, &bi_base, NULL); + return err; +} + + +#endif diff --git a/libtommath/bn_s_mp_log_2expt.c b/libtommath/bn_s_mp_log_2expt.c new file mode 100644 index 0000000..e87ff35 --- /dev/null +++ b/libtommath/bn_s_mp_log_2expt.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_LOG_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +int s_mp_log_2expt(const mp_int *a, mp_digit base) +{ + int y; + for (y = 0; (base & 1) == 0; y++, base >>= 1) {} + return (mp_count_bits(a) - 1) / y; +} +#endif diff --git a/libtommath/bn_s_mp_log_d.c b/libtommath/bn_s_mp_log_d.c new file mode 100644 index 0000000..181d984 --- /dev/null +++ b/libtommath/bn_s_mp_log_d.c @@ -0,0 +1,65 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_LOG_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static mp_word s_pow(mp_word base, mp_word exponent) +{ + mp_word result = 1u; + while (exponent != 0u) { + if ((exponent & 1u) == 1u) { + result *= base; + } + exponent >>= 1; + base *= base; + } + + return result; +} + +int s_mp_log_d(mp_digit base, mp_digit n) +{ + mp_word bracket_low = 1uLL, bracket_high = base, N = n; + int ret, high = 1, low = 0; + + if (n < base) { + return 0; + } + if (n == base) { + return 1; + } + + while (bracket_high < N) { + low = high; + bracket_low = bracket_high; + high <<= 1; + bracket_high *= bracket_high; + } + + while (((mp_digit)(high - low)) > 1uL) { + int mid = (low + high) >> 1; + mp_word bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low)); + + if (N < bracket_mid) { + high = mid ; + bracket_high = bracket_mid ; + } + if (N > bracket_mid) { + low = mid ; + bracket_low = bracket_mid ; + } + if (N == bracket_mid) { + return mid; + } + } + + if (bracket_high == N) { + ret = high; + } else { + ret = low; + } + + return ret; +} + +#endif diff --git a/libtommath/bn_s_mp_mul_high_digs_fast.c b/libtommath/bn_s_mp_mul_high_digs_fast.c index 0796f72..4ce7f59 100644 --- a/libtommath/bn_s_mp_mul_high_digs_fast.c +++ b/libtommath/bn_s_mp_mul_high_digs_fast.c @@ -3,8 +3,8 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ -/* this is a modified version of s_mp_mul_digs_fast that only produces - * output digits *above* digs. See the comments for s_mp_mul_digs_fast +/* this is a modified version of fast_s_mul_digs that only produces + * output digits *above* digs. See the comments for fast_s_mul_digs * to see how it works. * * This is used in the Barrett reduction since for one of the multiplications diff --git a/libtommath/bn_s_mp_rand_jenkins.c b/libtommath/bn_s_mp_rand_jenkins.c index c64afac..da0771c 100644 --- a/libtommath/bn_s_mp_rand_jenkins.c +++ b/libtommath/bn_s_mp_rand_jenkins.c @@ -27,10 +27,10 @@ static uint64_t s_rand_jenkins_val(void) void s_mp_rand_jenkins_init(uint64_t seed) { - int i; + uint64_t i; jenkins_x.a = 0xf1ea5eedULL; jenkins_x.b = jenkins_x.c = jenkins_x.d = seed; - for (i = 0; i < 20; ++i) { + for (i = 0uLL; i < 20uLL; ++i) { (void)s_rand_jenkins_val(); } } diff --git a/libtommath/bn_s_mp_toom_mul.c b/libtommath/bn_s_mp_toom_mul.c index c7db3a5..eefce6c 100644 --- a/libtommath/bn_s_mp_toom_mul.c +++ b/libtommath/bn_s_mp_toom_mul.c @@ -36,7 +36,7 @@ mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) mp_err err; /* init temps */ - if ((err = mp_init_multi(&S1, &S2, &T1, (void *)NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&S1, &S2, &T1, NULL)) != MP_OKAY) { return err; } @@ -146,7 +146,7 @@ mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; /** S2 = S2 / 3; \\ this is an exact division */ - if ((err = mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; + if ((err = s_mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; /** a1 = S1 - a1; */ if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR; @@ -208,7 +208,7 @@ LBL_ERRa2: LBL_ERRa1: mp_clear(&a0); LBL_ERRa0: - mp_clear_multi(&S1, &S2, &T1, (void *)NULL); + mp_clear_multi(&S1, &S2, &T1, NULL); return err; } diff --git a/libtommath/changes.txt b/libtommath/changes.txt index 956cdd4..80ff7dd 100644 --- a/libtommath/changes.txt +++ b/libtommath/changes.txt @@ -1,3 +1,9 @@ +Mar 27th, 2024 +v1.3.0 + -- Deprecate more APIs which are replaced in develop (PR #572) + -- Add support for CMake (PR #573) + -- Add support for GitHub Actions (PR #573) + Sep 04th, 2023 v1.2.1 -- Bugfix release because of potential integer overflow @@ -417,7 +423,7 @@ v0.13 -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which p Jan 17th, 2003 v0.12 -- re-wrote the majority of the makefile so its more portable and will install via "make install" on most *nix platforms - -- Re-packaged all the source as separate files. Means the library a single + -- Re-packaged all the source as seperate files. Means the library a single file packagage any more. Instead of just adding "bn.c" you have to add libtommath.a -- Renamed "bn.h" to "tommath.h" diff --git a/libtommath/helper.pl b/libtommath/helper.pl index c624b7c..6366d04 100755 --- a/libtommath/helper.pl +++ b/libtommath/helper.pl @@ -51,7 +51,7 @@ sub check_source { push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i; push @{$troubles->{non_ascii_char}}, $lineno if $l =~ /[^[:ascii:]]/; push @{$troubles->{cpp_comment}}, $lineno if $file =~ /\.(c|h)$/ && ($l =~ /\s\/\// || $l =~ /\/\/\s/); - # we prefer using MP_MALLOC, MP_FREE, MP_REALLOC, MP_CALLOC ... + # we prefer using XMALLOC, XFREE, XREALLOC, XCALLOC ... push @{$troubles->{unwanted_malloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmalloc\s*\(/; push @{$troubles->{unwanted_realloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\brealloc\s*\(/; push @{$troubles->{unwanted_calloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bcalloc\s*\(/; @@ -222,11 +222,32 @@ sub patch_file { return $content; } +sub make_sources_cmake { + my ($src_ref, $hdr_ref) = @_; + my @sources = @{ $src_ref }; + my @headers = @{ $hdr_ref }; + my $output = "# SPDX-License-Identifier: Unlicense +# Autogenerated File! Do not edit. + +set(SOURCES\n"; + foreach my $sobj (sort @sources) { + $output .= $sobj . "\n"; + } + $output .= ")\n\nset(HEADERS\n"; + foreach my $hobj (sort @headers) { + $output .= $hobj . "\n"; + } + $output .= ")\n"; + return $output; +} + sub process_makefiles { my $write = shift; my $changed_count = 0; - my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } bsd_glob("*.c"); - my @all = bsd_glob("*.{c,h}"); + my @headers = bsd_glob("*.h"); + my @sources = bsd_glob("*.c"); + my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } @sources; + my @all = sort(@sources, @headers); my $var_o = prepare_variable("OBJECTS", @o); (my $var_obj = $var_o) =~ s/\.o\b/.obj/sg; @@ -245,10 +266,12 @@ sub process_makefiles { } # update OBJECTS + HEADERS in makefile* - for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw /) { + for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw sources.cmake /) { my $old = read_file($m); my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj) - : patch_file($old, $var_o); + : $m eq 'sources.cmake' ? make_sources_cmake(\@sources, \@headers) + : patch_file($old, $var_o); + if ($old ne $new) { write_file($m, $new) if $write; warn "changed: $m\n"; @@ -389,6 +412,11 @@ EOS push @deps, $a; } } + if ($filename =~ "BN_DEPRECATED") { + push(@deps, qw(BN_MP_GET_LL_C BN_MP_INIT_LL_C BN_MP_SET_LL_C)); + push(@deps, qw(BN_MP_GET_MAG_ULL_C BN_MP_INIT_ULL_C BN_MP_SET_ULL_C)); + push(@deps, qw(BN_MP_DIV_3_C BN_MP_EXPT_U32_C BN_MP_ROOT_U32_C BN_MP_LOG_U32_C)); + } @deps = sort(@deps); foreach my $a (@deps) { if ($list !~ /$a/) { @@ -435,6 +463,8 @@ sub generate_def { @files = grep(!/mp_radix_smap/, @files); push(@files, qw(mp_set_int mp_set_long mp_set_long_long mp_get_int mp_get_long mp_get_long_long mp_init_set_int)); + push(@files, qw(mp_get_ll mp_get_mag_ull mp_init_ll mp_set_ll mp_init_ull mp_set_ull)); + push(@files, qw(mp_div_3 mp_expt_u32 mp_root_u32 mp_log_u32)); my $files = join("\n ", sort(grep(/^mp_/, @files))); write_file "tommath.def", "; libtommath diff --git a/libtommath/libtommath.pc.in b/libtommath/libtommath.pc.in index 099b1cd..7ce50fd 100644 --- a/libtommath/libtommath.pc.in +++ b/libtommath/libtommath.pc.in @@ -1,10 +1,9 @@ -prefix=@to-be-replaced@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include +prefix=@CMAKE_INSTALL_PREFIX@ +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: LibTomMath Description: public domain library for manipulating large integer numbers -Version: @to-be-replaced@ +Version: @PROJECT_VERSION@ Libs: -L${libdir} -ltommath Cflags: -I${includedir} diff --git a/libtommath/libtommath_VS2008.sln b/libtommath/libtommath_VS2008.sln index 3bd6688..6bfc159 100644 --- a/libtommath/libtommath_VS2008.sln +++ b/libtommath/libtommath_VS2008.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tommath", "libtommath_VS2008.vcproj", "{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}" diff --git a/libtommath/libtommath_VS2008.vcproj b/libtommath/libtommath_VS2008.vcproj index 67cc89b..5cbbb89 100644 --- a/libtommath/libtommath_VS2008.vcproj +++ b/libtommath/libtommath_VS2008.vcproj @@ -401,10 +401,6 @@ > - - @@ -429,7 +425,7 @@ > - - @@ -493,10 +485,6 @@ > - - @@ -525,10 +513,6 @@ > - - @@ -553,10 +537,6 @@ > - - @@ -581,7 +561,7 @@ > - - @@ -777,10 +753,6 @@ > - - @@ -857,6 +829,10 @@ > + + @@ -885,6 +861,18 @@ > + + + + + + diff --git a/libtommath/makefile b/libtommath/makefile index be9fac6..bee51a1 100644 --- a/libtommath/makefile +++ b/libtommath/makefile @@ -29,32 +29,32 @@ LCOV_ARGS=--directory . OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ -bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ -bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ -bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ -bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ -bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ -bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ -bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ -bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ -bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ -bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ -bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ -bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ -bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ -bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ -bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ -bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ -bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ -bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ -bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ -bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ -bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ -bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ -bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ -bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ -bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ +bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ +bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ +bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ +bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ +bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ +bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ +bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ +bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ +bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ +bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ +bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ +bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ +bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ +bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ +bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ +bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ +bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ +bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ +bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o #END_INS @@ -133,7 +133,11 @@ pre_gen: sed -e 's/[[:blank:]]*$$//' mpi.c > pre_gen/mpi.c rm mpi.c -zipup: clean astyle new_file docs +zipup: + $(MAKE) clean + $(MAKE) .zipup + +.zipup: astyle new_file docs @# Update the index, so diff-index won't fail in case the pdf has been created. @# As the pdf creation modifies the tex files, git sometimes detects the @# modified files, but misses that it's put back to its original version. diff --git a/libtommath/makefile.mingw b/libtommath/makefile.mingw index 7eee57d..d05d84d 100644 --- a/libtommath/makefile.mingw +++ b/libtommath/makefile.mingw @@ -11,16 +11,20 @@ #The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs PREFIX = c:\mingw -CC = gcc +CC = i686-w64-mingw32-gcc +#CC = x86_64-w64-mingw32-clang +#CC = aarch64-w64-mingw32-clang AR = ar ARFLAGS = r RANLIB = ranlib -STRIP = strip +STRIP = i686-w64-mingw32-gcc-strip +#STRIP = x86_64-w64-mingw32-strip +#STRIP = aarch64-w64-mingw32-strip CFLAGS = -O2 LDFLAGS = #Compilation flags -LTM_CFLAGS = -I. $(CFLAGS) +LTM_CFLAGS = -I. $(CFLAGS) -DTCL_WITH_EXTERNAL_TOMMATH LTM_LDFLAGS = $(LDFLAGS) -static-libgcc #Libraries to be created @@ -32,32 +36,32 @@ LIBMAIN_D =libtommath.dll OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ -bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ -bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ -bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ -bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ -bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ -bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ -bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ -bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ -bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ -bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ -bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ -bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ -bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ -bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ -bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ -bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ -bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ -bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ -bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ -bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ -bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ -bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ -bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ -bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ -bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ +bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ +bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ +bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ +bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ +bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ +bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ +bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ +bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ +bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ +bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ +bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ +bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ +bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ +bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ +bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ +bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ +bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ +bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ +bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) @@ -78,7 +82,7 @@ $(LIBMAIN_S): $(OBJECTS) #Create DLL + import library libtommath.dll.a $(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS) - $(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import,--export-all -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS) + $(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import tommath.def -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS) $(STRIP) -S $(LIBMAIN_D) #Build test suite diff --git a/libtommath/makefile.msvc b/libtommath/makefile.msvc index aa8d8be..a78080b 100644 --- a/libtommath/makefile.msvc +++ b/libtommath/makefile.msvc @@ -24,32 +24,32 @@ LIBMAIN_S =tommath.lib OBJECTS=bn_cutoffs.obj bn_deprecated.obj bn_mp_2expt.obj bn_mp_abs.obj bn_mp_add.obj bn_mp_add_d.obj bn_mp_addmod.obj \ bn_mp_and.obj bn_mp_clamp.obj bn_mp_clear.obj bn_mp_clear_multi.obj bn_mp_cmp.obj bn_mp_cmp_d.obj bn_mp_cmp_mag.obj \ bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_decr.obj bn_mp_div.obj bn_mp_div_2.obj \ -bn_mp_div_2d.obj bn_mp_div_3.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj bn_mp_dr_setup.obj \ -bn_mp_error_to_string.obj bn_mp_exch.obj bn_mp_expt_u32.obj bn_mp_exptmod.obj bn_mp_exteuclid.obj bn_mp_fread.obj \ +bn_mp_div_2d.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj bn_mp_dr_setup.obj \ +bn_mp_error_to_string.obj bn_mp_exch.obj bn_mp_expt_n.obj bn_mp_exptmod.obj bn_mp_exteuclid.obj bn_mp_fread.obj \ bn_mp_from_sbin.obj bn_mp_from_ubin.obj bn_mp_fwrite.obj bn_mp_gcd.obj bn_mp_get_double.obj bn_mp_get_i32.obj \ -bn_mp_get_i64.obj bn_mp_get_l.obj bn_mp_get_ll.obj bn_mp_get_mag_u32.obj bn_mp_get_mag_u64.obj bn_mp_get_mag_ul.obj \ -bn_mp_get_mag_ull.obj bn_mp_grow.obj bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_i32.obj \ -bn_mp_init_i64.obj bn_mp_init_l.obj bn_mp_init_ll.obj bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_size.obj \ -bn_mp_init_u32.obj bn_mp_init_u64.obj bn_mp_init_ul.obj bn_mp_init_ull.obj bn_mp_invmod.obj bn_mp_is_square.obj \ -bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_log_u32.obj bn_mp_lshd.obj bn_mp_mod.obj \ -bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj bn_mp_montgomery_reduce.obj \ -bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj bn_mp_mulmod.obj bn_mp_neg.obj \ -bn_mp_or.obj bn_mp_pack.obj bn_mp_pack_count.obj bn_mp_prime_fermat.obj bn_mp_prime_frobenius_underwood.obj \ -bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj bn_mp_prime_next_prime.obj \ -bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj bn_mp_prime_strong_lucas_selfridge.obj \ -bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj bn_mp_read_radix.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj \ -bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj \ -bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj bn_mp_root_u32.obj bn_mp_rshd.obj bn_mp_sbin_size.obj bn_mp_set.obj \ -bn_mp_set_double.obj bn_mp_set_i32.obj bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_ll.obj bn_mp_set_u32.obj \ -bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_set_ull.obj bn_mp_shrink.obj bn_mp_signed_rsh.obj bn_mp_sqr.obj \ -bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj bn_mp_submod.obj \ -bn_mp_to_radix.obj bn_mp_to_sbin.obj bn_mp_to_ubin.obj bn_mp_ubin_size.obj bn_mp_unpack.obj bn_mp_xor.obj bn_mp_zero.obj \ -bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj \ -bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj bn_s_mp_karatsuba_mul.obj \ -bn_s_mp_karatsuba_sqr.obj bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj \ -bn_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj \ -bn_s_mp_rand_jenkins.obj bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj \ -bn_s_mp_sub.obj bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj +bn_mp_get_i64.obj bn_mp_get_l.obj bn_mp_get_mag_u32.obj bn_mp_get_mag_u64.obj bn_mp_get_mag_ul.obj bn_mp_grow.obj \ +bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_i32.obj bn_mp_init_i64.obj bn_mp_init_l.obj \ +bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_size.obj bn_mp_init_u32.obj bn_mp_init_u64.obj bn_mp_init_ul.obj \ +bn_mp_invmod.obj bn_mp_is_square.obj bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_log_n.obj \ +bn_mp_lshd.obj bn_mp_mod.obj bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj \ +bn_mp_montgomery_reduce.obj bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj \ +bn_mp_mulmod.obj bn_mp_neg.obj bn_mp_or.obj bn_mp_pack.obj bn_mp_pack_count.obj bn_mp_prime_fermat.obj \ +bn_mp_prime_frobenius_underwood.obj bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj \ +bn_mp_prime_next_prime.obj bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj \ +bn_mp_prime_strong_lucas_selfridge.obj bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj \ +bn_mp_read_radix.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj \ +bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj \ +bn_mp_root_n.obj bn_mp_rshd.obj bn_mp_sbin_size.obj bn_mp_set.obj bn_mp_set_double.obj bn_mp_set_i32.obj \ +bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_u32.obj bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_shrink.obj \ +bn_mp_signed_rsh.obj bn_mp_sqr.obj bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj \ +bn_mp_submod.obj bn_mp_to_radix.obj bn_mp_to_sbin.obj bn_mp_to_ubin.obj bn_mp_ubin_size.obj bn_mp_unpack.obj \ +bn_mp_xor.obj bn_mp_zero.obj bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_div_3.obj \ +bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj \ +bn_s_mp_karatsuba_mul.obj bn_s_mp_karatsuba_sqr.obj bn_s_mp_log.obj bn_s_mp_log_2expt.obj bn_s_mp_log_d.obj \ +bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj bn_s_mp_mul_high_digs.obj \ +bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj bn_s_mp_rand_jenkins.obj \ +bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj bn_s_mp_sub.obj \ +bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) diff --git a/libtommath/makefile.shared b/libtommath/makefile.shared index 6802107..bf0ee43 100644 --- a/libtommath/makefile.shared +++ b/libtommath/makefile.shared @@ -26,32 +26,32 @@ LCOV_ARGS=--directory .libs --directory . OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ -bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ -bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ -bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ -bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ -bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ -bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ -bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ -bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ -bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ -bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ -bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ -bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ -bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ -bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ -bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ -bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ -bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ -bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ -bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ -bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ -bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ -bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ -bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ -bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ -bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ +bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ +bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ +bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ +bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ +bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ +bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ +bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ +bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ +bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ +bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ +bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ +bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ +bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ +bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ +bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ +bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ +bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ +bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ +bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o #END_INS @@ -70,7 +70,8 @@ install: $(LIBNAME) install -d $(DESTDIR)$(INCPATH) $(LIBTOOL) --mode=install install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) install -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH) - sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' libtommath.pc.in > libtommath.pc + sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' -e 's,@CMAKE_INSTALL_LIBDIR@,lib,' \ + -e 's,@CMAKE_INSTALL_INCLUDEDIR@,include,' libtommath.pc.in > libtommath.pc install -d $(DESTDIR)$(LIBPATH)/pkgconfig install -m 644 libtommath.pc $(DESTDIR)$(LIBPATH)/pkgconfig/ diff --git a/libtommath/makefile.unix b/libtommath/makefile.unix index 9336da0..fdc3fa7 100644 --- a/libtommath/makefile.unix +++ b/libtommath/makefile.unix @@ -21,7 +21,7 @@ RANLIB = ranlib CFLAGS = -O2 LDFLAGS = -VERSION = 1.2.1 +VERSION = 1.3.0 #Compilation flags LTM_CFLAGS = -I. $(CFLAGS) @@ -33,32 +33,32 @@ LIBMAIN_S = libtommath.a OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ -bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ -bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ -bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ -bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ -bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ -bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ -bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ -bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ -bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ -bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ -bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ -bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ -bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ -bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ -bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ -bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ -bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ -bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ -bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ -bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ -bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ -bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ -bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ -bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ -bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \ +bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \ +bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \ +bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \ +bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \ +bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \ +bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \ +bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \ +bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \ +bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \ +bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \ +bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ +bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \ +bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \ +bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \ +bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \ +bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \ +bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \ +bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \ +bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) diff --git a/libtommath/makefile_include.mk b/libtommath/makefile_include.mk index 71f04dd..df51a12 100644 --- a/libtommath/makefile_include.mk +++ b/libtommath/makefile_include.mk @@ -3,9 +3,9 @@ # #version of library -VERSION=1.2.1 -VERSION_PC=1.2.1 -VERSION_SO=3:1:2 +VERSION=1.3.0 +VERSION_PC=1.3.0 +VERSION_SO=4:0:3 PLATFORM := $(shell uname | sed -e 's/_.*//') diff --git a/libtommath/sources.cmake b/libtommath/sources.cmake new file mode 100644 index 0000000..a2df090 --- /dev/null +++ b/libtommath/sources.cmake @@ -0,0 +1,167 @@ +# SPDX-License-Identifier: Unlicense +# Autogenerated File! Do not edit. + +set(SOURCES +bn_cutoffs.c +bn_deprecated.c +bn_mp_2expt.c +bn_mp_abs.c +bn_mp_add.c +bn_mp_add_d.c +bn_mp_addmod.c +bn_mp_and.c +bn_mp_clamp.c +bn_mp_clear.c +bn_mp_clear_multi.c +bn_mp_cmp.c +bn_mp_cmp_d.c +bn_mp_cmp_mag.c +bn_mp_cnt_lsb.c +bn_mp_complement.c +bn_mp_copy.c +bn_mp_count_bits.c +bn_mp_decr.c +bn_mp_div.c +bn_mp_div_2.c +bn_mp_div_2d.c +bn_mp_div_d.c +bn_mp_dr_is_modulus.c +bn_mp_dr_reduce.c +bn_mp_dr_setup.c +bn_mp_error_to_string.c +bn_mp_exch.c +bn_mp_expt_n.c +bn_mp_exptmod.c +bn_mp_exteuclid.c +bn_mp_fread.c +bn_mp_from_sbin.c +bn_mp_from_ubin.c +bn_mp_fwrite.c +bn_mp_gcd.c +bn_mp_get_double.c +bn_mp_get_i32.c +bn_mp_get_i64.c +bn_mp_get_l.c +bn_mp_get_mag_u32.c +bn_mp_get_mag_u64.c +bn_mp_get_mag_ul.c +bn_mp_grow.c +bn_mp_incr.c +bn_mp_init.c +bn_mp_init_copy.c +bn_mp_init_i32.c +bn_mp_init_i64.c +bn_mp_init_l.c +bn_mp_init_multi.c +bn_mp_init_set.c +bn_mp_init_size.c +bn_mp_init_u32.c +bn_mp_init_u64.c +bn_mp_init_ul.c +bn_mp_invmod.c +bn_mp_is_square.c +bn_mp_iseven.c +bn_mp_isodd.c +bn_mp_kronecker.c +bn_mp_lcm.c +bn_mp_log_n.c +bn_mp_lshd.c +bn_mp_mod.c +bn_mp_mod_2d.c +bn_mp_mod_d.c +bn_mp_montgomery_calc_normalization.c +bn_mp_montgomery_reduce.c +bn_mp_montgomery_setup.c +bn_mp_mul.c +bn_mp_mul_2.c +bn_mp_mul_2d.c +bn_mp_mul_d.c +bn_mp_mulmod.c +bn_mp_neg.c +bn_mp_or.c +bn_mp_pack.c +bn_mp_pack_count.c +bn_mp_prime_fermat.c +bn_mp_prime_frobenius_underwood.c +bn_mp_prime_is_prime.c +bn_mp_prime_miller_rabin.c +bn_mp_prime_next_prime.c +bn_mp_prime_rabin_miller_trials.c +bn_mp_prime_rand.c +bn_mp_prime_strong_lucas_selfridge.c +bn_mp_radix_size.c +bn_mp_radix_smap.c +bn_mp_rand.c +bn_mp_read_radix.c +bn_mp_reduce.c +bn_mp_reduce_2k.c +bn_mp_reduce_2k_l.c +bn_mp_reduce_2k_setup.c +bn_mp_reduce_2k_setup_l.c +bn_mp_reduce_is_2k.c +bn_mp_reduce_is_2k_l.c +bn_mp_reduce_setup.c +bn_mp_root_n.c +bn_mp_rshd.c +bn_mp_sbin_size.c +bn_mp_set.c +bn_mp_set_double.c +bn_mp_set_i32.c +bn_mp_set_i64.c +bn_mp_set_l.c +bn_mp_set_u32.c +bn_mp_set_u64.c +bn_mp_set_ul.c +bn_mp_shrink.c +bn_mp_signed_rsh.c +bn_mp_sqr.c +bn_mp_sqrmod.c +bn_mp_sqrt.c +bn_mp_sqrtmod_prime.c +bn_mp_sub.c +bn_mp_sub_d.c +bn_mp_submod.c +bn_mp_to_radix.c +bn_mp_to_sbin.c +bn_mp_to_ubin.c +bn_mp_ubin_size.c +bn_mp_unpack.c +bn_mp_xor.c +bn_mp_zero.c +bn_prime_tab.c +bn_s_mp_add.c +bn_s_mp_balance_mul.c +bn_s_mp_div_3.c +bn_s_mp_exptmod.c +bn_s_mp_exptmod_fast.c +bn_s_mp_get_bit.c +bn_s_mp_invmod_fast.c +bn_s_mp_invmod_slow.c +bn_s_mp_karatsuba_mul.c +bn_s_mp_karatsuba_sqr.c +bn_s_mp_log.c +bn_s_mp_log_2expt.c +bn_s_mp_log_d.c +bn_s_mp_montgomery_reduce_fast.c +bn_s_mp_mul_digs.c +bn_s_mp_mul_digs_fast.c +bn_s_mp_mul_high_digs.c +bn_s_mp_mul_high_digs_fast.c +bn_s_mp_prime_is_divisible.c +bn_s_mp_rand_jenkins.c +bn_s_mp_rand_platform.c +bn_s_mp_reverse.c +bn_s_mp_sqr.c +bn_s_mp_sqr_fast.c +bn_s_mp_sub.c +bn_s_mp_toom_mul.c +bn_s_mp_toom_sqr.c +) + +set(HEADERS +tommath.h +tommath_class.h +tommath_cutoffs.h +tommath_private.h +tommath_superclass.h +) diff --git a/libtommath/tommath.def b/libtommath/tommath.def index 879767f..312843d 100644 --- a/libtommath/tommath.def +++ b/libtommath/tommath.def @@ -33,6 +33,7 @@ EXPORTS mp_dr_setup mp_error_to_string mp_exch + mp_expt_n mp_expt_u32 mp_exptmod mp_exteuclid @@ -75,6 +76,7 @@ EXPORTS mp_isodd mp_kronecker mp_lcm + mp_log_n mp_log_u32 mp_lshd mp_mod @@ -111,11 +113,11 @@ EXPORTS mp_reduce_is_2k mp_reduce_is_2k_l mp_reduce_setup + mp_root_n mp_root_u32 mp_rshd mp_sbin_size mp_set - mp_set_double mp_set_i32 mp_set_i64 mp_set_int @@ -143,14 +145,15 @@ EXPORTS mp_unpack mp_xor mp_zero - s_mp_mul_digs - s_mp_sub s_mp_add - s_mp_toom_mul - s_mp_mul_digs_fast + s_mp_balance_mul s_mp_karatsuba_mul - s_mp_sqr_fast - s_mp_reverse s_mp_karatsuba_sqr - s_mp_toom_sqr + s_mp_mul_digs + s_mp_mul_digs_fast + s_mp_reverse s_mp_sqr + s_mp_sqr_fast + s_mp_sub + s_mp_toom_mul + s_mp_toom_sqr diff --git a/libtommath/tommath.h b/libtommath/tommath.h index a235210..9e0839e 100644 --- a/libtommath/tommath.h +++ b/libtommath/tommath.h @@ -234,22 +234,13 @@ TOOM_SQR_CUTOFF; #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) # define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x))) -#elif defined(_MSC_VER) && _MSC_VER >= 1500 -# define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x)) -#else -# define MP_DEPRECATED(x) -#endif - -#ifndef MP_NO_DEPRECATED_PRAGMA -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) # define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s) # define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s) #elif defined(_MSC_VER) && _MSC_VER >= 1500 +# define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x)) # define MP_DEPRECATED_PRAGMA(s) __pragma(message(s)) -#endif -#endif - -#ifndef MP_DEPRECATED_PRAGMA +#else +# define MP_DEPRECATED(s) # define MP_DEPRECATED_PRAGMA(s) #endif @@ -338,7 +329,7 @@ mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR; uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR; uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR; unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR; -#define mp_get_mag_ull(a) ((unsigned long long)mp_get_mag_u64(a)) +MP_DEPRECATED(mp_get_mag_u64) unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR; /* get integer, set integer (long) */ long mp_get_l(const mp_int *a) MP_WUR; @@ -351,14 +342,14 @@ void mp_set_ul(mp_int *a, unsigned long b); mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR; /* get integer, set integer (long long) */ -#define mp_get_ll(a) ((long long)mp_get_i64(a)) -#define mp_set_ll(a,b) mp_set_i64(a,b) -#define mp_init_ll(a,b) mp_init_i64(a,b) +MP_DEPRECATED(mp_get_i64) long long mp_get_ll(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_set_i64) void mp_set_ll(mp_int *a, long long b); +MP_DEPRECATED(mp_init_i64) mp_err mp_init_ll(mp_int *a, long long b) MP_WUR; /* get integer, set integer (unsigned long long) */ -#define mp_get_ull(a) ((unsigned long long)mp_get_i64(a)) -#define mp_set_ull(a,b) mp_set_u64(a,b) -#define mp_init_ull(a,b) mp_init_u64(a,b) +#define mp_get_ull(a) (MP_DEPRECATED_PRAGMA("mp_get_ull() has been deprecated, use mp_get_u64()") ((unsigned long long)mp_get_ll(a))) +MP_DEPRECATED(mp_set_u64) void mp_set_ull(mp_int *a, unsigned long long b); +MP_DEPRECATED(mp_init_u64) mp_err mp_init_ull(mp_int *a, unsigned long long b) MP_WUR; /* set to single unsigned digit, up to MP_DIGIT_MAX */ void mp_set(mp_int *a, mp_digit b); @@ -367,7 +358,7 @@ mp_err mp_init_set(mp_int *a, mp_digit b) MP_WUR; /* get integer, set integer and init with integer (deprecated) */ MP_DEPRECATED(mp_get_mag_u32/mp_get_u32) unsigned long mp_get_int(const mp_int *a) MP_WUR; MP_DEPRECATED(mp_get_mag_ul/mp_get_ul) unsigned long mp_get_long(const mp_int *a) MP_WUR; -MP_DEPRECATED(mp_get_mag_ull/mp_get_ull) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_get_mag_u64/mp_get_u64) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR; MP_DEPRECATED(mp_set_ul) mp_err mp_set_int(mp_int *a, unsigned long b); MP_DEPRECATED(mp_set_ul) mp_err mp_set_long(mp_int *a, unsigned long b); MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned long long b); @@ -416,7 +407,7 @@ mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR; mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR; /* a/3 => 3c + d == a */ -mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; +MP_DEPRECATED(mp_div_d) mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; /* c = a * 2**b, implemented as c = a << b */ mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) MP_WUR; @@ -563,13 +554,24 @@ mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp /* c = [a, b] or (a*b)/(a, b) */ mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +/* Integer logarithm to integer base */ +mp_err mp_log_n(const mp_int *a, int base, int *c) MP_WUR; +MP_DEPRECATED(mp_log_n) mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) MP_WUR; + +/* c = a**b */ +mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_expt_n) mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_expt_n) mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_expt_n) mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; + /* finds one of the b'th root of a, such that |c|**b <= |a| * * returns error if a < 0 and b is even */ -mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; -MP_DEPRECATED(mp_root_u32) mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; -MP_DEPRECATED(mp_root_u32) mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_root_n) mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_root_n) mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_root_n) mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; /* special sqrt algo */ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) MP_WUR; @@ -729,14 +731,6 @@ MP_DEPRECATED(mp_prime_rand) mp_err mp_prime_random_ex(mp_int *a, int t, int siz private_mp_prime_callback cb, void *dat) MP_WUR; mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR; -/* Integer logarithm to integer base */ -mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) MP_WUR; - -/* c = a**b */ -mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; -MP_DEPRECATED(mp_expt_u32) mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; -MP_DEPRECATED(mp_expt_u32) mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; - /* ---> radix conversion <--- */ int mp_count_bits(const mp_int *a) MP_WUR; diff --git a/libtommath/tommath_class.h b/libtommath/tommath_class.h index 52ba585..0be592b 100644 --- a/libtommath/tommath_class.h +++ b/libtommath/tommath_class.h @@ -33,14 +33,13 @@ # define BN_MP_DIV_C # define BN_MP_DIV_2_C # define BN_MP_DIV_2D_C -# define BN_MP_DIV_3_C # define BN_MP_DIV_D_C # define BN_MP_DR_IS_MODULUS_C # define BN_MP_DR_REDUCE_C # define BN_MP_DR_SETUP_C # define BN_MP_ERROR_TO_STRING_C # define BN_MP_EXCH_C -# define BN_MP_EXPT_U32_C +# define BN_MP_EXPT_N_C # define BN_MP_EXPTMOD_C # define BN_MP_EXTEUCLID_C # define BN_MP_FREAD_C @@ -52,11 +51,9 @@ # define BN_MP_GET_I32_C # define BN_MP_GET_I64_C # define BN_MP_GET_L_C -# define BN_MP_GET_LL_C # define BN_MP_GET_MAG_U32_C # define BN_MP_GET_MAG_U64_C # define BN_MP_GET_MAG_UL_C -# define BN_MP_GET_MAG_ULL_C # define BN_MP_GROW_C # define BN_MP_INCR_C # define BN_MP_INIT_C @@ -64,21 +61,19 @@ # define BN_MP_INIT_I32_C # define BN_MP_INIT_I64_C # define BN_MP_INIT_L_C -# define BN_MP_INIT_LL_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SET_C # define BN_MP_INIT_SIZE_C # define BN_MP_INIT_U32_C # define BN_MP_INIT_U64_C # define BN_MP_INIT_UL_C -# define BN_MP_INIT_ULL_C # define BN_MP_INVMOD_C # define BN_MP_IS_SQUARE_C # define BN_MP_ISEVEN_C # define BN_MP_ISODD_C # define BN_MP_KRONECKER_C # define BN_MP_LCM_C -# define BN_MP_LOG_U32_C +# define BN_MP_LOG_N_C # define BN_MP_LSHD_C # define BN_MP_MOD_C # define BN_MP_MOD_2D_C @@ -115,7 +110,7 @@ # define BN_MP_REDUCE_IS_2K_C # define BN_MP_REDUCE_IS_2K_L_C # define BN_MP_REDUCE_SETUP_C -# define BN_MP_ROOT_U32_C +# define BN_MP_ROOT_N_C # define BN_MP_RSHD_C # define BN_MP_SBIN_SIZE_C # define BN_MP_SET_C @@ -123,11 +118,9 @@ # define BN_MP_SET_I32_C # define BN_MP_SET_I64_C # define BN_MP_SET_L_C -# define BN_MP_SET_LL_C # define BN_MP_SET_U32_C # define BN_MP_SET_U64_C # define BN_MP_SET_UL_C -# define BN_MP_SET_ULL_C # define BN_MP_SHRINK_C # define BN_MP_SIGNED_RSH_C # define BN_MP_SQR_C @@ -147,6 +140,7 @@ # define BN_PRIME_TAB_C # define BN_S_MP_ADD_C # define BN_S_MP_BALANCE_MUL_C +# define BN_S_MP_DIV_3_C # define BN_S_MP_EXPTMOD_C # define BN_S_MP_EXPTMOD_FAST_C # define BN_S_MP_GET_BIT_C @@ -154,6 +148,9 @@ # define BN_S_MP_INVMOD_SLOW_C # define BN_S_MP_KARATSUBA_MUL_C # define BN_S_MP_KARATSUBA_SQR_C +# define BN_S_MP_LOG_C +# define BN_S_MP_LOG_2EXPT_C +# define BN_S_MP_LOG_D_C # define BN_S_MP_MONTGOMERY_REDUCE_FAST_C # define BN_S_MP_MUL_DIGS_C # define BN_S_MP_MUL_DIGS_FAST_C @@ -182,28 +179,36 @@ # define BN_MP_AND_C # define BN_MP_BALANCE_MUL_C # define BN_MP_CMP_D_C +# define BN_MP_DIV_3_C # define BN_MP_EXPORT_C # define BN_MP_EXPTMOD_FAST_C # define BN_MP_EXPT_D_C # define BN_MP_EXPT_D_EX_C +# define BN_MP_EXPT_N_C # define BN_MP_EXPT_U32_C # define BN_MP_FROM_SBIN_C # define BN_MP_FROM_UBIN_C # define BN_MP_GET_BIT_C # define BN_MP_GET_INT_C +# define BN_MP_GET_LL_C # define BN_MP_GET_LONG_C # define BN_MP_GET_LONG_LONG_C # define BN_MP_GET_MAG_U32_C +# define BN_MP_GET_MAG_U64_C # define BN_MP_GET_MAG_ULL_C # define BN_MP_GET_MAG_UL_C # define BN_MP_IMPORT_C +# define BN_MP_INIT_LL_C # define BN_MP_INIT_SET_INT_C # define BN_MP_INIT_U32_C +# define BN_MP_INIT_ULL_C # define BN_MP_INVMOD_SLOW_C # define BN_MP_JACOBI_C # define BN_MP_KARATSUBA_MUL_C # define BN_MP_KARATSUBA_SQR_C # define BN_MP_KRONECKER_C +# define BN_MP_LOG_N_C +# define BN_MP_LOG_U32_C # define BN_MP_N_ROOT_C # define BN_MP_N_ROOT_EX_C # define BN_MP_OR_C @@ -213,13 +218,16 @@ # define BN_MP_RAND_DIGIT_C # define BN_MP_READ_SIGNED_BIN_C # define BN_MP_READ_UNSIGNED_BIN_C +# define BN_MP_ROOT_N_C # define BN_MP_ROOT_U32_C # define BN_MP_SBIN_SIZE_C # define BN_MP_SET_INT_C +# define BN_MP_SET_LL_C # define BN_MP_SET_LONG_C # define BN_MP_SET_LONG_LONG_C # define BN_MP_SET_U32_C # define BN_MP_SET_U64_C +# define BN_MP_SET_ULL_C # define BN_MP_SIGNED_BIN_SIZE_C # define BN_MP_SIGNED_RSH_C # define BN_MP_TC_AND_C @@ -242,6 +250,7 @@ # define BN_MP_UNSIGNED_BIN_SIZE_C # define BN_MP_XOR_C # define BN_S_MP_BALANCE_MUL_C +# define BN_S_MP_DIV_3_C # define BN_S_MP_EXPTMOD_FAST_C # define BN_S_MP_GET_BIT_C # define BN_S_MP_INVMOD_FAST_C @@ -369,21 +378,14 @@ # define BN_MP_ZERO_C #endif -#if defined(BN_MP_DIV_3_C) -# define BN_MP_CLAMP_C -# define BN_MP_CLEAR_C -# define BN_MP_EXCH_C -# define BN_MP_INIT_SIZE_C -#endif - #if defined(BN_MP_DIV_D_C) # define BN_MP_CLAMP_C # define BN_MP_CLEAR_C # define BN_MP_COPY_C # define BN_MP_DIV_2D_C -# define BN_MP_DIV_3_C # define BN_MP_EXCH_C # define BN_MP_INIT_SIZE_C +# define BN_S_MP_DIV_3_C #endif #if defined(BN_MP_DR_IS_MODULUS_C) @@ -405,7 +407,7 @@ #if defined(BN_MP_EXCH_C) #endif -#if defined(BN_MP_EXPT_U32_C) +#if defined(BN_MP_EXPT_N_C) # define BN_MP_CLEAR_C # define BN_MP_INIT_COPY_C # define BN_MP_MUL_C @@ -486,10 +488,6 @@ # define BN_MP_GET_MAG_UL_C #endif -#if defined(BN_MP_GET_LL_C) -# define BN_MP_GET_MAG_ULL_C -#endif - #if defined(BN_MP_GET_MAG_U32_C) #endif @@ -499,9 +497,6 @@ #if defined(BN_MP_GET_MAG_UL_C) #endif -#if defined(BN_MP_GET_MAG_ULL_C) -#endif - #if defined(BN_MP_GROW_C) #endif @@ -535,11 +530,6 @@ # define BN_MP_SET_L_C #endif -#if defined(BN_MP_INIT_LL_C) -# define BN_MP_INIT_C -# define BN_MP_SET_LL_C -#endif - #if defined(BN_MP_INIT_MULTI_C) # define BN_MP_CLEAR_C # define BN_MP_INIT_C @@ -568,11 +558,6 @@ # define BN_MP_SET_UL_C #endif -#if defined(BN_MP_INIT_ULL_C) -# define BN_MP_INIT_C -# define BN_MP_SET_ULL_C -#endif - #if defined(BN_MP_INVMOD_C) # define BN_MP_CMP_D_C # define BN_S_MP_INVMOD_FAST_C @@ -616,18 +601,10 @@ # define BN_MP_MUL_C #endif -#if defined(BN_MP_LOG_U32_C) -# define BN_MP_CLEAR_MULTI_C -# define BN_MP_CMP_C -# define BN_MP_CMP_D_C -# define BN_MP_COPY_C -# define BN_MP_COUNT_BITS_C -# define BN_MP_EXCH_C -# define BN_MP_EXPT_U32_C -# define BN_MP_INIT_MULTI_C -# define BN_MP_MUL_C -# define BN_MP_SET_C -# define BN_MP_SQR_C +#if defined(BN_MP_LOG_N_C) +# define BN_S_MP_LOG_2EXPT_C +# define BN_S_MP_LOG_C +# define BN_S_MP_LOG_D_C #endif #if defined(BN_MP_LSHD_C) @@ -929,7 +906,7 @@ # define BN_MP_DIV_C #endif -#if defined(BN_MP_ROOT_U32_C) +#if defined(BN_MP_ROOT_N_C) # define BN_MP_2EXPT_C # define BN_MP_ADD_D_C # define BN_MP_CLEAR_MULTI_C @@ -938,7 +915,7 @@ # define BN_MP_COUNT_BITS_C # define BN_MP_DIV_C # define BN_MP_EXCH_C -# define BN_MP_EXPT_U32_C +# define BN_MP_EXPT_N_C # define BN_MP_INIT_MULTI_C # define BN_MP_MUL_C # define BN_MP_MUL_D_C @@ -976,10 +953,6 @@ # define BN_MP_SET_UL_C #endif -#if defined(BN_MP_SET_LL_C) -# define BN_MP_SET_ULL_C -#endif - #if defined(BN_MP_SET_U32_C) #endif @@ -989,9 +962,6 @@ #if defined(BN_MP_SET_UL_C) #endif -#if defined(BN_MP_SET_ULL_C) -#endif - #if defined(BN_MP_SHRINK_C) #endif @@ -1121,6 +1091,13 @@ # define BN_MP_MUL_C #endif +#if defined(BN_S_MP_DIV_3_C) +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_C +#endif + #if defined(BN_S_MP_EXPTMOD_C) # define BN_MP_CLEAR_C # define BN_MP_COPY_C @@ -1213,6 +1190,26 @@ # define BN_S_MP_SUB_C #endif +#if defined(BN_S_MP_LOG_C) +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_COPY_C +# define BN_MP_EXCH_C +# define BN_MP_EXPT_N_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MUL_C +# define BN_MP_SET_C +# define BN_MP_SQR_C +#endif + +#if defined(BN_S_MP_LOG_2EXPT_C) +# define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_S_MP_LOG_D_C) +#endif + #if defined(BN_S_MP_MONTGOMERY_REDUCE_FAST_C) # define BN_MP_CLAMP_C # define BN_MP_CMP_MAG_C @@ -1283,13 +1280,13 @@ # define BN_MP_CLEAR_C # define BN_MP_CLEAR_MULTI_C # define BN_MP_DIV_2_C -# define BN_MP_DIV_3_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SIZE_C # define BN_MP_LSHD_C # define BN_MP_MUL_2_C # define BN_MP_MUL_C # define BN_MP_SUB_C +# define BN_S_MP_DIV_3_C #endif #if defined(BN_S_MP_TOOM_SQR_C) diff --git a/libtommath/tommath_private.h b/libtommath/tommath_private.h index f5ee285..2d2d9a4 100644 --- a/libtommath/tommath_private.h +++ b/libtommath/tommath_private.h @@ -5,7 +5,11 @@ #define TOMMATH_PRIV_H_ #include -#include "tclTomMath.h" +#ifndef TCL_WITH_EXTERNAL_TOMMATH +# include "tclTomMath.h" +#else +# include "tommath.h" +#endif #include "tommath_class.h" /* @@ -159,6 +163,8 @@ typedef private_mp_word mp_word; #define MP_MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MP_MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MP_IS_2EXPT(x) (((x) != 0u) && (((x) & ((x) - 1u)) == 0u)) + /* Static assertion */ #define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1]; @@ -190,8 +196,11 @@ extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size); /* lowlevel functions, do not call! */ MP_PRIVATE mp_bool s_mp_get_bit(const mp_int *a, unsigned int b); +MP_PRIVATE int s_mp_log_2expt(const mp_int *a, mp_digit base) MP_WUR; +MP_PRIVATE int s_mp_log_d(mp_digit base, mp_digit n) MP_WUR; MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; MP_PRIVATE mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; MP_PRIVATE mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; @@ -208,6 +217,7 @@ MP_PRIVATE mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) MP_PRIVATE mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_log(const mp_int *a, mp_digit base, int *c) MP_WUR; MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat); MP_PRIVATE void s_mp_reverse(unsigned char *s, size_t len); diff --git a/libtommath/win64-arm/libtommath.dll b/libtommath/win64-arm/libtommath.dll index e795d6d..9cec45b 100755 Binary files a/libtommath/win64-arm/libtommath.dll and b/libtommath/win64-arm/libtommath.dll differ diff --git a/libtommath/win64/libtommath.dll b/libtommath/win64/libtommath.dll index 3667593..856af88 100755 Binary files a/libtommath/win64/libtommath.dll and b/libtommath/win64/libtommath.dll differ diff --git a/macosx/Tcl.xcodeproj/project.pbxproj b/macosx/Tcl.xcodeproj/project.pbxproj index 8d27c1c..09b3b14 100644 --- a/macosx/Tcl.xcodeproj/project.pbxproj +++ b/macosx/Tcl.xcodeproj/project.pbxproj @@ -110,7 +110,7 @@ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; }; F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; }; F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; }; - F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; }; + F96D48F708F272C3004A47F5 /* bn_s_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_s_mp_div_3.c */; }; F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; }; F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; }; F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; }; @@ -163,7 +163,7 @@ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; }; F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; }; F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; }; - F9E61D2C090A48AC002B3151 /* bn_mp_expt_u32.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */; }; + F9E61D2C090A48AC002B3151 /* bn_mp_expt_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_n.c */; }; F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; }; F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; }; F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; }; @@ -569,10 +569,10 @@ F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = ""; }; F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = ""; }; F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = ""; }; - F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = ""; }; + F96D427908F272B3004A47F5 /* bn_s_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_div_3.c; sourceTree = ""; }; F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = ""; }; F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = ""; }; - F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_u32.c; sourceTree = ""; }; + F96D427F08F272B3004A47F5 /* bn_mp_expt_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_n.c; sourceTree = ""; }; F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d_ex.c; sourceTree = ""; }; F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = ""; }; F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = ""; }; @@ -1406,10 +1406,10 @@ F96D427608F272B3004A47F5 /* bn_mp_div.c */, F96D427708F272B3004A47F5 /* bn_mp_div_2.c */, F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */, - F96D427908F272B3004A47F5 /* bn_mp_div_3.c */, + F96D427908F272B3004A47F5 /* bn_s_mp_div_3.c */, F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */, F96D427E08F272B3004A47F5 /* bn_mp_exch.c */, - F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */, + F96D427F08F272B3004A47F5 /* bn_mp_expt_n.c */, F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */, F96D428708F272B3004A47F5 /* bn_mp_grow.c */, F96D428808F272B3004A47F5 /* bn_mp_init.c */, @@ -2023,10 +2023,10 @@ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */, F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */, F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */, - F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */, + F96D48F708F272C3004A47F5 /* bn_s_mp_div_3.c in Sources */, F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */, F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */, - F9E61D2C090A48AC002B3151 /* bn_mp_expt_u32.c in Sources */, + F9E61D2C090A48AC002B3151 /* bn_mp_expt_n.c in Sources */, F9E61D2C090A48AC002B3151 /* bn_mp_expt_d_ex.c in Sources */, F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */, F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */, diff --git a/unix/Makefile.in b/unix/Makefile.in index eed8d91..3d8267f 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -328,7 +328,7 @@ TOMMATH_OBJS = bn_s_mp_reverse.o bn_s_mp_mul_digs_fast.o \ bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ bn_mp_cnt_lsb.o bn_mp_copy.o \ bn_mp_count_bits.o bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o \ - bn_mp_div_2d.o bn_mp_div_3.o bn_mp_exch.o bn_mp_expt_u32.o \ + bn_mp_div_2d.o bn_s_mp_div_3.o bn_mp_exch.o bn_mp_expt_n.o \ bn_mp_get_mag_u64.o \ bn_mp_grow.o bn_mp_init.o \ bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \ @@ -522,14 +522,14 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_div.c \ $(TOMMATH_DIR)/bn_mp_div_2.c \ $(TOMMATH_DIR)/bn_mp_div_2d.c \ - $(TOMMATH_DIR)/bn_mp_div_3.c \ + $(TOMMATH_DIR)/bn_s_mp_div_3.c \ $(TOMMATH_DIR)/bn_mp_div_d.c \ $(TOMMATH_DIR)/bn_mp_dr_is_modulus.c \ $(TOMMATH_DIR)/bn_mp_dr_reduce.c \ $(TOMMATH_DIR)/bn_mp_dr_setup.c \ $(TOMMATH_DIR)/bn_mp_error_to_string.c \ $(TOMMATH_DIR)/bn_mp_exch.c \ - $(TOMMATH_DIR)/bn_mp_expt_u32.c \ + $(TOMMATH_DIR)/bn_mp_expt_n.c \ $(TOMMATH_DIR)/bn_mp_exptmod.c \ $(TOMMATH_DIR)/bn_mp_exteuclid.c \ $(TOMMATH_DIR)/bn_mp_fread.c \ @@ -541,11 +541,9 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_get_i32.c \ $(TOMMATH_DIR)/bn_mp_get_i64.c \ $(TOMMATH_DIR)/bn_mp_get_l.c \ - $(TOMMATH_DIR)/bn_mp_get_ll.c \ $(TOMMATH_DIR)/bn_mp_get_mag_u32.c \ $(TOMMATH_DIR)/bn_mp_get_mag_u64.c \ $(TOMMATH_DIR)/bn_mp_get_mag_ul.c \ - $(TOMMATH_DIR)/bn_mp_get_mag_ull.c \ $(TOMMATH_DIR)/bn_mp_grow.c \ $(TOMMATH_DIR)/bn_mp_incr.c \ $(TOMMATH_DIR)/bn_mp_init.c \ @@ -553,21 +551,22 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_init_i32.c \ $(TOMMATH_DIR)/bn_mp_init_i64.c \ $(TOMMATH_DIR)/bn_mp_init_l.c \ - $(TOMMATH_DIR)/bn_mp_init_ll.c \ $(TOMMATH_DIR)/bn_mp_init_multi.c \ $(TOMMATH_DIR)/bn_mp_init_set.c \ $(TOMMATH_DIR)/bn_mp_init_size.c \ $(TOMMATH_DIR)/bn_mp_init_u32.c \ $(TOMMATH_DIR)/bn_mp_init_u64.c \ $(TOMMATH_DIR)/bn_mp_init_ul.c \ - $(TOMMATH_DIR)/bn_mp_init_ull.c \ $(TOMMATH_DIR)/bn_mp_invmod.c \ $(TOMMATH_DIR)/bn_mp_is_square.c \ $(TOMMATH_DIR)/bn_mp_iseven.c \ $(TOMMATH_DIR)/bn_mp_isodd.c \ $(TOMMATH_DIR)/bn_mp_kronecker.c \ $(TOMMATH_DIR)/bn_mp_lcm.c \ - $(TOMMATH_DIR)/bn_mp_log_u32.c \ + $(TOMMATH_DIR)/bn_mp_log_n.c \ + $(TOMMATH_DIR)/bn_s_mp_log.c \ + $(TOMMATH_DIR)/bn_s_mp_log_2expt.c \ + $(TOMMATH_DIR)/bn_s_mp_log_d.c \ $(TOMMATH_DIR)/bn_mp_lshd.c \ $(TOMMATH_DIR)/bn_mp_mod.c \ $(TOMMATH_DIR)/bn_mp_mod_2d.c \ @@ -604,7 +603,7 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_reduce_is_2k.c \ $(TOMMATH_DIR)/bn_mp_reduce_is_2k_l.c \ $(TOMMATH_DIR)/bn_mp_reduce_setup.c \ - $(TOMMATH_DIR)/bn_mp_root_u32.c \ + $(TOMMATH_DIR)/bn_mp_root_n.c \ $(TOMMATH_DIR)/bn_mp_rshd.c \ $(TOMMATH_DIR)/bn_mp_sbin_size.c \ $(TOMMATH_DIR)/bn_mp_set.c \ @@ -612,11 +611,9 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_set_i32.c \ $(TOMMATH_DIR)/bn_mp_set_i64.c \ $(TOMMATH_DIR)/bn_mp_set_l.c \ - $(TOMMATH_DIR)/bn_mp_set_ll.c \ $(TOMMATH_DIR)/bn_mp_set_u32.c \ $(TOMMATH_DIR)/bn_mp_set_u64.c \ $(TOMMATH_DIR)/bn_mp_set_ul.c \ - $(TOMMATH_DIR)/bn_mp_set_ull.c \ $(TOMMATH_DIR)/bn_mp_shrink.c \ $(TOMMATH_DIR)/bn_mp_signed_rsh.c \ $(TOMMATH_DIR)/bn_mp_sqr.c \ @@ -1656,14 +1653,14 @@ bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c $(MATHHDRS) bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c -bn_mp_div_3.o: $(TOMMATH_DIR)/bn_mp_div_3.c $(MATHHDRS) - $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_3.c +bn_s_mp_div_3.o: $(TOMMATH_DIR)/bn_s_mp_div_3.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_div_3.c bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_exch.c -bn_mp_expt_u32.o: $(TOMMATH_DIR)/bn_mp_expt_u32.c $(MATHHDRS) - $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_u32.c +bn_mp_expt_n.o: $(TOMMATH_DIR)/bn_mp_expt_n.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_n.c bn_mp_get_mag_u64.o: $(TOMMATH_DIR)/bn_mp_get_mag_u64.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_get_mag_u64.c diff --git a/win/Makefile.in b/win/Makefile.in index 625d9e7..fa88264 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -387,9 +387,9 @@ TOMMATH_OBJS = \ bn_mp_div_d.${OBJEXT} \ bn_mp_div_2.${OBJEXT} \ bn_mp_div_2d.${OBJEXT} \ - bn_mp_div_3.${OBJEXT} \ + bn_s_mp_div_3.${OBJEXT} \ bn_mp_exch.${OBJEXT} \ - bn_mp_expt_u32.${OBJEXT} \ + bn_mp_expt_n.${OBJEXT} \ bn_mp_get_mag_u64.${OBJEXT} \ bn_mp_grow.${OBJEXT} \ bn_mp_init.${OBJEXT} \ diff --git a/win/makefile.vc b/win/makefile.vc index ed7157f..aa122c3 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -367,9 +367,9 @@ TOMMATHOBJS = \ $(TMP_DIR)\bn_mp_div_d.obj \ $(TMP_DIR)\bn_mp_div_2.obj \ $(TMP_DIR)\bn_mp_div_2d.obj \ - $(TMP_DIR)\bn_mp_div_3.obj \ + $(TMP_DIR)\bn_s_mp_div_3.obj \ $(TMP_DIR)\bn_mp_exch.obj \ - $(TMP_DIR)\bn_mp_expt_u32.obj \ + $(TMP_DIR)\bn_mp_expt_n.obj \ $(TMP_DIR)\bn_mp_get_mag_u64.obj \ $(TMP_DIR)\bn_mp_grow.obj \ $(TMP_DIR)\bn_mp_init.obj \ -- cgit v0.12 From c1d497335b62374f9f0869d48fc3ee804704c55c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Mar 2024 09:50:22 +0000 Subject: Re-build libtommath.dll for x86. Re-build tommath.lib for all platforms (since libtommath 1.3 has more symbols) --- libtommath/win32/libtommath.dll | Bin 72704 -> 71168 bytes libtommath/win32/tommath.lib | Bin 29796 -> 30148 bytes libtommath/win64-arm/tommath.lib | Bin 28856 -> 29386 bytes libtommath/win64/tommath.lib | Bin 29044 -> 29386 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/libtommath/win32/libtommath.dll b/libtommath/win32/libtommath.dll index 62779fa..c0aba14 100755 Binary files a/libtommath/win32/libtommath.dll and b/libtommath/win32/libtommath.dll differ diff --git a/libtommath/win32/tommath.lib b/libtommath/win32/tommath.lib index dd3e82e..9c539d1 100644 Binary files a/libtommath/win32/tommath.lib and b/libtommath/win32/tommath.lib differ diff --git a/libtommath/win64-arm/tommath.lib b/libtommath/win64-arm/tommath.lib index f14fbe7..36d3527 100644 Binary files a/libtommath/win64-arm/tommath.lib and b/libtommath/win64-arm/tommath.lib differ diff --git a/libtommath/win64/tommath.lib b/libtommath/win64/tommath.lib index 434fa7c..18a8532 100644 Binary files a/libtommath/win64/tommath.lib and b/libtommath/win64/tommath.lib differ -- cgit v0.12 From d79e8e211c9ddde38109238127709570e50063e4 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Mar 2024 12:51:50 +0000 Subject: C++ improvements/typo's --- libtommath/bn_mp_div.c | 4 +- libtommath/bn_mp_exptmod.c | 4 +- libtommath/bn_mp_exteuclid.c | 4 +- libtommath/bn_mp_lcm.c | 4 +- libtommath/bn_mp_mul.c | 2 +- libtommath/bn_mp_prime_frobenius_underwood.c | 4 +- libtommath/bn_mp_prime_strong_lucas_selfridge.c | 4 +- libtommath/bn_mp_root_n.c | 4 +- libtommath/bn_mp_sqrt.c | 73 +++++++++++++++++++++++++ libtommath/bn_mp_sqrtmod_prime.c | 4 +- libtommath/bn_s_mp_balance_mul.c | 4 +- libtommath/bn_s_mp_invmod_fast.c | 4 +- libtommath/bn_s_mp_invmod_slow.c | 4 +- libtommath/bn_s_mp_log.c | 4 +- libtommath/bn_s_mp_mul_high_digs_fast.c | 4 +- libtommath/bn_s_mp_rand_jenkins.c | 4 +- libtommath/bn_s_mp_toom_mul.c | 4 +- libtommath/changes.txt | 2 +- 18 files changed, 105 insertions(+), 32 deletions(-) diff --git a/libtommath/bn_mp_div.c b/libtommath/bn_mp_div.c index 71de55b..bca227d 100644 --- a/libtommath/bn_mp_div.c +++ b/libtommath/bn_mp_div.c @@ -31,7 +31,7 @@ mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) } /* init our temps */ - if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&ta, &tb, &tq, &q, (void *)NULL)) != MP_OKAY) { return err; } @@ -64,7 +64,7 @@ mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n; } LBL_ERR: - mp_clear_multi(&ta, &tb, &tq, &q, NULL); + mp_clear_multi(&ta, &tb, &tq, &q, (void *)NULL); return err; } diff --git a/libtommath/bn_mp_exptmod.c b/libtommath/bn_mp_exptmod.c index 5f811eb..1ca2e93 100644 --- a/libtommath/bn_mp_exptmod.c +++ b/libtommath/bn_mp_exptmod.c @@ -26,7 +26,7 @@ mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) return MP_VAL; } - if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&tmpG, &tmpX, (void *)NULL)) != MP_OKAY) { return err; } @@ -43,7 +43,7 @@ mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) /* and now compute (1/G)**|X| instead of G**X [X < 0] */ err = mp_exptmod(&tmpG, &tmpX, P, Y); LBL_ERR: - mp_clear_multi(&tmpG, &tmpX, NULL); + mp_clear_multi(&tmpG, &tmpX, (void *)NULL); return err; } diff --git a/libtommath/bn_mp_exteuclid.c b/libtommath/bn_mp_exteuclid.c index faf47ba..fbac454 100644 --- a/libtommath/bn_mp_exteuclid.c +++ b/libtommath/bn_mp_exteuclid.c @@ -11,7 +11,7 @@ mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp; mp_err err; - if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, (void *)NULL)) != MP_OKAY) { return err; } @@ -67,7 +67,7 @@ mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp err = MP_OKAY; LBL_ERR: - mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, (void *)NULL); return err; } #endif diff --git a/libtommath/bn_mp_lcm.c b/libtommath/bn_mp_lcm.c index c32b269..5be3fc6 100644 --- a/libtommath/bn_mp_lcm.c +++ b/libtommath/bn_mp_lcm.c @@ -10,7 +10,7 @@ mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) mp_int t1, t2; - if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&t1, &t2, (void *)NULL)) != MP_OKAY) { return err; } @@ -38,7 +38,7 @@ mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) c->sign = MP_ZPOS; LBL_T: - mp_clear_multi(&t1, &t2, NULL); + mp_clear_multi(&t1, &t2, (void *)NULL); return err; } #endif diff --git a/libtommath/bn_mp_mul.c b/libtommath/bn_mp_mul.c index 561913a..91707cd 100644 --- a/libtommath/bn_mp_mul.c +++ b/libtommath/bn_mp_mul.c @@ -17,7 +17,7 @@ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger * to make some sense, but it depends on architecture, OS, position of the * stars... so YMMV. - * Using it to cut the input into slices small enough for fast_s_mp_mul_digs + * Using it to cut the input into slices small enough for s_mp_mul_digs_fast * was actually slower on the author's machine, but YMMV. */ (min_len >= MP_KARATSUBA_MUL_CUTOFF) && diff --git a/libtommath/bn_mp_prime_frobenius_underwood.c b/libtommath/bn_mp_prime_frobenius_underwood.c index 253e8d5..be4bd08 100644 --- a/libtommath/bn_mp_prime_frobenius_underwood.c +++ b/libtommath/bn_mp_prime_frobenius_underwood.c @@ -32,7 +32,7 @@ mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result) *result = MP_NO; - if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, (void *)NULL)) != MP_OKAY) { return err; } @@ -124,7 +124,7 @@ mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result) } LBL_FU_ERR: - mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL); + mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, (void *)NULL); return err; } diff --git a/libtommath/bn_mp_prime_strong_lucas_selfridge.c b/libtommath/bn_mp_prime_strong_lucas_selfridge.c index b50bbcd..617648c 100644 --- a/libtommath/bn_mp_prime_strong_lucas_selfridge.c +++ b/libtommath/bn_mp_prime_strong_lucas_selfridge.c @@ -73,7 +73,7 @@ mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result) */ if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz, - NULL)) != MP_OKAY) { + (void *)NULL)) != MP_OKAY) { return err; } @@ -281,7 +281,7 @@ mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result) } } LBL_LS_ERR: - mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL); + mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, (void *)NULL); return err; } #endif diff --git a/libtommath/bn_mp_root_n.c b/libtommath/bn_mp_root_n.c index 5b92ff5..51ad759 100644 --- a/libtommath/bn_mp_root_n.c +++ b/libtommath/bn_mp_root_n.c @@ -27,7 +27,7 @@ mp_err mp_root_n(const mp_int *a, int b, mp_int *c) return MP_VAL; } - if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&t1, &t2, &t3, (void *)NULL)) != MP_OKAY) { return err; } @@ -134,7 +134,7 @@ mp_err mp_root_n(const mp_int *a, int b, mp_int *c) c->sign = a->sign; LBL_ERR: - mp_clear_multi(&t1, &t2, &t3, NULL); + mp_clear_multi(&t1, &t2, &t3, (void *)NULL); return err; } diff --git a/libtommath/bn_mp_sqrt.c b/libtommath/bn_mp_sqrt.c index 82d6824..dcf28fd 100644 --- a/libtommath/bn_mp_sqrt.c +++ b/libtommath/bn_mp_sqrt.c @@ -3,11 +3,24 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#ifndef NO_FLOATING_POINT +#include +#include +#if (MP_DIGIT_BIT != 28) || (FLT_RADIX != 2) || (DBL_MANT_DIG != 53) || (DBL_MAX_EXP != 1024) +#define NO_FLOATING_POINT +#endif +#endif + /* this function is less generic than mp_n_root, simpler and faster */ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) { mp_err err; mp_int t1, t2; +#ifndef NO_FLOATING_POINT + int i, j, k; + volatile double d; + mp_digit dig; +#endif /* must be positive */ if (arg->sign == MP_NEG) { @@ -20,6 +33,64 @@ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) return MP_OKAY; } +#ifndef NO_FLOATING_POINT + + i = (arg->used / 2) - 1; + j = 2 * i; + if ((err = mp_init_size(&t1, i+2)) != MP_OKAY) { + return err; + } + + if ((err = mp_init(&t2)) != MP_OKAY) { + goto E2; + } + + for (k = 0; k < i; ++k) { + t1.dp[k] = (mp_digit) 0; + } + + /* Estimate the square root using the hardware floating point unit. */ + + d = 0.0; + for (k = arg->used-1; k >= j; --k) { + d = ldexp(d, MP_DIGIT_BIT) + (double)(arg->dp[k]); + } + + /* + * At this point, d is the nearest floating point number to the most + * significant 1 or 2 mp_digits of arg. Extract its square root. + */ + + d = sqrt(d); + + /* dig is the most significant mp_digit of the square root */ + + dig = (mp_digit) ldexp(d, -MP_DIGIT_BIT); + + /* + * If the most significant digit is nonzero, find the next digit down + * by subtracting MP_DIGIT_BIT times thie most significant digit. + * Subtract one from the result so that our initial estimate is always + * low. + */ + + if (dig) { + t1.used = i+2; + d -= ldexp((double) dig, MP_DIGIT_BIT); + if (d >= 1.0) { + t1.dp[i+1] = dig; + t1.dp[i] = ((mp_digit) d) - 1; + } else { + t1.dp[i+1] = dig-1; + t1.dp[i] = MP_DIGIT_MAX; + } + } else { + t1.used = i+1; + t1.dp[i] = ((mp_digit) d) - 1; + } + +#else + if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { return err; } @@ -31,6 +102,8 @@ mp_err mp_sqrt(const mp_int *arg, mp_int *ret) /* First approx. (not very bad for large arg) */ mp_rshd(&t1, t1.used/2); +#endif + /* t1 > 0 */ if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { goto E1; diff --git a/libtommath/bn_mp_sqrtmod_prime.c b/libtommath/bn_mp_sqrtmod_prime.c index a833ed7..425ae17 100644 --- a/libtommath/bn_mp_sqrtmod_prime.c +++ b/libtommath/bn_mp_sqrtmod_prime.c @@ -25,7 +25,7 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err; if (legendre == -1) return MP_VAL; /* quadratic non-residue mod prime */ - if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, (void *)NULL)) != MP_OKAY) { return err; } @@ -111,7 +111,7 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) } cleanup: - mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL); + mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, (void *)NULL); return err; } diff --git a/libtommath/bn_s_mp_balance_mul.c b/libtommath/bn_s_mp_balance_mul.c index 7ece5d7..557cc1d 100644 --- a/libtommath/bn_s_mp_balance_mul.c +++ b/libtommath/bn_s_mp_balance_mul.c @@ -19,7 +19,7 @@ mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) { return err; } - if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&tmp, &r, (void *)NULL)) != MP_OKAY) { mp_clear(&a0); return err; } @@ -75,7 +75,7 @@ mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) mp_exch(&r,c); LBL_ERR: - mp_clear_multi(&a0, &tmp, &r,NULL); + mp_clear_multi(&a0, &tmp, &r, (void *)NULL); return err; } #endif diff --git a/libtommath/bn_s_mp_invmod_fast.c b/libtommath/bn_s_mp_invmod_fast.c index 677d7ab..e76c604 100644 --- a/libtommath/bn_s_mp_invmod_fast.c +++ b/libtommath/bn_s_mp_invmod_fast.c @@ -21,7 +21,7 @@ mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) } /* init all our temps */ - if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, (void *)NULL)) != MP_OKAY) { return err; } @@ -112,7 +112,7 @@ top: err = MP_OKAY; LBL_ERR: - mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL); + mp_clear_multi(&x, &y, &u, &v, &B, &D, (void *)NULL); return err; } #endif diff --git a/libtommath/bn_s_mp_invmod_slow.c b/libtommath/bn_s_mp_invmod_slow.c index 4c5db33..6079d4b 100644 --- a/libtommath/bn_s_mp_invmod_slow.c +++ b/libtommath/bn_s_mp_invmod_slow.c @@ -16,7 +16,7 @@ mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) /* init temps */ if ((err = mp_init_multi(&x, &y, &u, &v, - &A, &B, &C, &D, NULL)) != MP_OKAY) { + &A, &B, &C, &D, (void *)NULL)) != MP_OKAY) { return err; } @@ -113,7 +113,7 @@ top: mp_exch(&C, c); err = MP_OKAY; LBL_ERR: - mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL); + mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, (void *)NULL); return err; } #endif diff --git a/libtommath/bn_s_mp_log.c b/libtommath/bn_s_mp_log.c index a75212a..6ead7d9 100644 --- a/libtommath/bn_s_mp_log.c +++ b/libtommath/bn_s_mp_log.c @@ -17,7 +17,7 @@ mp_err s_mp_log(const mp_int *a, mp_digit base, int *c) if ((err = mp_init_multi(&bracket_low, &bracket_high, - &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) { + &bracket_mid, &t, &bi_base, (void *)NULL)) != MP_OKAY) { return err; } @@ -73,7 +73,7 @@ mp_err s_mp_log(const mp_int *a, mp_digit base, int *c) LBL_END: mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid, - &t, &bi_base, NULL); + &t, &bi_base, (void *)NULL); return err; } diff --git a/libtommath/bn_s_mp_mul_high_digs_fast.c b/libtommath/bn_s_mp_mul_high_digs_fast.c index 4ce7f59..04c74a8 100644 --- a/libtommath/bn_s_mp_mul_high_digs_fast.c +++ b/libtommath/bn_s_mp_mul_high_digs_fast.c @@ -3,8 +3,8 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ -/* this is a modified version of fast_s_mul_digs that only produces - * output digits *above* digs. See the comments for fast_s_mul_digs +/* this is a modified version of s_mp_mul_digs_fast that only produces + * output digits *above* digs. See the comments for s_mp_mul_digs_fast * to see how it works. * * This is used in the Barrett reduction since for one of the multiplications diff --git a/libtommath/bn_s_mp_rand_jenkins.c b/libtommath/bn_s_mp_rand_jenkins.c index da0771c..c64afac 100644 --- a/libtommath/bn_s_mp_rand_jenkins.c +++ b/libtommath/bn_s_mp_rand_jenkins.c @@ -27,10 +27,10 @@ static uint64_t s_rand_jenkins_val(void) void s_mp_rand_jenkins_init(uint64_t seed) { - uint64_t i; + int i; jenkins_x.a = 0xf1ea5eedULL; jenkins_x.b = jenkins_x.c = jenkins_x.d = seed; - for (i = 0uLL; i < 20uLL; ++i) { + for (i = 0; i < 20; ++i) { (void)s_rand_jenkins_val(); } } diff --git a/libtommath/bn_s_mp_toom_mul.c b/libtommath/bn_s_mp_toom_mul.c index eefce6c..fd574a2 100644 --- a/libtommath/bn_s_mp_toom_mul.c +++ b/libtommath/bn_s_mp_toom_mul.c @@ -36,7 +36,7 @@ mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) mp_err err; /* init temps */ - if ((err = mp_init_multi(&S1, &S2, &T1, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&S1, &S2, &T1, (void *)NULL)) != MP_OKAY) { return err; } @@ -208,7 +208,7 @@ LBL_ERRa2: LBL_ERRa1: mp_clear(&a0); LBL_ERRa0: - mp_clear_multi(&S1, &S2, &T1, NULL); + mp_clear_multi(&S1, &S2, &T1, (void *)NULL); return err; } diff --git a/libtommath/changes.txt b/libtommath/changes.txt index 80ff7dd..ac9e49a 100644 --- a/libtommath/changes.txt +++ b/libtommath/changes.txt @@ -423,7 +423,7 @@ v0.13 -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which p Jan 17th, 2003 v0.12 -- re-wrote the majority of the makefile so its more portable and will install via "make install" on most *nix platforms - -- Re-packaged all the source as seperate files. Means the library a single + -- Re-packaged all the source as separate files. Means the library a single file packagage any more. Instead of just adding "bn.c" you have to add libtommath.a -- Renamed "bn.h" to "tommath.h" -- cgit v0.12 From 45a5a343349c73758bf3714896199324b65e1b0d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Mar 2024 14:16:02 +0000 Subject: Take care of the deprecation of mp_expt_u32 --- generic/tclExecute.c | 3 ++- generic/tclStubInit.c | 21 +++++++++++++++------ generic/tclTomMath.decls | 2 +- generic/tclTomMathDecls.h | 33 ++++++++++++++++++--------------- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 94de5f2..89668a5 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8504,7 +8504,8 @@ ExecuteExtendedBinaryMathOp( Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); err = mp_init(&bigResult); if (err == MP_OKAY) { - err = mp_expt_u32(&big1, (unsigned int)w2, &bigResult); + /* Don't use "mp_expt_n" directly here, it doesn't exist in libtommath 1.2 */ + err = TclBN_mp_expt_n(&big1, (int)w2, &bigResult); } if (err != MP_OKAY) { return OUT_OF_MEMORY; diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index e35a401..e7dc543 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -246,17 +246,18 @@ int TclParseArgsObjv(Tcl_Interp *interp, #define TclBN_mp_xor mp_xor #define TclBN_mp_zero mp_zero #define TclBN_s_mp_add s_mp_add -#define TclBN_mp_balance_mul s_mp_balance_mul -#define TclBN_mp_karatsuba_mul s_mp_karatsuba_mul -#define TclBN_mp_karatsuba_sqr s_mp_karatsuba_sqr +#define TclBN_s_mp_balance_mul s_mp_balance_mul +#define TclBN_s_mp_div_3 s_mp_div_3 +#define TclBN_s_mp_karatsuba_mul s_mp_karatsuba_mul +#define TclBN_s_mp_karatsuba_sqr s_mp_karatsuba_sqr #define TclBN_s_mp_mul_digs s_mp_mul_digs #define TclBN_s_mp_mul_digs_fast s_mp_mul_digs_fast #define TclBN_s_mp_reverse s_mp_reverse #define TclBN_s_mp_sqr s_mp_sqr #define TclBN_s_mp_sqr_fast s_mp_sqr_fast #define TclBN_s_mp_sub s_mp_sub -#define TclBN_mp_toom_mul s_mp_toom_mul -#define TclBN_mp_toom_sqr s_mp_toom_sqr +#define TclBN_s_mp_toom_mul s_mp_toom_mul +#define TclBN_s_mp_toom_sqr s_mp_toom_sqr #ifndef MAC_OSX_TCL /* On UNIX, fill with other stub entries */ # define Tcl_MacOSXOpenVersionedBundleResources 0 @@ -382,6 +383,14 @@ MODULE_SCOPE const TclTomMathStubs tclTomMathStubs; #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif +#if TCL_WITH_EXTERNAL_TOMMATH +/* If Tcl is linked with an external libtommath 1.2.x, then mp_expt_n doesn't + * exist (since that was introduced in libtommath 1.3.0. Provide it here.) */ +mp_err MP_WUR TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) { + return mp_expt_u32(a, (uint32_t)b, c);; +} +#endif /* TCL_WITH_EXTERNAL_TOMMATH */ + /* !BEGIN!: Do not edit below this line. */ static const TclIntStubs tclIntStubs = { @@ -718,7 +727,7 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_div_2d, /* 16 */ 0, /* 17 */ TclBN_mp_exch, /* 18 */ - TclBN_mp_expt_u32, /* 19 */ + TclBN_mp_expt_n, /* 19 */ TclBN_mp_grow, /* 20 */ TclBN_mp_init, /* 21 */ TclBN_mp_init_copy, /* 22 */ diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index dad35b3..a6e48e9 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -77,7 +77,7 @@ declare 18 { void TclBN_mp_exch(mp_int *a, mp_int *b) } declare 19 { - mp_err MP_WUR TclBN_mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) + mp_err MP_WUR TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) } declare 20 { mp_err MP_WUR TclBN_mp_grow(mp_int *a, int size) diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index 35eb9f8..e62c90e 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -65,11 +65,13 @@ extern "C" { #endif MODULE_SCOPE mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b); MODULE_SCOPE mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r); -MODULE_SCOPE mp_err TclBN_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c); -MODULE_SCOPE mp_err TclBN_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c); -MODULE_SCOPE mp_err TclBN_mp_karatsuba_sqr(const mp_int *a, mp_int *b); -MODULE_SCOPE mp_err TclBN_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c); -MODULE_SCOPE mp_err TclBN_mp_toom_sqr(const mp_int *a, mp_int *b); +MODULE_SCOPE mp_err TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c); +MODULE_SCOPE mp_err TclBN_s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c); +MODULE_SCOPE mp_err TclBN_s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d); +MODULE_SCOPE mp_err TclBN_s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c); +MODULE_SCOPE mp_err TclBN_s_mp_karatsuba_sqr(const mp_int *a, mp_int *b); +MODULE_SCOPE mp_err TclBN_s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c); +MODULE_SCOPE mp_err TclBN_s_mp_toom_sqr(const mp_int *a, mp_int *b); MODULE_SCOPE mp_err TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c); MODULE_SCOPE mp_err TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs); MODULE_SCOPE mp_err TclBN_s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs); @@ -110,6 +112,7 @@ MODULE_SCOPE mp_err TclBN_mp_set_int(mp_int *a, unsigned long b); #define mp_expt_d TclBN_mp_expt_d #define mp_expt_d_ex TclBN_mp_expt_d_ex #define mp_expt_u32 TclBN_mp_expt_u32 +#define mp_expt_n TclBN_mp_expt_n #define mp_get_mag_u64 TclBN_mp_get_mag_u64 #define mp_grow TclBN_mp_grow #define mp_init TclBN_mp_init @@ -159,17 +162,18 @@ MODULE_SCOPE mp_err TclBN_mp_set_int(mp_int *a, unsigned long b); #define mp_xor TclBN_mp_xor #define mp_zero TclBN_mp_zero #define s_mp_add TclBN_s_mp_add -#define s_mp_balance_mul TclBN_mp_balance_mul -#define s_mp_karatsuba_mul TclBN_mp_karatsuba_mul -#define s_mp_karatsuba_sqr TclBN_mp_karatsuba_sqr +#define s_mp_balance_mul TclBN_s_mp_balance_mul +#define s_mp_div_3 TclBN_s_mp_div_3 +#define s_mp_karatsuba_mul TclBN_s_mp_karatsuba_mul +#define s_mp_karatsuba_sqr TclBN_s_mp_karatsuba_sqr #define s_mp_mul_digs TclBN_s_mp_mul_digs #define s_mp_mul_digs_fast TclBN_s_mp_mul_digs_fast #define s_mp_reverse TclBN_s_mp_reverse #define s_mp_sqr TclBN_s_mp_sqr #define s_mp_sqr_fast TclBN_s_mp_sqr_fast #define s_mp_sub TclBN_s_mp_sub -#define s_mp_toom_mul TclBN_mp_toom_mul -#define s_mp_toom_sqr TclBN_mp_toom_sqr +#define s_mp_toom_mul TclBN_s_mp_toom_mul +#define s_mp_toom_sqr TclBN_s_mp_toom_sqr #endif /* !TCL_WITH_EXTERNAL_TOMMATH */ #undef TCL_STORAGE_CLASS @@ -243,8 +247,7 @@ EXTERN mp_err TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, /* 18 */ EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b); /* 19 */ -EXTERN mp_err TclBN_mp_expt_u32(const mp_int *a, uint32_t b, - mp_int *c) MP_WUR; +EXTERN mp_err TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR; /* 20 */ EXTERN mp_err TclBN_mp_grow(mp_int *a, int size) MP_WUR; /* 21 */ @@ -386,7 +389,7 @@ typedef struct TclTomMathStubs { mp_err (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* 16 */ void (*reserved17)(void); void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */ - mp_err (*tclBN_mp_expt_u32) (const mp_int *a, uint32_t b, mp_int *c) MP_WUR; /* 19 */ + mp_err (*tclBN_mp_expt_n) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 19 */ mp_err (*tclBN_mp_grow) (mp_int *a, int size) MP_WUR; /* 20 */ mp_err (*tclBN_mp_init) (mp_int *a) MP_WUR; /* 21 */ mp_err (*tclBN_mp_init_copy) (mp_int *a, const mp_int *b) MP_WUR; /* 22 */ @@ -499,8 +502,8 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; /* Slot 17 is reserved */ #define TclBN_mp_exch \ (tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */ -#define TclBN_mp_expt_u32 \ - (tclTomMathStubsPtr->tclBN_mp_expt_u32) /* 19 */ +#define TclBN_mp_expt_n \ + (tclTomMathStubsPtr->tclBN_mp_expt_n) /* 19 */ #define TclBN_mp_grow \ (tclTomMathStubsPtr->tclBN_mp_grow) /* 20 */ #define TclBN_mp_init \ -- cgit v0.12 From 0951575eb7e3c67105c3f463358afba46f1a14a9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 28 Mar 2024 15:52:10 +0000 Subject: Fix windows build --- generic/tclTomMathDecls.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index e62c90e..49610c2 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -63,9 +63,9 @@ #ifdef __cplusplus extern "C" { #endif -MODULE_SCOPE mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b); -MODULE_SCOPE mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r); -MODULE_SCOPE mp_err TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c); +MODULE_SCOPE mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b); +MODULE_SCOPE mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r); +MODULE_SCOPE mp_err TclBN_mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c); MODULE_SCOPE mp_err TclBN_s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c); MODULE_SCOPE mp_err TclBN_s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d); MODULE_SCOPE mp_err TclBN_s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c); @@ -75,10 +75,10 @@ MODULE_SCOPE mp_err TclBN_s_mp_toom_sqr(const mp_int *a, mp_int *b); MODULE_SCOPE mp_err TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c); MODULE_SCOPE mp_err TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs); MODULE_SCOPE mp_err TclBN_s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs); -MODULE_SCOPE void TclBN_s_mp_reverse(unsigned char *s, size_t len); -MODULE_SCOPE mp_err TclBN_s_mp_sqr(const mp_int *a, mp_int *b); -MODULE_SCOPE mp_err TclBN_s_mp_sqr_fast(const mp_int *a, mp_int *b); -MODULE_SCOPE mp_err TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c); +MODULE_SCOPE void TclBN_s_mp_reverse(unsigned char *s, size_t len); +MODULE_SCOPE mp_err TclBN_s_mp_sqr(const mp_int *a, mp_int *b); +MODULE_SCOPE mp_err TclBN_s_mp_sqr_fast(const mp_int *a, mp_int *b); +MODULE_SCOPE mp_err TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c); MODULE_SCOPE const char *const TclBN_mp_s_rmap; MODULE_SCOPE const uint8_t TclBN_mp_s_rmap_reverse[]; MODULE_SCOPE const size_t TclBN_mp_s_rmap_reverse_sz; -- cgit v0.12 From 20b1651076663322baa44d45de13aed62f5cde16 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Fri, 29 Mar 2024 11:47:32 +0000 Subject: Added minor detail to file attr -shortname handling docs. --- doc/file.n | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/file.n b/doc/file.n index d37ed22..6c7c7a5 100644 --- a/doc/file.n +++ b/doc/file.n @@ -73,8 +73,10 @@ expand each path element to its long version. This attribute cannot be set. \fB\-readonly\fR gives the value or sets or clears the readonly attribute of the file. \fB\-shortname\fR gives a string where every path element is replaced with its short (8.3) version of the -name. This attribute cannot be set. \fB\-system\fR gives or sets or -clears the value of the system attribute of the file. +name if possible. For path elements that cannot be mapped to short +names, the long name is retained. This attribute cannot be set. +\fB\-system\fR gives or sets or clears the value of the system +attribute of the file. .PP On Mac OS X and Darwin, \fB\-creator\fR gives or sets the Finder creator type of the file. \fB\-hidden\fR gives or sets or clears -- cgit v0.12 From f0fa5ca1840e9254e5fbd8f4c8035ee614a93a2c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 1 Apr 2024 20:07:23 +0000 Subject: Oops, ckalloc -> Tcl_Alloc --- generic/tclStrIdxTree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index f764d02..5410b55 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -156,7 +156,7 @@ TclStrIdxTreeFree( TclStrIdxTreeFree(tree->childTree.firstPtr); } t = tree, tree = tree->nextPtr; - ckfree(t); + Tcl_Free(t); } } @@ -239,7 +239,7 @@ TclStrIdxTreeBuildFromList( /* create lowercase reflection of the list keys */ - lwrv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*) * lstc); + lwrv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj*) * lstc); if (lwrv == NULL) { return TCL_ERROR; } @@ -288,7 +288,7 @@ TclStrIdxTreeBuildFromList( * but don't split by fulfilled child of found item ( ii->iii->iiii ) */ if (foundItem->length != (f - s)) { /* first split found item (insert one between parent and found + new one) */ - item = (TclStrIdx *)ckalloc(sizeof(TclStrIdx)); + item = (TclStrIdx *)Tcl_Alloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -306,7 +306,7 @@ TclStrIdxTreeBuildFromList( } } /* append item at end of found parent */ - item = (TclStrIdx *)ckalloc(sizeof(TclStrIdx)); + item = (TclStrIdx *)Tcl_Alloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -325,7 +325,7 @@ done: for (i = 0; i < lstc; i++) { Tcl_DecrRefCount(lwrv[i]); } - ckfree(lwrv); + Tcl_Free(lwrv); } if (ret != TCL_OK) { -- cgit v0.12 From dfda01d97f073673635b19ca1f6a2ee7ee94db16 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Thu, 4 Apr 2024 11:50:51 +0000 Subject: Possibly a fix for [080f846fd58958ef]: When updating the interest of a channel, don't schedule the channel handler timer if a nonblocking channel doesn't yet have a buffer or if the buffer is empty or overflowing. Where asynchronous connection state is concerned, this should mean that the time won't be scheduled if the initial connection isn't established. --- generic/tclIO.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/generic/tclIO.c b/generic/tclIO.c index 4b5cb7d..c836342 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -8631,6 +8631,7 @@ UpdateInterest( { ChannelState *statePtr = chanPtr->state; /* State info for channel */ + ChannelBuffer *bufPtr = statePtr->outQueueHead; int mask = statePtr->interestMask; if (chanPtr->typePtr == NULL) { @@ -8711,7 +8712,15 @@ UpdateInterest( if (!statePtr->timer && mask & TCL_WRITABLE - && GotFlag(statePtr, CHANNEL_NONBLOCKING)) { + && GotFlag(statePtr, CHANNEL_NONBLOCKING) + && ( + bufPtr + && + !IsBufferEmpty(bufPtr) + && + !IsBufferFull(bufPtr) + ) + ) { TclChannelPreserve((Tcl_Channel)chanPtr); statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, -- cgit v0.12 From f0fa42f7094385b7cff6153d115cce5e5fd9bfa8 Mon Sep 17 00:00:00 2001 From: sebres Date: Sat, 6 Apr 2024 13:20:29 +0000 Subject: simple attempt to silence valgrind [167e0635db], improved error message by bad seconds (or -base), repair errorCode (index for badOption), remove unneeded code --- generic/tclClock.c | 22 ++++++++++++---------- tests/clock.test | 8 ++++++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 03a4a48..9aa8242 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -3322,7 +3322,7 @@ ClockParseFmtScnArgs( }; int optionIndex; /* Index of an option. */ int saw = 0; /* Flag == 1 if option was seen already. */ - int i; + int i, baseIdx; Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */ if ( flags & (CLC_SCN_ARGS) ) { @@ -3330,7 +3330,7 @@ ClockParseFmtScnArgs( opts->flags |= dataPtr->defFlags & (CLF_VALIDATE); } else { /* clock value (as current base) */ - opts->baseObj = objv[1]; + opts->baseObj = objv[(baseIdx = 1)]; saw |= (1 << CLC_ARGS_BASE); } @@ -3382,7 +3382,7 @@ ClockParseFmtScnArgs( opts->timezoneObj = objv[i+1]; break; case CLC_ARGS_BASE: - opts->baseObj = objv[i+1]; + opts->baseObj = objv[(baseIdx = i+1)]; break; case CLC_ARGS_VALIDATE: if ( !(flags & CLC_SCN_ARGS) ) { @@ -3441,7 +3441,7 @@ ClockParseFmtScnArgs( Tcl_Obj *baseObj = opts->baseObj; /* bypass integer recognition if looks like option "-now" */ if ( - (baseObj->length == 4 && baseObj->bytes && *(baseObj->bytes+1) == 'n') || + (baseObj->bytes && baseObj->length == 4 && *(baseObj->bytes+1) == 'n') || TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK ) { @@ -3450,17 +3450,19 @@ ClockParseFmtScnArgs( "-now", NULL }; int idx; - if (Tcl_GetIndexFromObj(NULL, baseObj, nowOpts, "seconds or -now", + if (Tcl_GetIndexFromObj(interp, baseObj, nowOpts, "seconds", TCL_EXACT, &idx) == TCL_OK ) { goto baseNow; } - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "expected integer but got \"%s\"", - TclGetString(baseObj))); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL); - i = 1; + if (baseObj->typePtr != &tclBignumType) { + Tcl_AppendResult(interp, " or integer", NULL); + } else { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "expected integer but got \"%s\"", TclGetString(baseObj))); + } + i = baseIdx; goto badOption; } /* diff --git a/tests/clock.test b/tests/clock.test index b3510fa..b966666 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -329,8 +329,8 @@ test clock-1.0.1 "clock format - wrong # args (compiled ensemble with invalid sy } [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}] test clock-1.1 "clock format - bad time" { - list [catch {clock format foo} msg] $msg -} {1 {expected integer but got "foo"}} + list [catch {clock format foo} msg opt] $msg [dict getd $opt -errorcode {}] +} {1 {bad seconds "foo": must be -now or integer} {CLOCK badOption foo}} test clock-1.2 "clock format - bad gmt val" { list [catch {clock format 0 -gmt foo} msg] $msg @@ -18696,6 +18696,10 @@ test clock-6.8 {input of seconds} { clock scan {9223372036854775807} -format %s -gmt true } 9223372036854775807 +test clock-6.8b "clock scan - bad base" { + list [catch {clock scan "" -base foo -gmt 1} msg opt] $msg [dict getd $opt -errorcode {}] +} {1 {bad seconds "foo": must be -now or integer} {CLOCK badOption foo}} + test clock-6.9 {input of seconds - overflow} { list [catch {clock scan -9223372036854775809 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""] } {1 {integer value too large to represent} {CLOCK dateTooLarge}} -- cgit v0.12 From 3eae990587282881a59c302899fd3f67006845c4 Mon Sep 17 00:00:00 2001 From: sebres Date: Sat, 6 Apr 2024 13:48:46 +0000 Subject: more improvements for overflow cases (always proper message, errorCode, correct badOption value) --- generic/tclClock.c | 13 +++++++------ tests/clock.test | 26 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 9aa8242..f79a5b4 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -3456,12 +3456,11 @@ ClockParseFmtScnArgs( goto baseNow; } - if (baseObj->typePtr != &tclBignumType) { - Tcl_AppendResult(interp, " or integer", NULL); - } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "expected integer but got \"%s\"", TclGetString(baseObj))); + if (baseObj->typePtr == &tclBignumType) { + goto baseOverflow; } + + Tcl_AppendResult(interp, " or integer", NULL); i = baseIdx; goto badOption; } @@ -3476,8 +3475,10 @@ ClockParseFmtScnArgs( if ( baseObj->typePtr == &tclBignumType || baseVal < TCL_MIN_SECONDS || baseVal > TCL_MAX_SECONDS ) { +baseOverflow: Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]); - return TCL_ERROR; + i = baseIdx; + goto badOption; } } else { diff --git a/tests/clock.test b/tests/clock.test index b966666..3a43017 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -38184,14 +38184,32 @@ test clock-61.1 {overflow of a wide integer on output} {*}{ -body { clock format 0x8000000000000000 -format %s -gmt true } - -result {expected integer but got "0x8000000000000000"} + -result {integer value too large to represent} + -errorCode {CLOCK badOption 0x8000000000000000} + -returnCodes error +} +test clock-61.1b {overflow of a wide integer on base} {*}{ + -body { + clock scan "" -base 0x8000000000000000 -gmt true + } + -result {integer value too large to represent} + -errorCode {CLOCK badOption 0x8000000000000000} -returnCodes error } test clock-61.2 {overflow of a wide integer on output} {*}{ -body { clock format -0x8000000000000001 -format %s -gmt true } - -result {expected integer but got "-0x8000000000000001"} + -result {integer value too large to represent} + -errorCode {CLOCK badOption -0x8000000000000001} + -returnCodes error +} +test clock-61.2b {overflow of a wide integer on base} {*}{ + -body { + clock scan "" -base -0x8000000000000001 -gmt true + } + -result {integer value too large to represent} + -errorCode {CLOCK badOption -0x8000000000000001} -returnCodes error } test clock-61.3 {near-miss overflow of a wide integer on output, very large datetime (upper range)} { @@ -38203,10 +38221,10 @@ test clock-61.4 {near-miss overflow of a wide integer on output, very small date test clock-61.5 {overflow of possible date-time (upper range)} -body { clock format 0x00F0000000000001 -gmt true -} -returnCodes error -result {integer value too large to represent} +} -returnCodes error -result {integer value too large to represent} -errorCode {CLOCK badOption 0x00F0000000000001} test clock-61.6 {overflow of possible date-time (lower range)} -body { clock format -0x00F0000000000001 -gmt true -} -returnCodes error -result {integer value too large to represent} +} -returnCodes error -result {integer value too large to represent} -errorCode {CLOCK badOption -0x00F0000000000001} test clock-62.1 {Bug 1902423} {*}{ -setup {::tcl::clock::ClearCaches} -- cgit v0.12 From f5355790e845985f5865e4bf9de60824f495c536 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 8 Apr 2024 08:29:07 +0000 Subject: Fix [a6fb744b20]: missing file from distribution --- unix/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index e096f35..4a2c395 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -2334,7 +2334,7 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in gen $(DIST_INSTALL_DATA) $(TOP_DIR)/tests/*.test $(TOP_DIR)/tests/README \ $(TOP_DIR)/tests/*.bench $(TOP_DIR)/tests/*.tar.gz \ $(TOP_DIR)/tests/httpd $(TOP_DIR)/tests/*.tcl \ - $(TOP_DIR)/tests/auto-files.zip $(DISTDIR)/tests + $(TOP_DIR)/tests/*.zip $(DISTDIR)/tests @mkdir $(DISTDIR)/tests/auto0 for i in auto1 auto2 ; \ do \ -- cgit v0.12 From 5706177d94b4322a66c3990418043c1762b7337d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 9 Apr 2024 11:14:23 +0000 Subject: Move new Tcl_GetAliasObj() to slot 285 (old slot was used for Tcl_FreeResult() in 8.x) --- generic/tcl.decls | 13 +++++-------- generic/tclDecls.h | 24 ++++++++++++------------ generic/tclStubInit.c | 4 ++-- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/generic/tcl.decls b/generic/tcl.decls index 2bc1934..f57eb2e 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -470,11 +470,6 @@ declare 145 { declare 146 { int Tcl_Flush(Tcl_Channel chan) } -declare 147 { - int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd, - Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, - Tcl_Size *objcPtr, Tcl_Obj ***objvPtr) -} declare 149 { int TclGetAliasObj(Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, @@ -880,9 +875,11 @@ declare 284 { void Tcl_SetMainLoop(Tcl_MainLoopProc *proc) } -# Reserved for future use (8.0.x vs. 8.1) -# declare 285 { -# } +declare 285 { + int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd, + Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, + Tcl_Size *objcPtr, Tcl_Obj ***objvPtr) +} # Added in 8.1: diff --git a/generic/tclDecls.h b/generic/tclDecls.h index c867549..d261921 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -426,12 +426,7 @@ EXTERN Tcl_HashEntry * Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 146 */ EXTERN int Tcl_Flush(Tcl_Channel chan); -/* 147 */ -EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp, - const char *childCmd, - Tcl_Interp **targetInterpPtr, - const char **targetCmdPtr, Tcl_Size *objcPtr, - Tcl_Obj ***objvPtr); +/* Slot 147 is reserved */ /* Slot 148 is reserved */ /* 149 */ EXTERN int TclGetAliasObj(Tcl_Interp *interp, @@ -761,7 +756,12 @@ EXTERN int Tcl_UnstackChannel(Tcl_Interp *interp, EXTERN Tcl_Channel Tcl_GetStackedChannel(Tcl_Channel chan); /* 284 */ EXTERN void Tcl_SetMainLoop(Tcl_MainLoopProc *proc); -/* Slot 285 is reserved */ +/* 285 */ +EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp, + const char *childCmd, + Tcl_Interp **targetInterpPtr, + const char **targetCmdPtr, Tcl_Size *objcPtr, + Tcl_Obj ***objvPtr); /* 286 */ EXTERN void Tcl_AppendObjToObj(Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); @@ -2026,7 +2026,7 @@ typedef struct TclStubs { void (*reserved144)(void); Tcl_HashEntry * (*tcl_FirstHashEntry) (Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 145 */ int (*tcl_Flush) (Tcl_Channel chan); /* 146 */ - int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); /* 147 */ + void (*reserved147)(void); void (*reserved148)(void); int (*tclGetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 149 */ void * (*tcl_GetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr); /* 150 */ @@ -2164,7 +2164,7 @@ typedef struct TclStubs { int (*tcl_UnstackChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 282 */ Tcl_Channel (*tcl_GetStackedChannel) (Tcl_Channel chan); /* 283 */ void (*tcl_SetMainLoop) (Tcl_MainLoopProc *proc); /* 284 */ - void (*reserved285)(void); + int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); /* 285 */ void (*tcl_AppendObjToObj) (Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); /* 286 */ Tcl_Encoding (*tcl_CreateEncoding) (const Tcl_EncodingType *typePtr); /* 287 */ void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 288 */ @@ -2859,8 +2859,7 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_FirstHashEntry) /* 145 */ #define Tcl_Flush \ (tclStubsPtr->tcl_Flush) /* 146 */ -#define Tcl_GetAliasObj \ - (tclStubsPtr->tcl_GetAliasObj) /* 147 */ +/* Slot 147 is reserved */ /* Slot 148 is reserved */ #define TclGetAliasObj \ (tclStubsPtr->tclGetAliasObj) /* 149 */ @@ -3108,7 +3107,8 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_GetStackedChannel) /* 283 */ #define Tcl_SetMainLoop \ (tclStubsPtr->tcl_SetMainLoop) /* 284 */ -/* Slot 285 is reserved */ +#define Tcl_GetAliasObj \ + (tclStubsPtr->tcl_GetAliasObj) /* 285 */ #define Tcl_AppendObjToObj \ (tclStubsPtr->tcl_AppendObjToObj) /* 286 */ #define Tcl_CreateEncoding \ diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 1d8dd7a..2dcb747 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -966,7 +966,7 @@ const TclStubs tclStubs = { 0, /* 144 */ Tcl_FirstHashEntry, /* 145 */ Tcl_Flush, /* 146 */ - Tcl_GetAliasObj, /* 147 */ + 0, /* 147 */ 0, /* 148 */ TclGetAliasObj, /* 149 */ Tcl_GetAssocData, /* 150 */ @@ -1104,7 +1104,7 @@ const TclStubs tclStubs = { Tcl_UnstackChannel, /* 282 */ Tcl_GetStackedChannel, /* 283 */ Tcl_SetMainLoop, /* 284 */ - 0, /* 285 */ + Tcl_GetAliasObj, /* 285 */ Tcl_AppendObjToObj, /* 286 */ Tcl_CreateEncoding, /* 287 */ Tcl_CreateThreadExitHandler, /* 288 */ -- cgit v0.12 From 40eb0c491503308095cfadcb918205f8cbd6c91f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 9 Apr 2024 12:05:08 +0000 Subject: TCL_MIN_SECONDS/TCL_MAX_SECONDS should use 'LL', because the constants are > LONG_MAX on 32-bit platforms --- generic/tclDate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclDate.h b/generic/tclDate.h index cdef706..60aca7b 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -64,8 +64,8 @@ CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | \ CLF_DAYOFWEEK | CLF_ISO8601WEAK) -#define TCL_MIN_SECONDS -0x00F0000000000000L -#define TCL_MAX_SECONDS 0x00F0000000000000L +#define TCL_MIN_SECONDS -0x00F0000000000000LL +#define TCL_MAX_SECONDS 0x00F0000000000000LL #define TCL_INV_SECONDS (TCL_MIN_SECONDS-1) /* -- cgit v0.12 From 2be590933b8f279e5c7e7f11b6b6d1150018cbf2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 9 Apr 2024 15:07:59 +0000 Subject: Remove Tcl_NewIndexObj/Tcl_SetIndexObj. Since Tcl_Size is signed now, it doesn't add much value any more. --- doc/IntObj.3 | 13 ++++--------- generic/tclDecls.h | 8 -------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/doc/IntObj.3 b/doc/IntObj.3 index 98cba9b..2cc3593 100644 --- a/doc/IntObj.3 +++ b/doc/IntObj.3 @@ -8,7 +8,7 @@ .so man.macros .BS .SH NAME -Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_NewIndexObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_SetWideUIntObj, Tcl_SetIndexObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetWideUIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers +Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_SetWideUIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetWideUIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers .SH SYNOPSIS .nf \fB#include \fR @@ -25,9 +25,6 @@ Tcl_Obj * Tcl_Obj * \fBTcl_NewWideUIntObj\fR(\fIuwideValue\fR) .sp -Tcl_Obj * -\fBTcl_NewIndexObj\fR(\fIindexValue\fR) -.sp \fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR) .sp \fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR) @@ -36,8 +33,6 @@ Tcl_Obj * .sp \fBTcl_SetWideUIntObj\fR(\fIobjPtr, uwideValue\fR) .sp -\fBTcl_SetIndexObj\fR(\fIobjPtr, indexValue\fR) -.sp int \fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) .sp @@ -90,7 +85,7 @@ Unsigned wide integer value used to initialize or set a Tcl value. In Tcl 8.x, \fTcl_Size\f is actually the same as int. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, -\fBTcl_SetWideUIntObj\fR, \fBTcl_SetIndexObj\fR, +\fBTcl_SetWideUIntObj\fR, and \fBTcl_SetBignumObj\fR, this points to the value in which to store an integral value. For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR, \fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and @@ -136,12 +131,12 @@ The \fBmp_int\fR type is a multiple-precision integer type defined by the LibTomMath multiple-precision integer library. .PP The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR, -\fBTcl_NewWideUIntObj\fR, \fBTcl_NewIndexObj\fR, and \fBTcl_NewBignumObj\fR +\fBTcl_NewWideUIntObj\fR, and \fBTcl_NewBignumObj\fR routines each create and return a new Tcl value initialized to the integral value of the argument. The returned Tcl value is unshared. .PP The \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, -\fBTcl_SetWideUIntObj\fR, \fBTcl_SetIndexObj\fR, and \fBTcl_SetBignumObj\fR +\fBTcl_SetWideUIntObj\fR, and \fBTcl_SetBignumObj\fR routines each set the value of an existing Tcl value pointed to by \fIobjPtr\fR to the integral value provided by the other argument. The \fIobjPtr\fR argument must point to an unshared Tcl value. Any attempt to set the diff --git a/generic/tclDecls.h b/generic/tclDecls.h index dc942b0..e497928 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4086,14 +4086,6 @@ extern const TclStubs *tclStubsPtr; #define Tcl_BackgroundError(interp) Tcl_BackgroundException((interp), TCL_ERROR) #define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0) -#if TCL_MAJOR_VERSION > 8 -# define Tcl_NewIndexObj(value) (((Tcl_WideUInt)(value) > (((size_t)-1)>>1)) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideIntObj(value)) -# define Tcl_SetIndexObj(objPtr, value) (((Tcl_WideUInt)(value) > (((size_t)-1)>>1)) ? Tcl_SetWideIntObj(objPtr, -1) : Tcl_SetWideUIntObj(objPtr, value)) -#else -# define Tcl_NewIndexObj Tcl_NewIntObj -# define Tcl_SetIndexObj Tcl_SetIntObj -#endif - #if TCL_UTF_MAX < 4 # undef Tcl_UniCharToUtfDString # define Tcl_UniCharToUtfDString Tcl_Char16ToUtfDString -- cgit v0.12 From b4088024a52289a663d42a8ca2d640c90d013f31 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 9 Apr 2024 15:16:26 +0000 Subject: Update documentation --- doc/IntObj.3 | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/IntObj.3 b/doc/IntObj.3 index 2cc3593..7cc93c1 100644 --- a/doc/IntObj.3 +++ b/doc/IntObj.3 @@ -80,9 +80,6 @@ Long integer value used to initialize or set a Tcl value. Wide integer value used to initialize or set a Tcl value. .AP Tcl_WideUInt uwideValue in Unsigned wide integer value used to initialize or set a Tcl value. -.AP Tcl_Size indexValue in -\fTcl_Size\f value used to initialize or set a Tcl value. -In Tcl 8.x, \fTcl_Size\f is actually the same as int. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, \fBTcl_SetWideUIntObj\fR, -- cgit v0.12 From 19768f9f6ce6031c3b61b11dc8fd67013551dd62 Mon Sep 17 00:00:00 2001 From: dkf Date: Tue, 9 Apr 2024 15:23:22 +0000 Subject: Add ability to regenerate tclOOScript.h to Win build --- tools/makeHeader.tcl | 1 + win/Makefile.in | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/makeHeader.tcl b/tools/makeHeader.tcl index 17526e0..e20e336 100644 --- a/tools/makeHeader.tcl +++ b/tools/makeHeader.tcl @@ -108,6 +108,7 @@ namespace eval makeHeader { proc updateTemplateFile {headerFile scriptLines} { set f [open $headerFile "r+"] try { + chan configure $f -translation {auto lf} set content [split [chan read -nonewline $f] "\n"] updateTemplate content [stripSurround $scriptLines] chan seek $f 0 diff --git a/win/Makefile.in b/win/Makefile.in index 856a21c..e71c5f3 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -1109,6 +1109,16 @@ genstubs: "$(GENERIC_DIR_NATIVE)" \ "$(GENERIC_DIR_NATIVE)/tclOO.decls" +$(GENERIC_DIR)/tclOOScript.h: $(TOOL_DIR)/tclOOScript.tcl + @echo "Warning: tclOOScript.h may be out of date." + @echo "Developers may want to run \"make genscript\" to regenerate." + @echo "This warning can be safely ignored, do not report as a bug!" + +genscript: + $(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/makeHeader.tcl" \ + "$(ROOT_DIR_NATIVE)/tools/tclOOScript.tcl" \ + "$(GENERIC_DIR_NATIVE)/tclOOScript.h" + # # This target creates the HTML folder for Tcl & Tk and places it in # DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool @@ -1137,7 +1147,7 @@ html-tk: $(TCLSH) .PHONY: install-doc install-private-headers test test-tcl runtest shell .PHONY: gdb depend cleanhelp clean distclean packages install-packages .PHONY: test-packages clean-packages distclean-packages genstubs html -.PHONY: html-tcl html-tk +.PHONY: html-tcl html-tk genscript .PHONY: tclzipfile # DO NOT DELETE THIS LINE -- make depend depends on it. -- cgit v0.12 From d30a8fa3d452bd96dd59335d6f94e12310ef8e3e Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 10 Apr 2024 13:01:36 +0000 Subject: Use standard macro for freeing the internal rep --- generic/tclClockFmt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 96b6db4..b9ce546 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -670,8 +670,7 @@ ClockFmtObj_SetFromAny( (void)TclGetString(objPtr); /* free old internal representation */ - if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) - objPtr->typePtr->freeIntRepProc(objPtr); + TclFreeInternalRep(objPtr); /* initial state of format object */ ObjClockFmtScn(objPtr) = NULL; -- cgit v0.12 From a559960fa0128e5abf2817a1604ee29158716735 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 10 Apr 2024 13:18:37 +0000 Subject: [e155cedf33]: Error-handling in TclGetOpenMode() --- generic/tclIOCmd.c | 21 +++--- generic/tclIOUtil.c | 180 +++++++++++++++++++++++++++------------------------- generic/tclInt.h | 3 - tests/ioCmd.test | 15 ++++- 4 files changed, 116 insertions(+), 103 deletions(-) diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index 808ce97..f9d85b6 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -10,6 +10,7 @@ */ #include "tclInt.h" +#include "tclIO.h" /* * Callback structure for accept callback in a TCP server. @@ -40,9 +41,9 @@ static Tcl_ExitProc FinalizeIOCmdTSD; static Tcl_TcpAcceptProc AcceptCallbackProc; static Tcl_ObjCmdProc ChanPendingObjCmd; static Tcl_ObjCmdProc ChanTruncateObjCmd; -static void RegisterTcpServerInterpCleanup( - Tcl_Interp *interp, - AcceptCallback *acceptCallbackPtr); +static void RegisterTcpServerInterpCleanup( + Tcl_Interp *interp, + AcceptCallback *acceptCallbackPtr); static Tcl_InterpDeleteProc TcpAcceptCallbacksDeleteProc; static void TcpServerCloseProc(void *callbackData); static void UnregisterTcpServerInterpCleanupProc( @@ -546,7 +547,7 @@ Tcl_SeekObjCmd( if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } - if (Tcl_GetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) { + if (TclGetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) { return TCL_ERROR; } mode = SEEK_SET; @@ -1154,7 +1155,7 @@ Tcl_OpenObjCmd( if (!pipeline) { chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot); } else { - int mode, seekFlag, binary; + int mode, modeFlags; Tcl_Size cmdObjc; const char **cmdArgv; @@ -1162,13 +1163,13 @@ Tcl_OpenObjCmd( return TCL_ERROR; } - mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary); + mode = TclGetOpenMode(interp, modeString, &modeFlags); if (mode == -1) { chan = NULL; } else { int flags = TCL_STDERR | TCL_ENFORCE_MODE; - switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { + switch (mode & O_ACCMODE) { case O_RDONLY: flags |= TCL_STDOUT; break; @@ -1183,7 +1184,7 @@ Tcl_OpenObjCmd( break; } chan = Tcl_OpenCommandChannel(interp, cmdObjc, cmdArgv, flags); - if (binary && chan) { + if ((modeFlags & CHANNEL_RAW_MODE) && chan) { Tcl_SetChannelOption(interp, chan, "-translation", "binary"); } } @@ -1774,7 +1775,7 @@ Tcl_FcopyObjCmd( } switch (index) { case FcopySize: - if (Tcl_GetWideIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) { + if (TclGetWideIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) { return TCL_ERROR; } if (toRead < 0) { @@ -1901,7 +1902,7 @@ ChanTruncateObjCmd( * User is supplying an explicit length. */ - if (Tcl_GetWideIntFromObj(interp, objv[2], &length) != TCL_OK) { + if (TclGetWideIntFromObj(interp, objv[2], &length) != TCL_OK) { return TCL_ERROR; } if (length < 0) { diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 4f6a008..ec24535 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -16,6 +16,7 @@ */ #include "tclInt.h" +#include "tclIO.h" #ifdef _WIN32 # include "tclWinInt.h" #endif @@ -1342,14 +1343,20 @@ TclFSNormalizeToUniquePath( */ path = TclGetStringFromObj(pathPtr, &i); - if ( (i >= 3) && ( (path[0] == '/' && path[1] == '/') - || (path[0] == '\\' && path[1] == '\\') ) ) { - for ( i = 2; ; i++) { - if (path[i] == '\0') break; - if (path[i] == path[0]) break; + if ((i >= 3) && ((path[0] == '/' && path[1] == '/') + || (path[0] == '\\' && path[1] == '\\'))) { + for (i = 2; ; i++) { + if (path[i] == '\0') { + break; + } + if (path[i] == path[0]) { + break; + } } --i; - if (path[i] == ':') isVfsPath = 1; + if (path[i] == ':') { + isVfsPath = 1; + } } /* @@ -1414,51 +1421,20 @@ TclFSNormalizeToUniquePath( * * TclGetOpenMode -- * - * Obsolete. A limited version of TclGetOpenModeEx() which exists only to - * satisfy any extensions imprudently using it via Tcl's internal stubs - * table. - * - * Results: - * See TclGetOpenModeEx(). - * - * Side effects: - * See TclGetOpenModeEx(). - * - *--------------------------------------------------------------------------- - */ - -int -TclGetOpenMode( - Tcl_Interp *interp, /* Interpreter to use for error reporting. May - * be NULL. */ - const char *modeString, /* e.g. "r+" or "RDONLY CREAT". */ - int *seekFlagPtr) /* Sets this to 1 to tell the caller to seek to - EOF after opening the file, and - * 0 otherwise. */ -{ - int binary = 0; - return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary); -} - -/* - *--------------------------------------------------------------------------- - * - * TclGetOpenModeEx -- - * * Computes a POSIX mode mask for opening a file. * * Results: * The mode to pass to "open", or -1 if an error occurs. * * Side effects: - * Sets *seekFlagPtr to 1 to tell the caller to + * Sets *modeFlagPtr to 1 to tell the caller to * seek to EOF after opening the file, or to 0 otherwise. * - * Sets *binaryPtr to 1 to tell the caller to configure the channel as a - * binary channel, or to 0 otherwise. + * Adds CHANNEL_RAW_MODE to *modeFlagPtr to tell the caller + * to configure the channel as a binary channel. * - * If there is an error and interp is not NULL, sets interpreter result to - * an error message. + * If there is an error and interp is not NULL, sets + * interpreter result to an error message. * * Special note: * Based on a prototype implementation contributed by Mark Diekhans. @@ -1467,20 +1443,15 @@ TclGetOpenMode( */ int -TclGetOpenModeEx( +TclGetOpenMode( Tcl_Interp *interp, /* Interpreter, possibly NULL, to use for * error reporting. */ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ - int *seekFlagPtr, /* Sets this to 1 to tell the the caller to seek to - * EOF after opening the file, and 0 otherwise. */ - int *binaryPtr) /* Sets this to 1 to tell the caller to - * configure the channel for binary - * operations after opening the file. */ + int *modeFlagPtr) { int mode, c, gotRW; Tcl_Size modeArgc, i; - const char **modeArgv, *flag; -#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR) + const char **modeArgv = NULL, *flag; /* * Check for the simpler fopen-like access modes like "r" which are @@ -1488,9 +1459,8 @@ TclGetOpenModeEx( * lower-case first letter. */ - *seekFlagPtr = 0; - *binaryPtr = 0; - mode = 0; + *modeFlagPtr = 0; + mode = O_RDONLY; /* * Guard against wide characters before using byte-oriented routines. @@ -1500,7 +1470,6 @@ TclGetOpenModeEx( && islower(UCHAR(modeString[0]))) { /* INTL: ISO only. */ switch (modeString[0]) { case 'r': - mode = O_RDONLY; break; case 'w': mode = O_WRONLY|O_CREAT|O_TRUNC; @@ -1512,7 +1481,7 @@ TclGetOpenModeEx( */ mode = O_WRONLY|O_CREAT|O_APPEND; - *seekFlagPtr = 1; + *modeFlagPtr |= 1; break; default: goto error; @@ -1529,11 +1498,10 @@ TclGetOpenModeEx( * 1773127] */ - mode &= ~(O_RDONLY|O_WRONLY|O_APPEND); - mode |= O_RDWR; + mode = (mode & ~(O_ACCMODE|O_APPEND)) | O_RDWR; break; case 'b': - *binaryPtr = 1; + *modeFlagPtr |= CHANNEL_RAW_MODE; break; default: goto error; @@ -1545,11 +1513,11 @@ TclGetOpenModeEx( return mode; error: - *seekFlagPtr = 0; - *binaryPtr = 0; + *modeFlagPtr = 0; if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "illegal access mode \"%s\"", modeString)); + Tcl_SetErrorCode(interp, "TCL", "OPENMODE", "INVALID", (char *)NULL); } return -1; } @@ -1561,11 +1529,16 @@ TclGetOpenModeEx( */ if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) { + invAccessMode: if (interp != NULL) { Tcl_AddErrorInfo(interp, "\n while processing open access modes \""); Tcl_AddErrorInfo(interp, modeString); Tcl_AddErrorInfo(interp, "\""); + Tcl_SetErrorCode(interp, "TCL", "OPENMODE", "INVALID", (char *)NULL); + } + if (modeArgv) { + ckfree((void *)modeArgv); } return -1; } @@ -1575,24 +1548,55 @@ TclGetOpenModeEx( flag = modeArgv[i]; c = flag[0]; if ((c == 'R') && (strcmp(flag, "RDONLY") == 0)) { - mode = (mode & ~RW_MODES) | O_RDONLY; + if (gotRW) { + invRW: + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid access mode \"%s\": modes RDONLY, " + "RDWR, and WRONLY cannot be combined", flag)); + } + goto invAccessMode; + } + mode = (mode & ~O_ACCMODE) | O_RDONLY; gotRW = 1; } else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) { - mode = (mode & ~RW_MODES) | O_WRONLY; + if (gotRW) { + goto invRW; + } + mode = (mode & ~O_ACCMODE) | O_WRONLY; gotRW = 1; } else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) { - mode = (mode & ~RW_MODES) | O_RDWR; + if (gotRW) { + goto invRW; + } + mode = (mode & ~O_ACCMODE) | O_RDWR; gotRW = 1; } else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) { + if (mode & O_APPEND) { + accessFlagRepeated: + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "access mode \"%s\" repeated", flag)); + } + goto invAccessMode; + } mode |= O_APPEND; - *seekFlagPtr = 1; + *modeFlagPtr |= 1; } else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) { + if (mode & O_CREAT) { + goto accessFlagRepeated; + } mode |= O_CREAT; } else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) { + if (mode & O_EXCL) { + goto accessFlagRepeated; + } mode |= O_EXCL; - } else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) { #ifdef O_NOCTTY + if (mode & O_NOCTTY) { + goto accessFlagRepeated; + } mode |= O_NOCTTY; #else if (interp != NULL) { @@ -1600,12 +1604,14 @@ TclGetOpenModeEx( "access mode \"%s\" not supported by this system", flag)); } - ckfree(modeArgv); - return -1; + goto invAccessMode; #endif } else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) { #ifdef O_NONBLOCK + if (mode & O_NONBLOCK) { + goto accessFlagRepeated; + } mode |= O_NONBLOCK; #else if (interp != NULL) { @@ -1613,33 +1619,35 @@ TclGetOpenModeEx( "access mode \"%s\" not supported by this system", flag)); } - ckfree(modeArgv); - return -1; + goto invAccessMode; #endif - } else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) { + if (mode & O_TRUNC) { + goto accessFlagRepeated; + } mode |= O_TRUNC; } else if ((c == 'B') && (strcmp(flag, "BINARY") == 0)) { - *binaryPtr = 1; + if (*modeFlagPtr & CHANNEL_RAW_MODE) { + goto accessFlagRepeated; + } + *modeFlagPtr |= CHANNEL_RAW_MODE; } else { - if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "invalid access mode \"%s\": must be RDONLY, WRONLY, " - "RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK," - " or TRUNC", flag)); + "invalid access mode \"%s\": must be APPEND, BINARY, " + "CREAT, EXCL, NOCTTY, NONBLOCK, RDONLY, RDWR, " + "TRUNC, or WRONLY", flag)); } - ckfree(modeArgv); - return -1; + goto invAccessMode; } } - ckfree(modeArgv); + ckfree((void *)modeArgv); if (!gotRW) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "access mode must include either RDONLY, WRONLY, or RDWR", + "access mode must include either RDONLY, RDWR, or WRONLY", -1)); } return -1; @@ -2204,14 +2212,14 @@ Tcl_FSOpenFileChannel( fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) { - int mode, seekFlag, binary; + int mode, modeFlags; /* * Parse the mode to determine whether to seek at the outset * and/or set the channel into binary mode. */ - mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary); + mode = TclGetOpenMode(interp, modeString, &modeFlags); if (mode == -1) { return NULL; } @@ -2230,7 +2238,7 @@ Tcl_FSOpenFileChannel( * Seek and/or set binary mode as determined above. */ - if (seekFlag && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END) + if ((modeFlags & 1) && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END) < (Tcl_WideInt) 0) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -2240,7 +2248,7 @@ Tcl_FSOpenFileChannel( Tcl_Close(NULL, retVal); return NULL; } - if (binary) { + if (modeFlags & CHANNEL_RAW_MODE) { Tcl_SetChannelOption(interp, retVal, "-translation", "binary"); } return retVal; @@ -4353,16 +4361,14 @@ Tcl_FSCopyDirectory( int Tcl_FSRemoveDirectory( - Tcl_Obj *pathPtr, /* The pathname of the directory to be removed. - */ + Tcl_Obj *pathPtr, /* The pathname of the directory to be removed. */ int recursive, /* If zero, removes only an empty directory. * Otherwise, removes the directory and all its * contents. */ Tcl_Obj **errorPtr) /* If not NULL and an error occurs, stores a * place to store a a pointer to a new * object having a refCount of 1 and containing - * the name of the file that produced an error. - * */ + * the name of the file that produced an error. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); diff --git a/generic/tclInt.h b/generic/tclInt.h index 09c47d5..077708e 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3222,9 +3222,6 @@ MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp, Tcl_Obj *value, int *code); MODULE_SCOPE Proc * TclGetLambdaFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **nsObjPtrPtr); -MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp, - const char *modeString, int *seekFlagPtr, - int *binaryPtr); MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr); MODULE_SCOPE Tcl_Obj * TclGetSourceFromFrame(CmdFrame *cfPtr, int objc, Tcl_Obj *const objv[]); diff --git a/tests/ioCmd.test b/tests/ioCmd.test index 2b9aed6..91e53fe 100644 --- a/tests/ioCmd.test +++ b/tests/ioCmd.test @@ -497,14 +497,14 @@ unmatched open brace in list \"open \$path(test3) \"FOO \\{BAR BAZ\"\"" test iocmd-12.7 {POSIX open access modes: errors} { list [catch {open $path(test3) {FOO BAR BAZ}} msg] $msg -} {1 {invalid access mode "FOO": must be RDONLY, WRONLY, RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK, or TRUNC}} +} {1 {invalid access mode "FOO": must be APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK, RDONLY, RDWR, TRUNC, or WRONLY}} test iocmd-12.8 {POSIX open access modes: errors} { list [catch {open $path(test3) {TRUNC CREAT}} msg] $msg -} {1 {access mode must include either RDONLY, WRONLY, or RDWR}} +} {1 {access mode must include either RDONLY, RDWR, or WRONLY}} close [open $path(test3) w] test iocmd-12.9 {POSIX open access modes: BINARY} { list [catch {open $path(test1) BINARY} msg] $msg -} {1 {access mode must include either RDONLY, WRONLY, or RDWR}} +} {1 {access mode must include either RDONLY, RDWR, or WRONLY}} test iocmd-12.10 {POSIX open access modes: BINARY} { set f [open $path(test1) {WRONLY BINARY TRUNC}] puts $f a @@ -527,6 +527,15 @@ test iocmd-12.11 {POSIX open access modes: BINARY} { close $f set result } H +test iocmd-12.12 {POSIX open access modes: errors} { + list [catch {open $path(test3) {RDWR WRONLY}} msg] $msg +} {1 {invalid access mode "WRONLY": modes RDONLY, RDWR, and WRONLY cannot be combined}} +test iocmd-12.13 {POSIX open access modes: errors} { + list [catch {open $path(test3) {BINARY BINARY}} msg] $msg +} {1 {access mode "BINARY" repeated}} +test iocmd-12.14 {POSIX open access modes: errors} { + list [catch {open $path(test3) {TRUNC}} msg] $msg +} {1 {access mode must include either RDONLY, RDWR, or WRONLY}} test iocmd-13.1 {errors in open command} { list [catch {open} msg] $msg -- cgit v0.12 From 055ae86887960b4b2258778c0e5b6d7fc95e2663 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 10 Apr 2024 15:35:05 +0000 Subject: One more TclHasInternalRep() --- generic/tclStringObj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 81e6b18..73391fe 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3193,7 +3193,7 @@ TclStringCat( binary = 0; if (ov > objv+1 && ISCONTINUATION(TclGetString(objPtr))) { forceUniChar = 1; - } else if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) { + } else if ((objPtr->typePtr) && TclHasInternalRep(objPtr, &tclStringType)) { /* Prevent shimmer of non-string types. */ allowUniChar = 0; } -- cgit v0.12 -- cgit v0.12 From c31c0e64c17898357ae04a4a75b21500844cfdd7 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 10 Apr 2024 17:52:46 +0000 Subject: Start on consolidating chan related docs --- doc/chan.n | 321 ++++++++++++++++++++++++++++++++++++++++++++++--------- doc/close.n | 94 +--------------- doc/eof.n | 45 +------- doc/fblocked.n | 52 +-------- doc/fconfigure.n | 265 +-------------------------------------------- doc/fileevent.n | 136 +---------------------- doc/flush.n | 29 +---- doc/gets.n | 85 +-------------- doc/puts.n | 85 +-------------- doc/read.n | 142 +----------------------- 10 files changed, 299 insertions(+), 955 deletions(-) diff --git a/doc/chan.n b/doc/chan.n index b03d6e4..4054da6 100644 --- a/doc/chan.n +++ b/doc/chan.n @@ -33,17 +33,14 @@ otherwise. .TP \fBchan close \fIchannelName\fR ?\fIdirection\fR? . -Closes and destroys the named channel, deleting any existing event handlers -established for the channel, and returns the empty string. If \fIdirection\fR is -given, it is -.QW\fBread\fR -or -.QW\fBwrite\fR -or any unique abbreviation of those words, and only that side of the channel is -closed. I.e. a read-write channel may become read-only or write-only. -Closing a read-only channel for reading, or closing a write-only channel for -writing is the same as simply closing the channel. It is an error to close a -read-only channel for writing or to close a write-only channel for reading. +Closes and destroys the named channel deleting any existing event handlers +established for the channel. The command returns the empty string. If +\fIdirection\fR is given, it is \fBread\fR, or \fBwrite\fR, or any unique +abbreviation of those words, and only that side of the channel is closed. I.e. a +read-write channel may become read-only or write-only. Closing a read-only +channel for reading, or closing a write-only channel for writing is the same as +simply closing the channel. It is an error to close a read-only channel for +writing or to close a write-only channel for reading. .RS .PP When a channel is closed for writing, any buffered output on the channel is @@ -90,7 +87,7 @@ restores the previous behavior. .TP \fBchan configure \fIchannelName\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... . -Configures or reports the configuration of \fIchannelName\fR. +Configures or retrieves the configuration of the channel \fIchannelName\fR. .RS .PP If no \fIoptionName\fR or \fIvalue\fR arguments are given, @@ -109,11 +106,11 @@ relevant documentation. For example, additional options are documented for .TP \fB\-blocking\fI boolean\fR . -If \fB\-blocking\fR is set to \fBtrue\fR, which is the default, reading from or -writing to the channel may cause the process to block indefinitely. Otherwise, +If \fB\-blocking\fR is set to \fBtrue\fR (default), reading the channel +or writing to it may cause the process to block indefinitely. Otherwise, operations such as \fBchan gets\fR, \fBchan read\fR, \fBchan puts\fR, \fBchan flush\fR, and \fBchan close\fR take care not to block. Non-blocking mode in -generally requires that the event loop is entered, e.g. by calling +general requires that the event loop is entered, e.g. by calling \fBTcl_DoOneEvent\fR or \fBvwait\fR or by using Tk, to give Tcl a chance to process events on the channel. .\" OPTION: -buffering @@ -135,9 +132,9 @@ connect to terminal-like devices, the default value is \fBline\fR. For any input or output buffers subsequently allocated for this channel. .\" OPTION: -encoding .TP -\fB\-encoding\fR ?\fIname\fR? +\fB\-encoding\fR \fIname\fR . -Sets the encoding of the channel. \fIname\fR is either one of the names +Sets the encoding of the channel to \fIname\fR which should be one of the names returned by \fBencoding names\fR, or .QW \fBbinary\fR \&. Input is converted from the encoding into Unicode, and output is converted @@ -194,7 +191,7 @@ end-of-line character. .RS .PP Returns the input translation for a read-only channel, the output translation -for a write-only channel, and both the input translation and the the output +for a write-only channel, and both the input translation and the output translation for a read-write channel. When two translations are given, they are the input and output translation, respectively. When only one translation is given for a read-write channel, it is the translation for both input and @@ -343,7 +340,7 @@ handler, the handler is deleted if \fIscript\fR returns an error so that it is not evaluated again. .PP Without an event handler, \fBchan gets\fR or \fBchan read\fR on a channel in -blocking mode may block until data becomes available, become during which the +blocking mode may block until data becomes available, during which the thread is unable to perform other work or respond to events on other channels. This could cause the application to appear to .QW "freeze up" @@ -386,23 +383,47 @@ while all buffered output is flushed in the background as soon as possible. .TP \fBchan gets \fIchannelName\fR ?\fIvarName\fR? . -Returns the next line from the channel, removing the trailing line feed, or if -\fIvarName\fR is given, assigns the line to that variable and returns the -number of characters read. -the line that was read, removing the trailing line feed, or returns the -empty string if there is no data to return and the end of the file has been -reached, or in non-blocking mode, if no complete line is currently available. -If \fIvarName\fR is given, assigns the line that was read to variable named -\fIvarName\fR and returns the number of characters that were read, or -1 if -there no data available and the end of the channel was reached or the channel -is in non-blocking mode. +Reads a line from the channel consisting of all characters up to the next +end-of-line sequence or until end of file is seen. The line feed character +corresponding to end-of-line sequence is not included as part of the line. +If the \fIvarName\fR argument is specified, the line is stored in the variable +of that name and the command returns the length of the line. If \fIvarName\fR +is not specified, the command returns the line itself as the result of the command. +.RS +.PP +If a complete line is not available and the channel is not at EOF, the command +will block in the case of a blocking channel. For non-blocking channels, the +command will return the empty string as the result in the case of \fIvarName\fR +not specified and -1 if it is. +.RE .RS .PP -If the end of the channel is reached the data read so far is returned or -assigned to \fIvarName\fR. When \fIvarName\fR is not given, \fBchan eof\fR may -indicate that the empty string means that the end of the data has been reached, -and \fBchan blocked\fR may indicate that that the empty string means there -isn't currently enough data do return the next line. +If a blocking channel is already at EOF, the command returns an empty string if +\fIvarName\fR is not specified. Note an empty string result can also be returned +when a blank line (no characters before the next end of line sequence). The two +cases can be distinguished by calling the \fBchan eof\fR command to check for +end of file. If \fIvarName\fR is specified, the command returns -1 on end of file. +There is no ambiguity in this case because blank lines result in 0 being returned. +.RE +.RS +.PP +If a non-blocking channel is already at EOF, the command returns an empty line +if \fIvarName\fR is not specified. This can be distinguished from an empty line +being returned by either a blank line being read or a full line not being available +through the use of the \fBchan eof\fR and \fBchan blocked\fR commands. If +\fBchan eof\fR returns true, the channel is at EOF. If \fBchan blocked\fR returns +true, a full line was not available. If both commands return false, an empty +line was read. If \fIvarName\fR was specified for a non-bocking channel at EOF, +the command returns -1. This can be distinguished from full line not being +available either by \fBchan eof\fR or \fBchan blocked\fR as above. Note that +when \fIvarName\fR is specified, there is no need to distinguish between eof +and blank lines as the latter will result in the command returning 0. +.PP +If the encoding profile \fBstrict\fR is in effect for the channel, the command +will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding +errors are encountered in the channel input data. The file pointer remains +unchanged and it is possible to introspect, and in some cases recover, by +changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: names .TP @@ -509,8 +530,8 @@ given, the trailing line feed is not written. The default channel is \fBstdout\fR. .RS .PP -Each line feed in the output is translated according to the configuration of -\fB\-translation\fR. +Each line feed in the output is translated to the appropriate end of line +sequence as per the \fB\-translation\fR configuration setting of the channel. .PP Because Tcl internally buffers output, characters written to a channel may not immediately be available at the destination. Tcl normally delays output until @@ -518,17 +539,21 @@ the buffer is full or the channel is closed. \fBchan flush\fR forces output in the direction of the destination. .PP When the output for a channel in blocking mode fills up, \fBchan puts\fR blocks -until space in the buffer is available again, but for a channel in non-blocking -mode, it returns immediately and the data is written in the background as fast -possible, constrained by the speed at which as the destination accepts it. -Output to a channel in non-blocking mode only works properly when the -application enters the event loop, giving Tcl a chance to find out that the -destination is ready to accept more data. When a channel is in non-blocking -mode, Tcl's internal buffers can hold an arbitrary amount of data, possibly -consuming a large amount of memory. To avoid wasting memory, channels in -non-blocking mode should normally be handled using \fBchan event\fR, where the -application only invokes \fBchan puts\fR after being recently notified through -a file event handler that the channel is ready for more output data. +until space in the buffer is available again. On the other hand for a channel in +non-blocking mode, it returns immediately and the data is written in the +background as fast possible, constrained by the speed at which as the +destination accepts it. Output to a channel in non-blocking mode only works +properly when the application enters the event loop. When a channel is in +non-blocking mode, Tcl's internal buffers can hold an arbitrary amount of data, +possibly consuming a large amount of memory. To avoid wasting memory, channels +in non-blocking mode should normally be handled using \fBchan event\fR, where +the application only invokes \fBchan puts\fR after being notified through a file +event handler that the channel is ready for more output data. +.PP +The command will raise an error exception with POSIX error code \fBEILSEQ\fR if +the encoding profile \fBstrict\fR is in effect for the channel and the output +data cannot be encoded in the encoding configured for the channel. Data +may be partially written to the channel in this case. .RE .\" METHOD: read .TP @@ -541,7 +566,7 @@ Reads and returns the next \fInumChars\fR characters from the channel. If are read, or if the channel is in non-blocking mode, all currently-available characters are read. If there is an error on the channel, reading ceases and an error is returned. If \fInumChars\fR is not given, \fB\-nonewline\fR -may be given, causing any any trailing line feed to be trimmed. +may be given, causing any trailing line feed to be trimmed. .RS .PP If the channel is in non-blocking mode, fewer characters than requested may be @@ -560,6 +585,21 @@ handler since most serial ports are comparatively slow. It is entirely possible to get a \fBreadable\fR event for each individual character. In blocking mode, \fBchan read\fR blocks forever when reading to the end of the data if there is no \fBchan configure -eofchar\fR configured for the channel. +.PP +If the encoding profile \fBstrict\fR is in effect for the channel, the command +will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding +errors are encountered in the channel input data. If the channel is in blocking +mode, the error is thrown after advancing the file pointer to the beginning of +the invalid data. The successfully decoded leading portion of the data prior to +the error location is returned as the value of the \fB\-data\fR key of the error +option dictionary. If the channel is in non-blocking mode, the successfully +decoded portion of data is returned by the command without an error +exception being raised. A subsequent read will start at the invalid data +and immediately raise a \fBEILSEQ\fR POSIX error exception. Unlike the +blocking channel case, the \fB\-data\fR key is not present in the +error option dictionary. In the case of exception thrown due to encoding +errors, it is possible to introspect, and in some cases recover, by +changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: seek .TP @@ -602,6 +642,13 @@ bytes, or to the current position in bytes if \fIlength\fR is omitted. .SH EXAMPLES .SS "SIMPLE CHANNEL OPERATION EXAMPLES" .PP +Instruct Tcl to always send output to \fBstdout\fR immediately, +whether or not it is to a terminal: +.PP +.CS +\fBfconfigure\fR stdout -buffering none +.CE +.PP In the following example a file is opened using the encoding CP1252, which is common on Windows, searches for a string, rewrites that part, and truncates the file two lines later. @@ -635,6 +682,67 @@ while {[\fBchan gets\fR $f line] >= 0} { \fBchan close\fR $f .CE .PP +This example illustrates flushing of a channel. The user is +prompted for some information. Because the standard input channel +is line buffered, it must be flushed for the user to see the prompt. +.PP +.CS +chan puts -nonewline "Please type your name: " +\fBchan flush\fR stdout +chan gets stdin name +chan puts "Hello there, $name!" +.CE +.PP +This example reads a file one line at a time and prints it out with +the current line number attached to the start of each line. +.PP +.CS +set chan [open "some.file.txt"] +set lineNumber 0 +while {[\fBchan gets\fR $chan line] >= 0} { + chan puts "[incr lineNumber]: $line" +} +chan close $chan +.CE +.PP +In this example illustrating event driven reads, +\fBGetData\fR will be called with the channel as an +argument whenever $chan becomes readable. The \fBread\fR call will +read whatever binary data is currently available without blocking. +Here the channel has the fileevent removed when an end of file +occurs to avoid being continually called (see above). Alternatively +the channel may be closed on this condition. +.PP +.CS +proc GetData {chan} { + set data [chan read $chan] + chan puts "[string length $data] $data" + if {[chan eof $chan]} { + chan event $chan readable {} + } +} + +chan configure $chan -blocking 0 -encoding binary +\fBchan event\fR $chan readable [list GetData $chan] +.CE +.PP +The next example is similar but uses \fBchan gets\fR to read +line-oriented data. +.PP +.CS +proc GetData {chan} { + if {[chan gets $chan line] >= 0} { + chan puts $line + } + if {[chan eof $chan]} { + chan close $chan + } +} + +chan configure $chan -blocking 0 -buffering line -translation crlf +\fBchan event\fR $chan readable [list GetData $chan] +.CE +.PP A network server that echoes its input line-by-line without preventing servicing of other connections at the same time: .PP @@ -671,6 +779,120 @@ proc echoLine {chan clientName} { socket -server connect 12345 vwait forever .CE +.PP +The following example reads a PPM-format image from a file +combining ASCII and binary content. +.PP +.CS +# Open the file and put it into Unix ASCII mode +set f [open teapot.ppm] +\fBchan configure\fR $f -encoding ascii -translation lf + +# Get the header +if {[chan gets $f] ne "P6"} { + error "not a raw\-bits PPM" +} + +# Read lines until we have got non-comment lines +# that supply us with three decimal values. +set words {} +while {[llength $words] < 3} { + chan gets $f line + if {[string match "#*" $line]} continue + lappend words {*}[join [scan $line %d%d%d]] +} + +# Those words supply the size of the image and its +# overall depth per channel. Assign to variables. +lassign $words xSize ySize depth + +# Now switch to binary mode to pull in the data, +# one byte per channel (red,green,blue) per pixel. +\fBchan configure\fR $f -translation binary +set numDataBytes [expr {3 * $xSize * $ySize}] +set data [chan read $f $numDataBytes] + +close $f +.CE + +.SS "ENCODING ERROR EXAMPLES" +.PP +The example below illustrates handling of an encoding error encountered +during channel input. First, creation of a test file containing +the invalid UTF-8 sequence (\fBA \\xC3 B\fR): +.PP +.CS +% set f [open test_A_195_B.txt wb]; chan puts -nonewline $f A\\xC3B; chan close $f +.CE +.PP +An attempt to read the file will result in an encoding error which is +then introspected by switching the channel to binary mode. Note in the +example that when the error is reported the file position remains +unchanged so that the \fBchan gets\fR during recovery returns the +full line. +.PP +.CS +% set f [open test_A_195_B.txt r] +file384b6a8 +% chan configure $f -encoding utf-8 -profile strict +% catch {chan gets $f} e d +1 +% set d +-code 1 -level 0 +-errorstack {INNER {invokeStk1 gets file384b6a8}} +-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} +-errorinfo {...} -errorline 1 +% chan tell $f +0 +% chan configure $f -encoding binary -profile strict +% chan gets $f +AÃB +.CE +.PP +The following example is similar to the above but demonstrates recovery after a +blocking read. The successfully decoded data "A" is returned in the error options +dictionary key \fB\-data\fR. The file position is advanced on the encoding error +position 1. The data at the error position is thus recovered by the next +\fBchan read\fR command. +.PP +.CS +% set f [open test_A_195_B.txt r] +file35a65a0 +% chan configure $f -encoding utf-8 -profile strict -blocking 1 +% catch {chan read $f} e d +1 +% set d +-data A -code 1 -level 0 +-errorstack {INNER {invokeStk1 read file35a65a0}} +-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} +-errorinfo {...} -errorline 1 +% chan tell $f +1 +% chan configure $f -encoding binary -profile strict +% chan read $f +ÃB +% chan close $f +.CE +.PP +Finally the same example, but this time with a non-blocking channel. +.PP +.CS +% set f [open test_A_195_B.txt r] +file35a65a0 +% chan configure $f -encoding utf-8 -profile strict -blocking 0 +% chan read $f +A +% chan tell $f +1 +% catch {chan read $f} e d +1 +% set d +-code 1 -level 0 +-errorstack {INNER {invokeStk1 read file384b228}} +-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} +-errorinfo {...} -errorline 1 +.CE + .SS "CHANNEL COPY EXAMPLES" .PP The first example transfers the contents of one channel exactly to @@ -760,7 +982,8 @@ close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n), fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n), socket(n), tell(n), refchan(n), transchan(n) .SH KEYWORDS -channel, input, output, events, offset +blocking, channel, end of file, events, input, non-blocking, +offset, output, readable, writable '\" Local Variables: '\" mode: nroff '\" End: diff --git a/doc/close.n b/doc/close.n index 2066583..900679e 100644 --- a/doc/close.n +++ b/doc/close.n @@ -15,98 +15,10 @@ close \- Close an open channel \fBclose \fIchannelId\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)? .BE .SH DESCRIPTION -.PP -Closes or half-closes the channel given by \fIchannelId\fR. \fBchan close\fR -is another name for this command. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), -the return value from an invocation of \fBopen\fR or \fBsocket\fR, or -the result of a channel creation command provided by a Tcl extension. -.PP -The single-argument form is a simple -.QW "full-close" : -all buffered output is flushed to the channel's output device, -any buffered input is discarded, the underlying file or device is closed, -and \fIchannelId\fR becomes unavailable for use. -.PP -If the channel is blocking, the command does not return until all output -is flushed. -If the channel is nonblocking and there is unflushed output, the -channel remains open and the command -returns immediately; output will be flushed in the background and the -channel will be closed when all the flushing is complete. -.PP -If \fIchannelId\fR is a blocking channel for a command pipeline then -\fBclose\fR waits for the child processes to complete. -.PP -If the channel is shared between interpreters, then \fBclose\fR -makes \fIchannelId\fR unavailable in the invoking interpreter but has no -other effect until all of the sharing interpreters have closed the -channel. -When the last interpreter in which the channel is registered invokes -\fBclose\fR, the cleanup actions described above occur. See the -\fBinterp\fR command for a description of channel sharing. -.PP -Channels are automatically closed when an interpreter is destroyed and -when the process exits. -From 8.6 on (TIP#398), nonblocking channels are no longer switched to -blocking mode when exiting; this guarantees a timely exit even when the -peer or a communication channel is stalled. To ensure proper flushing of -stalled nonblocking channels on exit, one must now either (a) actively -switch them back to blocking or (b) use the environment variable -\fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to -.QW \fB0\fR -restores the previous behavior. -.PP -The command returns an empty string, and may generate an error if -an error occurs while flushing output. If a command in a command -pipeline created with \fBopen\fR returns an error (either by returning a -non-zero exit code or writing to its standard error file descriptor), -\fBclose\fR generates an error (similar to the \fBexec\fR command.) -.PP -The two-argument form is a -.QW "half-close" : -given a bidirectional channel like a -socket or command pipeline and a (possibly abbreviated) direction, it closes -only the sub-stream going in that direction. This means a shutdown() on a -socket, and a close() of one end of a pipe for a command pipeline. Then, the -Tcl-level channel data structure is either kept or freed depending on whether -the other direction is still open. -.PP -A single-argument close on an already half-closed bidirectional channel is -defined to just -.QW "finish the job" . -A half-close on an already closed half, or on a wrong-sided unidirectional -channel, raises an error. -.PP -In the case of a command pipeline, the child-reaping duty falls upon the -shoulders of the last close or half-close, which is thus allowed to report an -abnormal exit error. -.PP -Currently only sockets and command pipelines support half-close. A future -extension will allow reflected and stacked channels to do so. -.SH EXAMPLE -.PP -This illustrates how you can use Tcl to ensure that files get closed -even when errors happen by combining \fBcatch\fR, \fBclose\fR and -\fBreturn\fR: -.PP -.CS -proc withOpenFile {filename channelVar script} { - upvar 1 $channelVar chan - set chan [open $filename] - catch { - uplevel 1 $script - } result options - \fBclose\fR $chan - return -options $options $result -} -.CE +The \fBclose\fR command has been superceded by the \fBchan close\fR +command and supports the same syntax and options. .SH "SEE ALSO" -chan(n), file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3) -.SH KEYWORDS -blocking, channel, close, nonblocking, half-close +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/eof.n b/doc/eof.n index 0dcf34a..c0d09b4 100644 --- a/doc/eof.n +++ b/doc/eof.n @@ -16,49 +16,10 @@ eof \- Check for end of file condition on channel .BE .SH DESCRIPTION .PP -Returns 1 if an end of file condition occurred during the most -recent input operation on \fIchannelId\fR (such as \fBgets\fR), -0 otherwise. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), -the return value from an invocation of \fBopen\fR or \fBsocket\fR, or -the result of a channel creation command provided by a Tcl extension. -.SH EXAMPLES -.PP -Read and print out the contents of a file line-by-line: -.PP -.CS -set f [open somefile.txt] -while {1} { - set line [gets $f] - if {[\fBeof\fR $f]} { - close $f - break - } - puts "Read line: $line" -} -.CE -.PP -Read and print out the contents of a file by fixed-size records: -.PP -.CS -set f [open somefile.dat] -fconfigure $f -translation binary -set recordSize 40 -while {1} { - set record [read $f $recordSize] - if {[\fBeof\fR $f]} { - close $f - break - } - puts "Read record: $record" -} -.CE +The \fBeof\fR command has been superceded by the \fBchan eof\fR +command. It supports the same syntax and options as the latter. .SH "SEE ALSO" -file(n), open(n), close(n), fblocked(n), Tcl_StandardChannels(3) -.SH KEYWORDS -channel, end of file +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/fblocked.n b/doc/fblocked.n index 44dfcd5..625a79a 100644 --- a/doc/fblocked.n +++ b/doc/fblocked.n @@ -14,56 +14,10 @@ fblocked \- Test whether the last input operation exhausted all available input .BE .SH DESCRIPTION .PP -The \fBfblocked\fR command returns 1 if the most recent input operation -on \fIchannelId\fR returned less information than requested because all -available input was exhausted. -For example, if \fBgets\fR is invoked when there are only three -characters available for input and no end-of-line sequence, \fBgets\fR -returns an empty string and a subsequent call to \fBfblocked\fR will -return 1. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), -the return value from an invocation of \fBopen\fR or \fBsocket\fR, or -the result of a channel creation command provided by a Tcl extension. -.SH EXAMPLE -The \fBfblocked\fR command is particularly useful when writing network -servers, as it allows you to write your code in a line-by-line style -without preventing the servicing of other connections. This can be -seen in this simple echo-service: -.PP -.CS -# This is called whenever a new client connects to the server -proc connect {chan host port} { - set clientName [format <%s:%d> $host $port] - puts "connection from $clientName" - fconfigure $chan -blocking 0 -buffering line - fileevent $chan readable [list echoLine $chan $clientName] -} - -# This is called whenever either at least one byte of input -# data is available, or the channel was closed by the client. -proc echoLine {chan clientName} { - gets $chan line - if {[eof $chan]} { - puts "finishing connection from $clientName" - close $chan - } elseif {![\fBfblocked\fR $chan]} { - # Didn't block waiting for end-of-line - puts "$clientName - $line" - puts $chan $line - } -} - -# Create the server socket and enter the event-loop to wait -# for incoming connections... -socket -server connect 12345 -vwait forever -.CE +The \fBfblocked\fR command has been superceded by the \fBchan blocked\fR +command. It supports the same syntax and options as the latter. .SH "SEE ALSO" -gets(n), open(n), read(n), socket(n), Tcl_StandardChannels(3) -.SH KEYWORDS -blocking, nonblocking +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/fconfigure.n b/doc/fconfigure.n index 468cd62..e7978d0 100644 --- a/doc/fconfigure.n +++ b/doc/fconfigure.n @@ -19,269 +19,10 @@ fconfigure \- Set and get options on a channel .BE .SH DESCRIPTION .PP -The \fBfconfigure\fR command sets and retrieves options for channels. -.PP -\fIChannelId\fR identifies the channel for which to set or query an -option and must refer to an open channel such as a Tcl standard -channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return -value from an invocation of \fBopen\fR or \fBsocket\fR, or the result -of a channel creation command provided by a Tcl extension. -.PP -If no \fIname\fR or \fIvalue\fR arguments are supplied, the command -returns a list containing alternating option names and values for the channel. -If \fIname\fR is supplied but no \fIvalue\fR then the command returns -the current value of the given option. -If one or more pairs of \fIname\fR and \fIvalue\fR are supplied, the -command sets each of the named options to the corresponding \fIvalue\fR; -in this case the return value is an empty string. -.PP -The options described below are supported for all channels. In addition, -each channel type may add options that only it supports. See the manual -entry for the command that creates each type of channels for the options -that that specific type of channel supports. For example, see the manual -entry for the \fBsocket\fR command for additional options for sockets, and -the \fBopen\fR command for additional options for serial devices. -.\" OPTION: -blocking -.TP -\fB\-blocking\fI boolean\fR -. -The \fB\-blocking\fR option determines whether I/O operations on the -channel can cause the process to block indefinitely. -The value of the option must be a proper boolean value. -Channels are normally in blocking mode; if a channel is placed into -nonblocking mode it will affect the operation of the \fBgets\fR, -\fBread\fR, \fBputs\fR, \fBflush\fR, and \fBclose\fR commands by -allowing them to operate asynchronously; -see the documentation for those commands for details. -For nonblocking mode to work correctly, the application must be -using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or -invoking the \fBvwait\fR command). -.\" OPTION: -buffering -.TP -\fB\-buffering\fI newValue\fR -. -If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output -until its internal buffer is full or until the \fBflush\fR command is -invoked. If \fInewValue\fR is \fBline\fR, then the I/O system will -automatically flush output for the channel whenever a newline character -is output. If \fInewValue\fR is \fBnone\fR, the I/O system will flush -automatically after every output operation. The default is for -\fB\-buffering\fR to be set to \fBfull\fR except for channels that -connect to terminal-like devices; for these channels the initial setting -is \fBline\fR. Additionally, \fBstdin\fR and \fBstdout\fR are -initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR. -.\" OPTION: -buffersize -.TP -\fB\-buffersize\fI newSize\fR -. -\fINewvalue\fR must be an integer; its value is used to set the size of -buffers, in bytes, subsequently allocated for this channel to store input -or output. \fINewvalue\fR must be between one and one million, allowing -buffers of one to one million bytes in size. -.\" OPTION: -encoding -.TP -\fB\-encoding\fI name\fR -. -This option is used to specify the encoding of the channel, so that the data -can be converted to and from Unicode for use in Tcl. For instance, in -order for Tcl to read characters from a Japanese file in \fBshiftjis\fR -and properly process and display the contents, the encoding would be set -to \fBshiftjis\fR. Thereafter, when reading from the channel, the bytes in -the Japanese file would be converted to Unicode as they are read. -Writing is also supported \- as Tcl strings are written to the channel they -will automatically be converted to the specified encoding on output. -.RS -.PP -If a file contains pure binary data (for instance, a JPEG image), the -encoding for the channel should be configured to be \fBbinary\fR. Tcl -will then assign no interpretation to the data in the file and simply read or -write raw bytes. The Tcl \fBbinary\fR command can be used to manipulate this -byte-oriented data. It is usually better to set the -\fB\-translation\fR option to \fBbinary\fR when you want to transfer -binary data, as this turns off the other automatic interpretations of -the bytes in the stream as well. -.PP -The default encoding for newly opened channels is the same platform- and -locale-dependent system encoding used for interfacing with the operating -system, as returned by \fBencoding system\fR. -.RE -.\" OPTION: -eofchar -.TP -\fB\-eofchar\fI char\fR -. -This option supports DOS file systems that use Control-z (\ex1A) as an -end of file marker. If \fIchar\fR is not an empty string, then this -character signals end-of-file when it is encountered during input. -If \fIchar\fR is the empty string, then there is no special end of file -character marker. The default value for \fB\-eofchar\fR is the empty -string. -The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7F; -attempting to set \fB\-eofchar\fR to a value outside of this range will -generate an error. -.VS "TCL8.7 TIP656" -.\" OPTION: -profile -.TP -\fB\-profile\fI profile\fR -. -Specifies the encoding profile to be used on the channel. The encoding -transforms in use for the channel's input and output will then be subject to the -rules of that profile. Any failures will result in a channel error. See -\fBPROFILES\fR in the \fBencoding(n)\fR documentation for details about encoding -profiles. -.VE "TCL8.7 TIP656" -.\" OPTION: -translation -.TP -\fB\-translation\fI mode\fR -.TP -\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR -. -In Tcl scripts the end of a line is always represented using a single -newline character (\en). However, in actual files and devices the end of -a line may be represented differently on different platforms, or even for -different devices on the same platform. For example, under UNIX newlines -are used in files, whereas carriage-return-linefeed sequences are -normally used in network connections. On input (i.e., with \fBgets\fR -and \fBread\fR) the Tcl I/O system automatically translates the external -end-of-line representation into newline characters. Upon output (i.e., -with \fBputs\fR), the I/O system translates newlines to the external -end-of-line representation. The default translation mode, \fBauto\fR, -handles all the common cases automatically, but the \fB\-translation\fR -option provides explicit control over the end of line translations. -.RS -.PP -The value associated with \fB\-translation\fR is a single item for -read-only and write-only channels. The value is a two-element list for -read-write channels; the read translation mode is the first element of -the list, and the write translation mode is the second element. As a -convenience, when setting the translation mode for a read-write channel -you can specify a single value that will apply to both reading and -writing. When querying the translation mode of a read-write channel, a -two-element list will always be returned. The following values are -currently supported: -.IP \fBauto\fR -As the input translation mode, \fBauto\fR treats any of newline -(\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by a -newline (\fBcrlf\fR) as the end of line representation. The end of line -representation can even change from line-to-line, and all cases are -translated to a newline. As the output translation mode, \fBauto\fR -chooses a platform specific representation; for sockets on all platforms -Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, and -for the various flavors of Windows it chooses \fBcrlf\fR. The default -setting for \fB\-translation\fR is \fBauto\fR for both input and output. -.IP \fBbinary\fR -No end-of-line translations are performed. This is nearly identical to -\fBlf\fR mode, except that in addition \fBbinary\fR mode also sets the -end-of-file character to the empty string (which disables it) and sets the -encoding to \fBbinary\fR (which disables encoding filtering). See the -description of \fB\-eofchar\fR and \fB\-encoding\fR for more information. -.RS -.PP -Internally, i.e. when it comes to the actual behaviour of the -translator this value \fBis\fR identical to \fBlf\fR and is therefore -reported as such when queried. Even if \fBbinary\fR was used to set -the translation. -.RE -.IP \fBcr\fR -The end of a line in the underlying file or device is represented by a -single carriage return character. As the input translation mode, -\fBcr\fR mode converts carriage returns to newline characters. As the -output translation mode, \fBcr\fR mode translates newline characters to -carriage returns. -.IP \fBcrlf\fR -The end of a line in the underlying file or device is represented by a -carriage return character followed by a linefeed character. As the input -translation mode, \fBcrlf\fR mode converts carriage-return-linefeed -sequences to newline characters. As the output translation mode, -\fBcrlf\fR mode translates newline characters to carriage-return-linefeed -sequences. This mode is typically used on Windows platforms and for -network connections. -.IP \fBlf\fR -The end of a line in the underlying file or device is represented by a -single newline (linefeed) character. In this mode no translations occur -during either input or output. This mode is typically used on UNIX -platforms. -.RE -.PP -.SH "STANDARD CHANNELS" -.PP -The Tcl standard channels (\fBstdin\fR, \fBstdout\fR, and \fBstderr\fR) -can be configured through this command like every other channel opened -by the Tcl library. Beyond the standard options described above they -will also support any special option according to their current type. -If, for example, a Tcl application is started by the \fBinet\fR -super-server common on Unix system its Tcl standard channels will be -sockets and thus support the socket options. -.SH EXAMPLES -.PP -Instruct Tcl to always send output to \fBstdout\fR immediately, -whether or not it is to a terminal: -.PP -.CS -\fBfconfigure\fR stdout -buffering none -.CE -.PP -Open a socket and read lines from it without ever blocking the -processing of other events: -.PP -.CS -set s [socket some.where.com 12345] -\fBfconfigure\fR $s -blocking 0 -fileevent $s readable "readMe $s" -proc readMe chan { - if {[gets $chan line] < 0} { - if {[eof $chan]} { - close $chan - return - } - # Could not read a complete line this time; Tcl's - # internal buffering will hold the partial line for us - # until some more data is available over the socket. - } else { - puts stdout $line - } -} -.CE -.PP -Read a PPM-format image from a file: -.PP -.CS -# Open the file and put it into Unix ASCII mode -set f [open teapot.ppm] -\fBfconfigure\fR $f -encoding ascii -translation lf - -# Get the header -if {[gets $f] ne "P6"} { - error "not a raw\-bits PPM" -} - -# Read lines until we have got non-comment lines -# that supply us with three decimal values. -set words {} -while {[llength $words] < 3} { - gets $f line - if {[string match "#*" $line]} continue - lappend words {*}[join [scan $line %d%d%d]] -} - -# Those words supply the size of the image and its -# overall depth per channel. Assign to variables. -lassign $words xSize ySize depth - -# Now switch to binary mode to pull in the data, -# one byte per channel (red,green,blue) per pixel. -\fBfconfigure\fR $f -translation binary -set numDataBytes [expr {3 * $xSize * $ySize}] -set data [read $f $numDataBytes] - -close $f -.CE +The \fBfconfigure\fR command has been superceded by the \fBchan configure\fR +command. It supports the same syntax and options as the latter. .SH "SEE ALSO" -close(n), encoding(n), flush(n), gets(n), open(n), puts(n), read(n), socket(n), -Tcl_StandardChannels(3) -.SH KEYWORDS -blocking, buffering, carriage return, end of line, encoding, flushing, linemode, -newline, nonblocking, platform, profile, translation, encoding, filter, -byte array, binary +chan(n) '\" Local Variables: '\" mode: nroff '\" End: diff --git a/doc/fileevent.n b/doc/fileevent.n index c302b39..7be3e2e 100644 --- a/doc/fileevent.n +++ b/doc/fileevent.n @@ -19,140 +19,10 @@ fileevent \- Execute a script when a channel becomes readable or writable .BE .SH DESCRIPTION .PP -This command is used to create \fIfile event handlers\fR. A file event -handler is a binding between a channel and a script, such that the script -is evaluated whenever the channel becomes readable or writable. File event -handlers are most commonly used to allow data to be received from another -process on an event-driven basis, so that the receiver can continue to -interact with the user while waiting for the data to arrive. If an -application invokes \fBgets\fR or \fBread\fR on a blocking channel when -there is no input data available, the process will block; until the input -data arrives, it will not be able to service other events, so it will -appear to the user to -.QW "freeze up" . -With \fBfileevent\fR, the process can -tell when data is present and only invoke \fBgets\fR or \fBread\fR when -they will not block. -.PP -The \fIchannelId\fR argument to \fBfileevent\fR refers to an open -channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, -or \fBstderr\fR), the return value from an invocation of \fBopen\fR -or \fBsocket\fR, or the result of a channel creation command provided -by a Tcl extension. -.PP -If the \fIscript\fR argument is specified, then \fBfileevent\fR -creates a new event handler: \fIscript\fR will be evaluated -whenever the channel becomes readable or writable (depending on the -second argument to \fBfileevent\fR). -In this case \fBfileevent\fR returns an empty string. -The \fBreadable\fR and \fBwritable\fR event handlers for a file -are independent, and may be created and deleted separately. -However, there may be at most one \fBreadable\fR and one \fBwritable\fR -handler for a file at a given time in a given interpreter. -If \fBfileevent\fR is called when the specified handler already -exists in the invoking interpreter, the new script replaces the old one. -.PP -If the \fIscript\fR argument is not specified, \fBfileevent\fR -returns the current script for \fIchannelId\fR, or an empty string -if there is none. -If the \fIscript\fR argument is specified as an empty string -then the event handler is deleted, so that no script will be invoked. -A file event handler is also deleted automatically whenever -its channel is closed or its interpreter is deleted. -.PP -A channel is considered to be readable if there is unread data -available on the underlying device. -A channel is also considered to be readable if there is unread -data in an input buffer, except in the special case where the -most recent attempt to read from the channel was a \fBgets\fR -call that could not find a complete line in the input buffer. -This feature allows a file to be read a line at a time in nonblocking mode -using events. -A channel is also considered to be readable if an end of file or -error condition is present on the underlying file or device. -It is important for \fIscript\fR to check for these conditions -and handle them appropriately; for example, if there is no special -check for end of file, an infinite loop may occur where \fIscript\fR -reads no data, returns, and is immediately invoked again. -.PP -A channel is considered to be writable if at least one byte of data -can be written to the underlying file or device without blocking, -or if an error condition is present on the underlying file or device. -.PP -Event-driven I/O works best for channels that have been placed into -nonblocking mode with the \fBfconfigure\fR command. In blocking mode, -a \fBputs\fR command may block if you give it more data than the -underlying file or device can accept, and a \fBgets\fR or \fBread\fR -command will block if you attempt to read more data than is ready; a -readable underlying file or device may not even guarantee that a -blocking [read 1] will succeed (counter-examples being multi-byte -encodings, compression or encryption transforms ). In all such cases, -no events will be processed while the commands block. -.PP -In nonblocking mode \fBputs\fR, \fBread\fR, and \fBgets\fR never block. -See the documentation for the individual commands for information -on how they handle blocking and nonblocking channels. -.PP -Testing for the end of file condition should be done after any attempts -read the channel data. The eof flag is set once an attempt to read the -end of data has occurred and testing before this read will require an -additional event to be fired. -.PP -The script for a file event is executed at global level (outside the -context of any Tcl procedure) in the interpreter in which the -\fBfileevent\fR command was invoked. -If an error occurs while executing the script then the -command registered with \fBinterp bgerror\fR is used to report the error. -In addition, the file event handler is deleted if it ever returns -an error; this is done in order to prevent infinite loops due to -buggy handlers. -.SH EXAMPLE -.PP -In this setup \fBGetData\fR will be called with the channel as an -argument whenever $chan becomes readable. The \fBread\fR call will -read whatever binary data is currently available without blocking. -Here the channel has the fileevent removed when an end of file -occurs to avoid being continually called (see above). Alternatively -the channel may be closed on this condition. -.PP -.CS -proc GetData {chan} { - set data [read $chan] - puts "[string length $data] $data" - if {[eof $chan]} { - fileevent $chan readable {} - } -} - -fconfigure $chan -blocking 0 -encoding binary -\fBfileevent\fR $chan readable [list GetData $chan] -.CE -.PP -The next example demonstrates use of \fBgets\fR to read line-oriented -data. -.PP -.CS -proc GetData {chan} { - if {[gets $chan line] >= 0} { - puts $line - } - if {[eof $chan]} { - close $chan - } -} - -fconfigure $chan -blocking 0 -buffering line -translation crlf -\fBfileevent\fR $chan readable [list GetData $chan] -.CE -.SH CREDITS -.PP -\fBfileevent\fR is based on the \fBaddinput\fR command created -by Mark Diekhans. +The \fBfileevent\fR command has been superceded by the \fBchan event\fR +command and supports the same syntax and options. .SH "SEE ALSO" -fconfigure(n), gets(n), interp(n), puts(n), read(n), Tcl_StandardChannels(3) -.SH KEYWORDS -asynchronous I/O, blocking, channel, event handler, nonblocking, readable, -script, writable. +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/flush.n b/doc/flush.n index 1d84383..57c1c67 100644 --- a/doc/flush.n +++ b/doc/flush.n @@ -16,33 +16,10 @@ flush \- Flush buffered output for a channel .BE .SH DESCRIPTION .PP -Flushes any output that has been buffered for \fIchannelId\fR. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return -value from an invocation of \fBopen\fR or \fBsocket\fR, or the result -of a channel creation command provided by a Tcl extension. The -channel must have been opened for writing. -.PP -If the channel is in blocking mode the command does not return until all the -buffered output has been flushed to the channel. If the channel is in -nonblocking mode, the command may return before all buffered output has been -flushed; the remainder will be flushed in the background as fast as the -underlying file or device is able to absorb it. -.SH EXAMPLE -.PP -Prompt for the user to type some information in on the console: -.PP -.CS -puts -nonewline "Please type your name: " -\fBflush\fR stdout -gets stdin name -puts "Hello there, $name!" -.CE +The \fBflush\fR command has been superceded by the \fBchan flush\fR +command and supports the same syntax and options. .SH "SEE ALSO" -file(n), open(n), socket(n), Tcl_StandardChannels(3) -.SH KEYWORDS -blocking, buffer, channel, flush, nonblocking, output +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/gets.n b/doc/gets.n index 33d8cf6..99c5f72 100644 --- a/doc/gets.n +++ b/doc/gets.n @@ -16,89 +16,10 @@ gets \- Read a line from a channel .BE .SH DESCRIPTION .PP -This command reads the next line from \fIchannelId\fR, returns everything -in the line up to (but not including) the end-of-line character(s), and -discards the end-of-line character(s). -.PP -\fIChannelId\fR must be an identifier for an open channel such as the -Tcl standard input channel (\fBstdin\fR), the return value from an -invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel -creation command provided by a Tcl extension. The channel must have -been opened for input. -.PP -If \fIvarName\fR is omitted the line is returned as the result of the -command. -If \fIvarName\fR is specified then the line is placed in the variable by -that name and the return value is a count of the number of characters -returned. -.PP -If end of file occurs while scanning for an end of -line, the command returns whatever input is available up to the end of file. -If \fIchannelId\fR is in non-blocking mode and there is not a full -line of input available, the command returns an empty string and -does not consume any input. -If \fIvarName\fR is specified and an empty string is returned in -\fIvarName\fR because of end-of-file or because of insufficient -data in non-blocking mode, then the return count is -1. -Note that if \fIvarName\fR is not specified then the end-of-file -and no-full-line-available cases can -produce the same results as if there were an input line consisting -only of the end-of-line character(s). -The \fBeof\fR and \fBfblocked\fR commands can be used to distinguish -these three cases. -.SH "ENCODING ERRORS" -.PP -Encoding errors may exist, if the encoding profile \fBstrict\fR is used. -Encoding errors are special, as an eventual introspection or recovery is -possible by changing to an encoding which accepts the data. -An encoding error is reported by the POSIX error code \fBEILSEQ\fR. -The file pointer is unchanged in the error case. -.PP -Here is an example with an encoding error in UTF-8 encoding, which is then -introspected by a switch to the binary encoding. The test file contains a not -continued multi-byte sequence at position 1 (\fBA \\xC3 B\fR): -.PP -File creation for example -.CS -% set f [open test_A_195_B.txt wb]; puts -nonewline $f A\\xC3B; close $f -.CE -Encoding error example -.CS -% set f [open test_A_195_B.txt r] -file384b6a8 -% fconfigure $f -encoding utf-8 -profile strict -% catch {gets $f} e d -1 -% set d --code 1 -level 0 --errorstack {INNER {invokeStk1 gets file384b6a8}} --errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} --errorinfo {...} -errorline 1 -% tell $f -0 -% fconfigure $f -encoding binary -profile strict -% gets $f -AÃB -.CE -Compared to \fBread\fR, any already decoded data is not consumed. -The file position is still at 0 and the recovery \fBgets\fR returns also the -already well decoded leading data. -.SH "EXAMPLE" -This example reads a file one line at a time and prints it out with -the current line number attached to the start of each line. -.PP -.CS -set chan [open "some.file.txt"] -set lineNumber 0 -while {[\fBgets\fR $chan line] >= 0} { - puts "[incr lineNumber]: $line" -} -close $chan -.CE +The \fBgets\fR command has been superceded by the \fBchan gets\fR +command and supports the same syntax and options. .SH "SEE ALSO" -file(n), eof(n), fblocked(n), Tcl_StandardChannels(3) -.SH KEYWORDS -blocking, channel, end of file, end of line, line, non-blocking, read +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/puts.n b/doc/puts.n index 5ce56b7..f3eb68e 100644 --- a/doc/puts.n +++ b/doc/puts.n @@ -16,89 +16,10 @@ puts \- Write to a channel .BE .SH DESCRIPTION .PP -Writes the characters given by \fIstring\fR to the channel given -by \fIchannelId\fR. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return -value from an invocation of \fBopen\fR or \fBsocket\fR, or the result -of a channel creation command provided by a Tcl extension. The channel -must have been opened for output. -.PP -If no \fIchannelId\fR is specified then it defaults to -\fBstdout\fR. \fBPuts\fR normally outputs a newline character after -\fIstring\fR, but this feature may be suppressed by specifying the -\fB\-nonewline\fR switch. -.PP -Newline characters in the output are translated by \fBputs\fR to -platform-specific end-of-line sequences according to the current -value of the \fB\-translation\fR option for the channel (for example, -on PCs newlines are normally replaced with carriage-return-linefeed -sequences. -See the \fBfconfigure\fR manual entry for a discussion on ways in -which \fBfconfigure\fR will alter output. -.PP -Tcl buffers output internally, so characters written with \fBputs\fR -may not appear immediately on the output file or device; Tcl will -normally delay output until the buffer is full or the channel is -closed. -You can force output to appear immediately with the \fBflush\fR -command. -.PP -When the output buffer fills up, the \fBputs\fR command will normally -block until all the buffered data has been accepted for output by the -operating system. -If \fIchannelId\fR is in nonblocking mode then the \fBputs\fR command -will not block even if the operating system cannot accept the data. -Instead, Tcl continues to buffer the data and writes it in the -background as fast as the underlying file or device can accept it. -The application must use the Tcl event loop for nonblocking output -to work; otherwise Tcl never finds out that the file or device is -ready for more output data. -It is possible for an arbitrarily large amount of data to be -buffered for a channel in nonblocking mode, which could consume a -large amount of memory. -To avoid wasting memory, nonblocking I/O should normally -be used in an event-driven fashion with the \fBfileevent\fR command -(do not invoke \fBputs\fR unless you have recently been notified -via a file event that the channel is ready for more output data). -.SH "ENCODING ERRORS" -.PP -Encoding errors may exist, if the encoding profile \fBstrict\fR is used. -\fBputs\fR writes out data until an encoding error occurs and fails with -POSIX error code \fBEILSEQ\fR. -.SH EXAMPLES -.PP -Write a short message to the console (or wherever \fBstdout\fR is -directed): -.PP -.CS -\fBputs\fR "Hello, World!" -.CE -.PP -Print a message in several parts: -.PP -.CS -\fBputs\fR -nonewline "Hello, " -\fBputs\fR "World!" -.CE -.PP -Print a message to the standard error channel: -.PP -.CS -\fBputs\fR stderr "Hello, World!" -.CE -.PP -Append a log message to a file: -.PP -.CS -set chan [open my.log a] -set timestamp [clock format [clock seconds]] -\fBputs\fR $chan "$timestamp - Hello, World!" -close $chan -.CE +The \fBputs\fR command has been superceded by the \fBchan puts\fR +command and supports the same syntax and options. .SH "SEE ALSO" -file(n), fileevent(n), Tcl_StandardChannels(3) +chan(n) .SH KEYWORDS channel, newline, output, write '\" Local Variables: diff --git a/doc/read.n b/doc/read.n index a19e2a2..c797072 100644 --- a/doc/read.n +++ b/doc/read.n @@ -18,146 +18,10 @@ read \- Read from a channel .BE .SH DESCRIPTION .PP -In the first form, the \fBread\fR command reads all of the data from -\fIchannelId\fR up to the end of the file. If the \fB\-nonewline\fR -switch is specified then the last character of the file is discarded -if it is a newline. In the second form, the extra argument specifies -how many characters to read. Exactly that many characters will be -read and returned, unless there are fewer than \fInumChars\fR left in -the file; in this case all the remaining characters are returned. If -the channel is configured to use a multi-byte encoding, then the -number of characters read may not be the same as the number of bytes -read. -.PP -\fIChannelId\fR must be an identifier for an open channel such as the -Tcl standard input channel (\fBstdin\fR), the return value from an -invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel -creation command provided by a Tcl extension. The channel must have -been opened for input. -.PP -If \fIchannelId\fR is in nonblocking mode, the command may not read as -many characters as requested: once all available input has been read, -the command will return the data that is available rather than -blocking for more input. If the channel is configured to use a -multi-byte encoding, then there may actually be some bytes remaining -in the internal buffers that do not form a complete character. These -bytes will not be returned until a complete character is available or -end-of-file is reached. The \fB\-nonewline\fR switch is ignored if -the command returns before reaching the end of the file. -.PP -\fBRead\fR translates end-of-line sequences in the input into -newline characters according to the \fB\-translation\fR option -for the channel. -See the \fBfconfigure\fR manual entry for a discussion on ways in -which \fBfconfigure\fR will alter input. -.SH "ENCODING ERRORS" -.PP -Encoding errors may exist, if the encoding profile \fBstrict\fR is used. -Encoding errors are special, as an eventual introspection or recovery is -possible by changing to an encoding (or encoding profile), which accepts -the data. -An encoding error is reported by the POSIX error code \fBEILSEQ\fR. -.PP -In blocking mode, the error is directly thrown, even, if there is a -leading decodable data portion. -The file pointer is advanced just before the encoding error. -An eventual well decoded data chunk before the encoding error is returned -in the error option dictionary key \fB\-data\fR. -The value of the key contains the empty string, if the error arises at the -first data position. -.PP -In non blocking mode, first, any data without encoding error is returned -(without error state). -In the next call, no data is returned and the \fBEILSEQ\fR error state is set. -The key \fB\-data\fR is not present. -.PP -Here is an example with an encoding error in UTF-8 encoding, which is then -introspected by a switch to the binary encoding. The test file contains a not -continued multi-byte sequence at position 1 (\fBA \\xC3 B\fR): -.PP -File creation for examples -. -.CS -% set f [open test_A_195_B.txt wb]; puts -nonewline $f A\\xC3B; close $f -.CE -Blocking example -. -.CS -% set f [open test_A_195_B.txt r] -file35a65a0 -% fconfigure $f -encoding utf-8 -profile strict -blocking 1 -% catch {read $f} e d -1 -% set d --data A -code 1 -level 0 --errorstack {INNER {invokeStk1 read file35a65a0}} --errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} --errorinfo {...} -errorline 1 -% tell $f -1 -% fconfigure $f -encoding binary -profile strict -% read $f -ÃB -% close $f -.CE -The already decoded data "A" is returned in the error options dictionary key -\fB\-data\fR. -The file position is advanced on the encoding error position 1. -The data at the error position is thus recovered by the next \fBread\fR command. -.PP -Non blocking example -. -.CS -% set f [open test_A_195_B.txt r] -file35a65a0 -% fconfigure $f -encoding utf-8 -profile strict -blocking 0 -% read $f -A -% tell $f -1 -% catch {read $f} e d -1 -% set d --code 1 -level 0 --errorstack {INNER {invokeStk1 read file384b228}} --errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} --errorinfo {...} -errorline 1 -.CE -.SH "USE WITH SERIAL PORTS" -'\" Note: this advice actually applies to many versions of Tcl -.PP -For most applications a channel connected to a serial port should be -configured to be nonblocking: \fBfconfigure\fI channelId \fB\-blocking -\fI0\fR. Then \fBread\fR behaves much like described above. Care -must be taken when using \fBread\fR on blocking serial ports: -.TP -\fBread \fIchannelId numChars\fR -. -In this form \fBread\fR blocks until \fInumChars\fR have been received -from the serial port. -.TP -\fBread \fIchannelId\fR -. -In this form \fBread\fR blocks until the reception of the end-of-file -character, see \fBfconfigure\fR \fB\-eofchar\fR. If there no end-of-file -character has been configured for the channel, then \fBread\fR will -block forever. -.SH "EXAMPLE" -.PP -This example code reads a file all at once, and splits it into a list, -with each line in the file corresponding to an element in the list: -.PP -.CS -set fl [open /proc/meminfo] -set data [\fBread\fR $fl] -close $fl -set lines [split $data \en] -.CE +The \fBread\fR command has been superceded by the \fBchan read\fR +command and supports the same syntax and options. .SH "SEE ALSO" -file(n), eof(n), fblocked(n), fconfigure(n), Tcl_StandardChannels(3) -.SH KEYWORDS -blocking, channel, end of line, end of file, nonblocking, read, translation, -encoding +chan(n) '\"Local Variables: '\"mode: nroff '\"End: -- cgit v0.12 From 805c237f9558eebd6f14aa789b796004d592328c Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Thu, 11 Apr 2024 02:27:25 +0000 Subject: Done with consolidating chan related docs except chan copy --- doc/chan.n | 44 ++++++++++++++++++++++++++++++++++++++--- doc/close.n | 1 + doc/seek.n | 66 +++---------------------------------------------------------- doc/tell.n | 30 +--------------------------- 4 files changed, 46 insertions(+), 95 deletions(-) diff --git a/doc/chan.n b/doc/chan.n index 4054da6..977e084 100644 --- a/doc/chan.n +++ b/doc/chan.n @@ -814,7 +814,44 @@ set data [chan read $f $numDataBytes] close $f .CE - +.SS "FILE SEEK EXAMPLES" +.PP +Read a file twice: +.PP +.CS +set f [open file.txt] +set data1 [chan read $f] +\fBchan seek\fR $f 0 +set data2 [chan read $f] +chan close $f +# $data1 eq $data2 if the file wasn't updated +.CE +.PP +Read the last 10 bytes from a file: +.PP +.CS +set f [open file.data] +# This is guaranteed to work with binary data but +# may fail with other encodings... +chan configure $f -translation binary +\fBchan seek\fR $f -10 end +set data [chan read $f 10] +chan close $f +.CE +.PP +Read a line from a file channel only if it starts with \fBfoobar\fR: +.PP +.CS +# Save the offset in case we need to undo the read... +set offset [\fBtell\fR $chan] +if {[read $chan 6] eq "foobar"} { + gets $chan line +} else { + set line {} + # Undo the read... + seek $chan $offset +} +.CE .SS "ENCODING ERROR EXAMPLES" .PP The example below illustrates handling of an encoding error encountered @@ -980,10 +1017,11 @@ vwait done .SH "SEE ALSO" close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n), fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n), -socket(n), tell(n), refchan(n), transchan(n) +socket(n), tell(n), refchan(n), transchan(n), +Tcl_StandardChannels(3) .SH KEYWORDS blocking, channel, end of file, events, input, non-blocking, -offset, output, readable, writable +offset, output, readable, seek, stdio, tell, writable '\" Local Variables: '\" mode: nroff '\" End: diff --git a/doc/close.n b/doc/close.n index 900679e..0851608 100644 --- a/doc/close.n +++ b/doc/close.n @@ -15,6 +15,7 @@ close \- Close an open channel \fBclose \fIchannelId\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)? .BE .SH DESCRIPTION +.PP The \fBclose\fR command has been superceded by the \fBchan close\fR command and supports the same syntax and options. .SH "SEE ALSO" diff --git a/doc/seek.n b/doc/seek.n index 68d40f7..cfd05ea 100644 --- a/doc/seek.n +++ b/doc/seek.n @@ -16,70 +16,10 @@ seek \- Change the access position for an open channel .BE .SH DESCRIPTION .PP -Changes the current access position for \fIchannelId\fR. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), -the return value from an invocation of \fBopen\fR or \fBsocket\fR, or -the result of a channel creation command provided by a Tcl extension. -.PP -The \fIoffset\fR and \fIorigin\fR -arguments specify the position at which the next read or write will occur -for \fIchannelId\fR. \fIOffset\fR must be an integer (which may be -negative) and \fIorigin\fR must be one of the following: -.IP \fBstart\fR 10 -The new access position will be \fIoffset\fR bytes from the start -of the underlying file or device. -.IP \fBcurrent\fR 10 -The new access position will be \fIoffset\fR bytes from the current -access position; a negative \fIoffset\fR moves the access position -backwards in the underlying file or device. -.IP \fBend\fR 10 -The new access position will be \fIoffset\fR bytes from the end of -the file or device. A negative \fIoffset\fR places the access position -before the end of file, and a positive \fIoffset\fR places the access -position after the end of file. -.PP -The \fIorigin\fR argument defaults to \fBstart\fR. -.PP -The command flushes all buffered output for the channel before the command -returns, even if the channel is in non-blocking mode. -It also discards any buffered and unread input. -This command returns an empty string. -An error occurs if this command is applied to channels whose underlying -file or device does not support seeking. -.PP -Note that \fIoffset\fR values are byte offsets, not character -offsets. Both \fBseek\fR and \fBtell\fR operate in terms of bytes, -not characters, unlike \fBread\fR. -.SH EXAMPLES -.PP -Read a file twice: -.PP -.CS -set f [open file.txt] -set data1 [read $f] -\fBseek\fR $f 0 -set data2 [read $f] -close $f -# $data1 eq $data2 if the file wasn't updated -.CE -.PP -Read the last 10 bytes from a file: -.PP -.CS -set f [open file.data] -# This is guaranteed to work with binary data but -# may fail with other encodings... -fconfigure $f -translation binary -\fBseek\fR $f -10 end -set data [read $f 10] -close $f -.CE +The \fBseek\fR command has been superceded by the \fBchan seek\fR +command and supports the same syntax and options. .SH "SEE ALSO" -file(n), open(n), close(n), gets(n), tell(n), Tcl_StandardChannels(3) -.SH KEYWORDS -access position, file, seek +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 diff --git a/doc/tell.n b/doc/tell.n index 54fbae1..1e91708 100644 --- a/doc/tell.n +++ b/doc/tell.n @@ -16,36 +16,8 @@ tell \- Return current access position for an open channel .BE .SH DESCRIPTION .PP -Returns an integer giving the current access position in -\fIchannelId\fR. This value returned is a byte offset that can be passed to -\fBseek\fR in order to set the channel to a particular position. Note -that this value is in terms of bytes, not characters like \fBread\fR. -The value returned is -1 for channels that do not support -seeking. -.PP -\fIChannelId\fR must be an identifier for an open channel such as a -Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), -the return value from an invocation of \fBopen\fR or \fBsocket\fR, or -the result of a channel creation command provided by a Tcl extension. -.SH EXAMPLE -.PP -Read a line from a file channel only if it starts with \fBfoobar\fR: -.PP -.CS -# Save the offset in case we need to undo the read... -set offset [\fBtell\fR $chan] -if {[read $chan 6] eq "foobar"} { - gets $chan line -} else { - set line {} - # Undo the read... - seek $chan $offset -} -.CE .SH "SEE ALSO" -file(n), open(n), close(n), gets(n), seek(n), Tcl_StandardChannels(3) -.SH KEYWORDS -access position, channel, seeking +chan(n) '\" Local Variables: '\" mode: nroff '\" fill-column: 78 -- cgit v0.12 From cb229ebf2ce1a8fbda9a6e7413b1b1c2b301ee2c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 11 Apr 2024 08:00:53 +0000 Subject: Add O_ACCMODE fow Windows, in case it is not defined --- win/tclWinPort.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/win/tclWinPort.h b/win/tclWinPort.h index f549420..c17cada 100644 --- a/win/tclWinPort.h +++ b/win/tclWinPort.h @@ -345,6 +345,9 @@ typedef DWORD_PTR * PDWORD_PTR; #ifndef R_OK # define R_OK 04 #endif +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) +#endif /* * Define macros to query file type bits, if they're not already -- cgit v0.12 From b8eff9b2453f1d9081a5cf93397e777ddbe47440 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 11 Apr 2024 08:55:01 +0000 Subject: Use Tcl_NewBooleanObj for booleans; we should say what we mean --- generic/tclClock.c | 2 +- generic/tclCmdIL.c | 4 ++-- generic/tclOOInfo.c | 4 ++-- generic/tclZlib.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 391a839..026c47b 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -1139,7 +1139,7 @@ ClockConfigureObjCmd( } if (i+1 >= objc) { Tcl_SetObjResult(interp, - Tcl_NewWideIntObj(dataPtr->defFlags & CLF_VALIDATE ? 1 : 0)); + Tcl_NewBooleanObj(dataPtr->defFlags & CLF_VALIDATE)); } break; case CLOCK_CLEAR_CACHE: diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index f5065f3..a7437af 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -989,7 +989,7 @@ InfoDefaultCmd( if (valueObjPtr == NULL) { return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1)); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } else { Tcl_Obj *nullObjPtr; TclNewObj(nullObjPtr); @@ -999,7 +999,7 @@ InfoDefaultCmd( if (valueObjPtr == NULL) { return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); } return TCL_OK; } diff --git a/generic/tclOOInfo.c b/generic/tclOOInfo.c index eba658b..39a4598 100644 --- a/generic/tclOOInfo.c +++ b/generic/tclOOInfo.c @@ -211,11 +211,11 @@ InfoObjectClassCmd( continue; } if (TclOOIsReachable(o2clsPtr, mixinPtr)) { - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1)); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); return TCL_OK; } } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj( + Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TclOOIsReachable(o2clsPtr, oPtr->selfCls))); return TCL_OK; } diff --git a/generic/tclZlib.c b/generic/tclZlib.c index a3be307..550eef8 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -2706,7 +2706,7 @@ ZlibStreamCmd( Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_ZlibStreamEof(zstream))); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_ZlibStreamEof(zstream))); return TCL_OK; case zs_checksum: /* $strm checksum */ if (objc != 2) { -- cgit v0.12 From 5221941a2ae530e1ff5b8ddb3c6558933d962c0c Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 11 Apr 2024 10:54:13 +0000 Subject: Style cleanup --- generic/tclStrIdxTree.h | 127 +++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 62 deletions(-) diff --git a/generic/tclStrIdxTree.h b/generic/tclStrIdxTree.h index 5052823..28e0710 100644 --- a/generic/tclStrIdxTree.h +++ b/generic/tclStrIdxTree.h @@ -13,26 +13,26 @@ #ifndef _TCLSTRIDXTREE_H #define _TCLSTRIDXTREE_H - /* * Main structures declarations of index tree and entry */ +typedef struct TclStrIdx TclStrIdx; + typedef struct TclStrIdxTree { - struct TclStrIdx *firstPtr; - struct TclStrIdx *lastPtr; + TclStrIdx *firstPtr; + TclStrIdx *lastPtr; } TclStrIdxTree; -typedef struct TclStrIdx { - struct TclStrIdxTree childTree; - struct TclStrIdx *nextPtr; - struct TclStrIdx *prevPtr; - Tcl_Obj *key; +struct TclStrIdx { + TclStrIdxTree childTree; + TclStrIdx *nextPtr; + TclStrIdx *prevPtr; + Tcl_Obj *key; Tcl_Size length; - void *value; -} TclStrIdx; - - + void *value; +}; + /* *---------------------------------------------------------------------- * @@ -51,38 +51,44 @@ typedef struct TclStrIdx { static inline const char * TclUtfFindEqual( - const char *cs, /* UTF string to find in cin. */ - const char *cse, /* End of cs */ - const char *cin, /* UTF string will be browsed. */ - const char *cine) /* End of cin */ + const char *cs, /* UTF string to find in cin. */ + const char *cse, /* End of cs */ + const char *cin, /* UTF string will be browsed. */ + const char *cine) /* End of cin */ { const char *ret = cs; Tcl_UniChar ch1, ch2; + do { cs += TclUtfToUniChar(cs, &ch1); cin += TclUtfToUniChar(cin, &ch2); - if (ch1 != ch2) break; + if (ch1 != ch2) { + break; + } } while ((ret = cs) < cse && cin < cine); return ret; } static inline const char * TclUtfFindEqualNC( - const char *cs, /* UTF string to find in cin. */ - const char *cse, /* End of cs */ - const char *cin, /* UTF string will be browsed. */ - const char *cine, /* End of cin */ - const char **cinfnd) /* Return position in cin */ + const char *cs, /* UTF string to find in cin. */ + const char *cse, /* End of cs */ + const char *cin, /* UTF string will be browsed. */ + const char *cine, /* End of cin */ + const char **cinfnd) /* Return position in cin */ { const char *ret = cs; Tcl_UniChar ch1, ch2; + do { cs += TclUtfToUniChar(cs, &ch1); cin += TclUtfToUniChar(cin, &ch2); if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); - if (ch1 != ch2) break; + if (ch1 != ch2) { + break; + } } *cinfnd = cin; } while ((ret = cs) < cse && cin < cine); @@ -91,20 +97,23 @@ TclUtfFindEqualNC( static inline const char * TclUtfFindEqualNCInLwr( - const char *cs, /* UTF string (in anycase) to find in cin. */ - const char *cse, /* End of cs */ - const char *cin, /* UTF string (in lowercase) will be browsed. */ - const char *cine, /* End of cin */ - const char **cinfnd) /* Return position in cin */ + const char *cs, /* UTF string (in anycase) to find in cin. */ + const char *cse, /* End of cs */ + const char *cin, /* UTF string (in lowercase) will be browsed. */ + const char *cine, /* End of cin */ + const char **cinfnd) /* Return position in cin */ { const char *ret = cs; Tcl_UniChar ch1, ch2; + do { cs += TclUtfToUniChar(cs, &ch1); cin += TclUtfToUniChar(cin, &ch2); if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); - if (ch1 != ch2) break; + if (ch1 != ch2) { + break; + } } *cinfnd = cin; } while ((ret = cs) < cse && cin < cine); @@ -116,48 +125,42 @@ TclUtfFindEqualNCInLwr( */ #define TclUnsetObjRef(obj) \ - do { \ - if (obj != NULL) { \ - Tcl_DecrRefCount(obj); \ - obj = NULL; \ - } \ + do { \ + if (obj != NULL) { \ + Tcl_DecrRefCount(obj); \ + obj = NULL; \ + } \ } while (0) #define TclInitObjRef(obj, val) \ - do { \ - obj = val; \ - if (obj) { \ - Tcl_IncrRefCount(obj); \ - } \ + do { \ + obj = val; \ + if (obj) { \ + Tcl_IncrRefCount(obj); \ + } \ } while (0) #define TclSetObjRef(obj, val) \ - do { \ - Tcl_Obj *nval = val; \ - if (obj != nval) { \ - Tcl_Obj *prev = obj; \ - TclInitObjRef(obj, nval); \ - if (prev != NULL) { \ - Tcl_DecrRefCount(prev); \ - }; \ - } \ + do { \ + Tcl_Obj *nval = val; \ + if (obj != nval) { \ + Tcl_Obj *prev = obj; \ + TclInitObjRef(obj, nval); \ + if (prev != NULL) { \ + Tcl_DecrRefCount(prev); \ + } \ + } \ } while (0) - + /* * Prototypes of module functions. */ -MODULE_SCOPE const char* - TclStrIdxTreeSearch(TclStrIdxTree **foundParent, - TclStrIdx **foundItem, TclStrIdxTree *tree, - const char *start, const char *end); - -MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree, - Tcl_Size lstc, Tcl_Obj **lstv, void **values); - -MODULE_SCOPE Tcl_Obj* - TclStrIdxTreeNewObj(); - -MODULE_SCOPE TclStrIdxTree* - TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr); +MODULE_SCOPE const char*TclStrIdxTreeSearch(TclStrIdxTree **foundParent, + TclStrIdx **foundItem, TclStrIdxTree *tree, + const char *start, const char *end); +MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree, + Tcl_Size lstc, Tcl_Obj **lstv, void **values); +MODULE_SCOPE Tcl_Obj * TclStrIdxTreeNewObj(); +MODULE_SCOPE TclStrIdxTree*TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr); #if 0 /* currently unused, debug resp. test purposes only */ -- cgit v0.12 From 043d1bb0ba97c0cf845c9d19caedaf4026c971f1 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 11 Apr 2024 13:19:29 +0000 Subject: Style cleanup, plus added comments on memory management --- generic/tclStrIdxTree.c | 230 +++++++++++++++++++++++++----------------------- generic/tclStrIdxTree.h | 31 +++++-- 2 files changed, 147 insertions(+), 114 deletions(-) diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index 2924829..af45c53 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -56,33 +56,45 @@ #include "tclInt.h" #include "tclStrIdxTree.h" +static void StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); +static void StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr); +static void StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr); + +Tcl_ObjType StrIdxTreeObjType = { + "str-idx-tree", /* name */ + StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */ + StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */ + StrIdxTreeObj_UpdateStringProc, /* updateStringProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 +}; /* *---------------------------------------------------------------------- * * TclStrIdxTreeSearch -- * - * Find largest part of string "start" in indexed tree (case sensitive). + * Find largest part of string "start" in indexed tree (case sensitive). * - * Also used for building of string index tree. + * Also used for building of string index tree. * * Results: - * Return position of UTF character in start after last equal character - * and found item (with parent). + * Return position of UTF character in start after last equal character + * and found item (with parent). * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -const char* +const char * TclStrIdxTreeSearch( TclStrIdxTree **foundParent, /* Return value of found sub tree (used for tree build) */ - TclStrIdx **foundItem, /* Return value of found item */ - TclStrIdxTree *tree, /* Index tree will be browsed */ - const char *start, /* UTF string to find in tree */ - const char *end) /* End of string */ + TclStrIdx **foundItem, /* Return value of found item */ + TclStrIdxTree *tree, /* Index tree will be browsed */ + const char *start, /* UTF string to find in tree */ + const char *end) /* End of string */ { TclStrIdxTree *parent = tree, *prevParent = tree; TclStrIdx *item = tree->firstPtr, *prevItem = NULL; @@ -103,7 +115,7 @@ TclStrIdxTreeSearch( if (f >= end) { start = f; goto done; - }; + } /* set new offset and shift start string */ offs += cinf - cin; s = f; @@ -126,7 +138,6 @@ TclStrIdxTreeSearch( } item = item->nextPtr; - } while (item != NULL); /* fallback (few greedy match) not ambigous (has a value) */ @@ -136,12 +147,13 @@ TclStrIdxTreeSearch( start = prevf; } -done: - - if (foundParent) + done: + if (foundParent) { *foundParent = parent; - if (foundItem) + } + if (foundItem) { *foundItem = item; + } return start; } @@ -150,12 +162,13 @@ TclStrIdxTreeFree( TclStrIdx *tree) { while (tree != NULL) { - TclStrIdx *t; + TclStrIdx *t = tree; + Tcl_DecrRefCount(tree->key); if (tree->childTree.firstPtr != NULL) { TclStrIdxTreeFree(tree->childTree.firstPtr); } - t = tree, tree = tree->nextPtr; + tree = tree->nextPtr; ckfree(t); } } @@ -169,15 +182,17 @@ TclStrIdxTreeInsertBranch( TclStrIdx *item, TclStrIdx *child) { - if (parent->firstPtr == child) + if (parent->firstPtr == child) { parent->firstPtr = item; - if (parent->lastPtr == child) + } + if (parent->lastPtr == child) { parent->lastPtr = item; - if ( (item->nextPtr = child->nextPtr) ) { + } + if ((item->nextPtr = child->nextPtr) != NULL) { item->nextPtr->prevPtr = item; child->nextPtr = NULL; } - if ( (item->prevPtr = child->prevPtr) ) { + if ((item->prevPtr = child->prevPtr) != NULL) { item->prevPtr->nextPtr = item; child->prevPtr = NULL; } @@ -188,7 +203,7 @@ TclStrIdxTreeInsertBranch( static inline void TclStrIdxTreeAppend( TclStrIdxTree *parent, - TclStrIdx *item) + TclStrIdx *item) { if (parent->lastPtr != NULL) { parent->lastPtr->nextPtr = item; @@ -200,25 +215,24 @@ TclStrIdxTreeAppend( parent->firstPtr = item; } } - /* *---------------------------------------------------------------------- * * TclStrIdxTreeBuildFromList -- * - * Build or extend string indexed tree from tcl list. - * If the values not given the values of built list are indices starts with 1. - * Value of 0 is thereby reserved to the ambigous values. + * Build or extend string indexed tree from tcl list. If the values not + * given the values of built list are indices starts with 1. Value of 0 + * is thereby reserved to the ambigous values. * - * Important: by multiple lists, optimal tree can be created only if list with - * larger strings used firstly. + * Important: by multiple lists, optimal tree can be created only if list + * with larger strings used firstly. * * Results: - * Returns a standard Tcl result. + * Returns a standard Tcl result. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -227,19 +241,19 @@ int TclStrIdxTreeBuildFromList( TclStrIdxTree *idxTree, Tcl_Size lstc, - Tcl_Obj **lstv, + Tcl_Obj **lstv, void **values) { - Tcl_Obj **lwrv; + Tcl_Obj **lwrv; Tcl_Size i; int ret = TCL_ERROR; void *val; const char *s, *e, *f; - TclStrIdx *item; + TclStrIdx *item; /* create lowercase reflection of the list keys */ - lwrv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*) * lstc); + lwrv = (Tcl_Obj **) attemptckalloc(sizeof(Tcl_Obj*) * lstc); if (lwrv == NULL) { return TCL_ERROR; } @@ -255,18 +269,22 @@ TclStrIdxTreeBuildFromList( /* build index tree of the list keys */ for (i = 0; i < lstc; i++) { TclStrIdxTree *foundParent = idxTree; + e = s = TclGetString(lwrv[i]); e += lwrv[i]->length; val = values ? values[i] : INT2PTR(i+1); /* ignore empty keys (impossible to index it) */ - if (lwrv[i]->length == 0) continue; + if (lwrv[i]->length == 0) { + continue; + } item = NULL; if (idxTree->firstPtr != NULL) { - TclStrIdx *foundItem; + TclStrIdx *foundItem; + f = TclStrIdxTreeSearch(&foundParent, &foundItem, - idxTree, s, e); + idxTree, s, e); /* if common prefix was found */ if (f > s) { /* ignore element if fulfilled or ambigous */ @@ -275,11 +293,10 @@ TclStrIdxTreeBuildFromList( } /* if shortest key was found with the same value, * just replace its current key with longest key */ - if ( foundItem->value == val - && foundItem->length <= lwrv[i]->length - && foundItem->length <= (f - s) /* only if found item is covered in full */ - && foundItem->childTree.firstPtr == NULL - ) { + if (foundItem->value == val + && foundItem->length <= lwrv[i]->length + && foundItem->length <= (f - s) /* only if found item is covered in full */ + && foundItem->childTree.firstPtr == NULL) { TclSetObjRef(foundItem->key, lwrv[i]); foundItem->length = lwrv[i]->length; continue; @@ -288,7 +305,7 @@ TclStrIdxTreeBuildFromList( * but don't split by fulfilled child of found item ( ii->iii->iiii ) */ if (foundItem->length != (f - s)) { /* first split found item (insert one between parent and found + new one) */ - item = (TclStrIdx *)ckalloc(sizeof(TclStrIdx)); + item = (TclStrIdx *) attemptckalloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -306,7 +323,7 @@ TclStrIdxTreeBuildFromList( } } /* append item at end of found parent */ - item = (TclStrIdx *)ckalloc(sizeof(TclStrIdx)); + item = (TclStrIdx *) attemptckalloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -315,120 +332,118 @@ TclStrIdxTreeBuildFromList( item->length = lwrv[i]->length; item->value = val; TclStrIdxTreeAppend(foundParent, item); - }; + } ret = TCL_OK; - -done: - + done: if (lwrv != NULL) { for (i = 0; i < lstc; i++) { Tcl_DecrRefCount(lwrv[i]); } ckfree(lwrv); } - if (ret != TCL_OK) { if (idxTree->firstPtr != NULL) { TclStrIdxTreeFree(idxTree->firstPtr); } } - return ret; } +/* Follow links (smart pointers). */ +static inline Tcl_Obj * +FollowPossibleLink( + Tcl_Obj *objPtr) +{ + if (objPtr->internalRep.twoPtrValue.ptr1 != NULL + && objPtr->internalRep.twoPtrValue.ptr2 == NULL) { + objPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr1; + } + return objPtr; +} -static void -StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); -static void -StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr); -static void -StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr); - -Tcl_ObjType StrIdxTreeObjType = { - "str-idx-tree", /* name */ - StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */ - StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */ - StrIdxTreeObj_UpdateStringProc, /* updateStringProc */ - NULL, /* setFromAnyProc */ - TCL_OBJTYPE_V0 -}; - -Tcl_Obj* -TclStrIdxTreeNewObj() +Tcl_Obj * +TclStrIdxTreeNewObj(void) { Tcl_Obj *objPtr = Tcl_NewObj(); - objPtr->internalRep.twoPtrValue.ptr1 = NULL; - objPtr->internalRep.twoPtrValue.ptr2 = NULL; + TclStrIdxTree *tree = (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue; + + /* + * This assert states that we can safely directly have a tree node as the + * internal representation of a Tcl_Obj instead of needing to hang it + * off the back with an extra alloc. + */ + TCL_CT_ASSERT(sizeof(TclStrIdxTree) <= sizeof(Tcl_ObjInternalRep)); + + tree->firstPtr = NULL; + tree->lastPtr = NULL; objPtr->typePtr = &StrIdxTreeObjType; /* return tree root in internal representation */ return objPtr; } static void -StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) +StrIdxTreeObj_DupIntRepProc( + Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr) { /* follow links (smart pointers) */ - if ( srcPtr->internalRep.twoPtrValue.ptr1 != NULL - && srcPtr->internalRep.twoPtrValue.ptr2 == NULL - ) { - srcPtr = (Tcl_Obj*)srcPtr->internalRep.twoPtrValue.ptr1; - } + srcPtr = FollowPossibleLink(srcPtr); /* create smart pointer to it (ptr1 != NULL, ptr2 = NULL) */ - TclInitObjRef(*((Tcl_Obj **)©Ptr->internalRep.twoPtrValue.ptr1), - srcPtr); + TclInitObjRef(*((Tcl_Obj **) ©Ptr->internalRep.twoPtrValue.ptr1), + srcPtr); copyPtr->internalRep.twoPtrValue.ptr2 = NULL; copyPtr->typePtr = &StrIdxTreeObjType; } static void -StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr) +StrIdxTreeObj_FreeIntRepProc( + Tcl_Obj *objPtr) { /* follow links (smart pointers) */ - if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL - && objPtr->internalRep.twoPtrValue.ptr2 == NULL - ) { + if (objPtr->internalRep.twoPtrValue.ptr1 != NULL + && objPtr->internalRep.twoPtrValue.ptr2 == NULL) { /* is a link */ - TclUnsetObjRef(*((Tcl_Obj **)&objPtr->internalRep.twoPtrValue.ptr1)); + TclUnsetObjRef(*((Tcl_Obj **) &objPtr->internalRep.twoPtrValue.ptr1)); } else { /* is a tree */ - TclStrIdxTree *tree = (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1; + TclStrIdxTree *tree = (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue; + if (tree->firstPtr != NULL) { TclStrIdxTreeFree(tree->firstPtr); } - objPtr->internalRep.twoPtrValue.ptr1 = NULL; - objPtr->internalRep.twoPtrValue.ptr2 = NULL; + tree->firstPtr = NULL; + tree->lastPtr = NULL; } objPtr->typePtr = NULL; -}; +} static void -StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr) +StrIdxTreeObj_UpdateStringProc( + Tcl_Obj *objPtr) { /* currently only dummy empty string possible */ objPtr->length = 0; objPtr->bytes = &tclEmptyString; -}; +} TclStrIdxTree * -TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr) { - /* follow links (smart pointers) */ +TclStrIdxTreeGetFromObj( + Tcl_Obj *objPtr) +{ if (objPtr->typePtr != &StrIdxTreeObjType) { return NULL; } - if ( objPtr->internalRep.twoPtrValue.ptr1 != NULL - && objPtr->internalRep.twoPtrValue.ptr2 == NULL - ) { - objPtr = (Tcl_Obj*)objPtr->internalRep.twoPtrValue.ptr1; - } + /* follow links (smart pointers) */ + objPtr = FollowPossibleLink(objPtr); /* return tree root in internal representation */ - return (TclStrIdxTree*)&objPtr->internalRep.twoPtrValue.ptr1; + return (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue; } - + /* * Several debug primitives */ -#if 0 +#ifdef TEST_STR_IDX_TREE /* currently unused, debug resp. test purposes only */ static void @@ -439,6 +454,7 @@ TclStrIdxTreePrint( { Tcl_Obj *obj[2]; const char *s; + TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", -1)); while (tree != NULL) { s = TclGetString(tree->key) + offs; @@ -454,14 +470,12 @@ TclStrIdxTreePrint( TclUnsetObjRef(obj[0]); } - int TclStrIdxTreeTestObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { const char *cs, *cin, *ret; - static const char *const options[] = { "index", "puts-index", "findequal", NULL @@ -476,7 +490,7 @@ TclStrIdxTreeTestObjCmd( return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, - "option", 0, &optionIndex) != TCL_OK) { + "option", 0, &optionIndex) != TCL_OK) { Tcl_SetErrorCode(interp, "CLOCK", "badOption", TclGetString(objv[1]), (char *)NULL); return TCL_ERROR; @@ -490,33 +504,33 @@ TclStrIdxTreeTestObjCmd( cs = TclGetString(objv[2]); cin = TclGetString(objv[3]); ret = TclUtfFindEqual( - cs, cs + objv[1]->length, cin, cin + objv[2]->length); + cs, cs + objv[1]->length, cin, cin + objv[2]->length); Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs)); - break; + break; case O_INDEX: case O_PUTS_INDEX: { Tcl_Obj **lstv; int i, lstc; TclStrIdxTree idxTree = {NULL, NULL}; + i = 1; while (++i < objc) { if (TclListObjGetElements(interp, objv[i], &lstc, &lstv) != TCL_OK) { return TCL_ERROR; - }; + } TclStrIdxTreeBuildFromList(&idxTree, lstc, lstv, NULL); } if (optionIndex == O_PUTS_INDEX) { TclStrIdxTreePrint(interp, idxTree.firstPtr, 0); } TclStrIdxTreeFree(idxTree.firstPtr); + break; } - break; } return TCL_OK; } - #endif /* diff --git a/generic/tclStrIdxTree.h b/generic/tclStrIdxTree.h index 28e0710..c5a6716 100644 --- a/generic/tclStrIdxTree.h +++ b/generic/tclStrIdxTree.h @@ -13,17 +13,36 @@ #ifndef _TCLSTRIDXTREE_H #define _TCLSTRIDXTREE_H +#include "tclInt.h" + /* * Main structures declarations of index tree and entry */ typedef struct TclStrIdx TclStrIdx; +/* + * Top level structure of the tree, or first two fields of the interior + * structure. + * + * Note that this is EXACTLY two pointers so it is the same size as the + * twoPtrValue of a Tcl_ObjInternalRep. This is how the top level structure + * of the tree is always allocated. (This type constraint is asserted in + * TclStrIdxTreeNewObj() so it's guaranteed.) + * + * Also note that if firstPtr is not NULL, lastPtr must also be not NULL. + * The case where firstPtr is not NULL and lastPtr is NULL is special (a + * smart pointer to one of these) and is not actually a valid instance of + * this structure. + */ typedef struct TclStrIdxTree { TclStrIdx *firstPtr; TclStrIdx *lastPtr; } TclStrIdxTree; +/* + * An interior node of the tree. Always directly allocated. + */ struct TclStrIdx { TclStrIdxTree childTree; TclStrIdx *nextPtr; @@ -38,13 +57,13 @@ struct TclStrIdx { * * TclUtfFindEqual, TclUtfFindEqualNC -- * - * Find largest part of string cs in string cin (case sensitive and not). + * Find largest part of string cs in string cin (case sensitive and not). * * Results: - * Return position of UTF character in cs after last equal character. + * Return position of UTF character in cs after last equal character. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -133,14 +152,14 @@ TclUtfFindEqualNCInLwr( } while (0) #define TclInitObjRef(obj, val) \ do { \ - obj = val; \ + obj = (val); \ if (obj) { \ Tcl_IncrRefCount(obj); \ } \ } while (0) #define TclSetObjRef(obj, val) \ do { \ - Tcl_Obj *nval = val; \ + Tcl_Obj *nval = (val); \ if (obj != nval) { \ Tcl_Obj *prev = obj; \ TclInitObjRef(obj, nval); \ @@ -162,7 +181,7 @@ MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree, MODULE_SCOPE Tcl_Obj * TclStrIdxTreeNewObj(); MODULE_SCOPE TclStrIdxTree*TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr); -#if 0 +#ifdef TEST_STR_IDX_TREE /* currently unused, debug resp. test purposes only */ MODULE_SCOPE Tcl_ObjCmdProc TclStrIdxTreeTestObjCmd; #endif -- cgit v0.12 From e42f21d821a4789b2d96ef611ed7c8aaacc0b0f4 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 11 Apr 2024 13:22:39 +0000 Subject: (cherry-pick): Possibly a fix for [080f846fd58958ef]: When updating the interest of a channel, don't schedule the channel handler timer if a nonblocking channel doesn't yet have a buffer or if the buffer is empty or overflowing. Where asynchronous connection state is concerned, this should mean that the time won't be scheduled if the initial connection isn't established. --- generic/tclIO.c | 10 +++++++--- generic/tclStrIdxTree.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/generic/tclIO.c b/generic/tclIO.c index b8897eb..1bfcd4f 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -8760,6 +8760,7 @@ UpdateInterest( { ChannelState *statePtr = chanPtr->state; /* State info for channel */ + ChannelBuffer *bufPtr = statePtr->outQueueHead; int mask = statePtr->interestMask; if (chanPtr->typePtr == NULL) { @@ -8839,15 +8840,18 @@ UpdateInterest( } if (!statePtr->timer - && mask & TCL_WRITABLE - && GotFlag(statePtr, CHANNEL_NONBLOCKING)) { + && (mask & TCL_WRITABLE) + && GotFlag(statePtr, CHANNEL_NONBLOCKING) + && bufPtr + && !IsBufferEmpty(bufPtr) + && !IsBufferFull(bufPtr) + ) { TclChannelPreserve((Tcl_Channel)chanPtr); statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); } - ChanWatch(chanPtr, mask); } diff --git a/generic/tclStrIdxTree.h b/generic/tclStrIdxTree.h index c5a6716..0352f90 100644 --- a/generic/tclStrIdxTree.h +++ b/generic/tclStrIdxTree.h @@ -24,7 +24,7 @@ typedef struct TclStrIdx TclStrIdx; /* * Top level structure of the tree, or first two fields of the interior * structure. - * + * * Note that this is EXACTLY two pointers so it is the same size as the * twoPtrValue of a Tcl_ObjInternalRep. This is how the top level structure * of the tree is always allocated. (This type constraint is asserted in -- cgit v0.12 From 20ac5ab1d39ebc78f06c1bcabb7a615f73017c30 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 11 Apr 2024 13:35:27 +0000 Subject: A few more small changes --- generic/tclStrIdxTree.c | 18 +++++++++++++----- generic/tclStrIdxTree.h | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index af45c53..b6e0672 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -350,15 +350,24 @@ TclStrIdxTreeBuildFromList( return ret; } -/* Follow links (smart pointers). */ +/* Is a Tcl_Obj (of right type) holding a smart pointer link? */ +static inline int +IsLink( + Tcl_Obj *objPtr) +{ + Tcl_ObjInternalRep *irPtr = &objPtr->internalRep; + return irPtr->twoPtrValue.ptr1 && !irPtr->twoPtrValue.ptr2; +} + +/* Follow links (smart pointers) if present. */ static inline Tcl_Obj * FollowPossibleLink( Tcl_Obj *objPtr) { - if (objPtr->internalRep.twoPtrValue.ptr1 != NULL - && objPtr->internalRep.twoPtrValue.ptr2 == NULL) { + if (IsLink(objPtr)) { objPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr1; } + /* assert(!IsLink(objPtr)); */ return objPtr; } @@ -401,8 +410,7 @@ StrIdxTreeObj_FreeIntRepProc( Tcl_Obj *objPtr) { /* follow links (smart pointers) */ - if (objPtr->internalRep.twoPtrValue.ptr1 != NULL - && objPtr->internalRep.twoPtrValue.ptr2 == NULL) { + if (IsLink(objPtr)) { /* is a link */ TclUnsetObjRef(*((Tcl_Obj **) &objPtr->internalRep.twoPtrValue.ptr1)); } else { diff --git a/generic/tclStrIdxTree.h b/generic/tclStrIdxTree.h index 0352f90..3aa43f2 100644 --- a/generic/tclStrIdxTree.h +++ b/generic/tclStrIdxTree.h @@ -178,7 +178,7 @@ MODULE_SCOPE const char*TclStrIdxTreeSearch(TclStrIdxTree **foundParent, const char *start, const char *end); MODULE_SCOPE int TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree, Tcl_Size lstc, Tcl_Obj **lstv, void **values); -MODULE_SCOPE Tcl_Obj * TclStrIdxTreeNewObj(); +MODULE_SCOPE Tcl_Obj * TclStrIdxTreeNewObj(void); MODULE_SCOPE TclStrIdxTree*TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr); #ifdef TEST_STR_IDX_TREE -- cgit v0.12 From 1ba24536456192e2d32ba0a36d4d2e67cfd74050 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 11 Apr 2024 13:55:02 +0000 Subject: No need for TCL_OBJTYPE_V0 in Tcl 8.7. Make StrIdxTreeObjType static const. Define TCL_OBJTYPE_V1/TCL_OBJTYPE_V2 for 8.7 --- generic/tcl.h | 2 ++ generic/tclClockFmt.c | 3 +-- generic/tclStrIdxTree.c | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index ca8901d..de74afb 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -783,6 +783,8 @@ typedef struct Tcl_ObjType { * old type. Returns TCL_ERROR on failure. */ } Tcl_ObjType; #define TCL_OBJTYPE_V0 /* just empty */ +#define TCL_OBJTYPE_V1(a) /* just empty */ +#define TCL_OBJTYPE_V2(a,b,c,d,e,f,g,h) /* just empty */ /* * The following structure stores an internal representation (internalrep) for diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index b9ce546..b5d507c 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -592,8 +592,7 @@ static const Tcl_ObjType ClockFmtObjType = { ClockFmtObj_FreeInternalRep, /* freeIntRepProc */ ClockFmtObj_DupInternalRep, /* dupIntRepProc */ ClockFmtObj_UpdateString, /* updateStringProc */ - ClockFmtObj_SetFromAny, /* setFromAnyProc */ - TCL_OBJTYPE_V0 + ClockFmtObj_SetFromAny /* setFromAnyProc */ }; #define ObjClockFmtScn(objPtr) \ diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index b6e0672..a1c83a9 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -60,13 +60,12 @@ static void StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr); static void StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr); -Tcl_ObjType StrIdxTreeObjType = { +static const Tcl_ObjType StrIdxTreeObjType = { "str-idx-tree", /* name */ StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */ StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */ StrIdxTreeObj_UpdateStringProc, /* updateStringProc */ - NULL, /* setFromAnyProc */ - TCL_OBJTYPE_V0 + NULL /* setFromAnyProc */ }; /* -- cgit v0.12 From db6c362be10ac3c32b2b59014d092a6afa393978 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 11 Apr 2024 15:19:45 +0000 Subject: Next stage of migrating things to follow style: clock format support --- generic/tclClockFmt.c | 1196 ++++++++++++++++++++++++++----------------------- generic/tclDate.h | 213 ++++----- 2 files changed, 730 insertions(+), 679 deletions(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index b5d507c..06684a6 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -18,22 +18,22 @@ * Miscellaneous forward declarations and functions used within this file */ -static void -ClockFmtObj_DupInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); -static void -ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr); -static int -ClockFmtObj_SetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); -static void -ClockFmtObj_UpdateString(Tcl_Obj *objPtr); - +static void ClockFmtObj_DupInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); +static void ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr); +static int ClockFmtObj_SetFromAny(Tcl_Interp *, Tcl_Obj *objPtr); +static void ClockFmtObj_UpdateString(Tcl_Obj *objPtr); -TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */ +TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */ -static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss); +static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss); +static void ClockFrmScnFinalize(void *); -static void ClockFrmScnFinalize(void *clientData); +/* + * Derivation of tclStringHashKeyType with another allocEntryProc + */ +static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; + /* * Clock scan and format facilities. */ @@ -58,35 +58,39 @@ static void ClockFrmScnFinalize(void *clientData); static inline void _str2int_no( - int *out, + int *out, const char *p, const char *e, int sign) { - /* assert(e <= p+10); */ + /* assert(e <= p + 10); */ int val = 0; /* overflow impossible for 10 digits ("9..9"), so no needs to check at all */ while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } - if (sign < 0) { val = -val; } + if (sign < 0) { + val = -val; + } *out = val; } static inline void _str2wideInt_no( Tcl_WideInt *out, - const char *p, - const char *e, + const char *p, + const char *e, int sign) { - /* assert(e <= p+18); */ + /* assert(e <= p + 18); */ Tcl_WideInt val = 0; /* overflow impossible for 18 digits ("9..9"), so no needs to check at all */ while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } - if (sign < 0) { val = -val; } + if (sign < 0) { + val = -val; + } *out = val; } @@ -97,14 +101,14 @@ _str2wideInt_no( static inline int _str2int( - int *out, + int *out, const char *p, const char *e, int sign) { int val = 0; /* overflow impossible for 10 digits ("9..9"), so no needs to check before */ - const char *eNO = p+10; + const char *eNO = p + 10; if (eNO > e) { eNO = e; } @@ -136,13 +140,13 @@ _str2int( static inline int _str2wideInt( Tcl_WideInt *out, - const char *p, - const char *e, + const char *p, + const char *e, int sign) { Tcl_WideInt val = 0; /* overflow impossible for 18 digits ("9..9"), so no needs to check before */ - const char *eNO = p+18; + const char *eNO = p + 18; if (eNO > e) { eNO = e; } @@ -174,8 +178,8 @@ _str2wideInt( int TclAtoWIe( Tcl_WideInt *out, - const char *p, - const char *e, + const char *p, + const char *e, int sign) { return _str2wideInt(out, p, e, sign); @@ -205,16 +209,15 @@ static inline char * _itoaw( char *buf, int val, - char padchar, - unsigned short int width) + char padchar, + unsigned short width) { char *p; static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; /* positive integer */ - if (val >= 0) - { + if (val >= 0) { /* check resp. recalculate width */ while (width <= 9 && val >= wrange[width]) { width++; @@ -223,7 +226,8 @@ _itoaw( p = buf + width; *p-- = '\0'; do { - char c = (val % 10); val /= 10; + char c = (val % 10); + val /= 10; *p-- = '0' + c; } while (val > 0); /* fulling with pad-char */ @@ -235,7 +239,9 @@ _itoaw( } /* negative integer */ - if (!width) width++; + if (!width) { + width++; + } /* check resp. recalculate width (regarding sign) */ width--; while (width <= 9 && val <= -wrange[width]) { @@ -248,23 +254,29 @@ _itoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); val /= 10; + char c = (val % 10); + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); val /= 10; + char c = (val % 10); + val /= 10; *p-- = '0' + c; } while (val < 0); } /* sign by 0 padding */ - if (padchar != '0') { *p-- = '-'; } + if (padchar != '0') { + *p-- = '-'; + } /* fulling with pad-char */ while (p >= buf + 1) { *p-- = padchar; } /* sign by non 0 padding */ - if (padchar == '0') { *p = '-'; } + if (padchar == '0') { + *p = '-'; + } return buf + width; } @@ -272,8 +284,8 @@ char * TclItoAw( char *buf, int val, - char padchar, - unsigned short int width) + char padchar, + unsigned short width) { return _itoaw(buf, val, padchar, width); } @@ -282,20 +294,18 @@ static inline char * _witoaw( char *buf, Tcl_WideInt val, - char padchar, - unsigned short int width) + char padchar, + unsigned short width) { char *p; static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; /* positive integer */ - if (val >= 0) - { + if (val >= 0) { /* check resp. recalculate width */ if (val >= 10000000000LL) { - Tcl_WideInt val2; - val2 = val / 10000000000LL; + Tcl_WideInt val2 = val / 10000000000LL; while (width <= 9 && val2 >= wrange[width]) { width++; } @@ -309,7 +319,8 @@ _witoaw( p = buf + width; *p-- = '\0'; do { - char c = (val % 10); val /= 10; + char c = (val % 10); + val /= 10; *p-- = '0' + c; } while (val > 0); /* fulling with pad-char */ @@ -322,12 +333,13 @@ _witoaw( /* negative integer */ - if (!width) width++; + if (!width) { + width++; + } /* check resp. recalculate width (regarding sign) */ width--; if (val <= -10000000000LL) { - Tcl_WideInt val2; - val2 = val / 10000000000LL; + Tcl_WideInt val2 = val / 10000000000LL; while (width <= 9 && val2 <= -wrange[width]) { width++; } @@ -344,23 +356,29 @@ _witoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); val /= 10; + char c = (val % 10); + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); val /= 10; + char c = (val % 10); + val /= 10; *p-- = '0' + c; } while (val < 0); } /* sign by 0 padding */ - if (padchar != '0') { *p-- = '-'; } + if (padchar != '0') { + *p-- = '-'; + } /* fulling with pad-char */ while (p >= buf + 1) { *p-- = padchar; } /* sign by non 0 padding */ - if (padchar == '0') { *p = '-'; } + if (padchar == '0') { + *p = '-'; + } return buf + width; } @@ -379,10 +397,10 @@ _witoaw( #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 -static struct { - ClockFmtScnStorage *stackPtr; - ClockFmtScnStorage *stackBound; - unsigned int count; +static struct ClockFmtScnStorage_GC { + ClockFmtScnStorage *stackPtr; + ClockFmtScnStorage *stackBound; + unsigned count; } ClockFmtScnStorage_GC = {NULL, NULL, 0}; /* @@ -404,7 +422,8 @@ static struct { */ static inline void -ClockFmtScnStorageGC_In(ClockFmtScnStorage *entry) +ClockFmtScnStorageGC_In( + ClockFmtScnStorage *entry) { /* add new entry */ TclSpliceIn(entry, ClockFmtScnStorage_GC.stackPtr); @@ -415,9 +434,9 @@ ClockFmtScnStorageGC_In(ClockFmtScnStorage *entry) /* if GC ist full */ if (ClockFmtScnStorage_GC.count > CLOCK_FMT_SCN_STORAGE_GC_SIZE) { - /* GC stack is LIFO: delete first inserted entry */ ClockFmtScnStorage *delEnt = ClockFmtScnStorage_GC.stackBound; + ClockFmtScnStorage_GC.stackBound = delEnt->prevPtr; TclSpliceOut(delEnt, ClockFmtScnStorage_GC.stackPtr); ClockFmtScnStorage_GC.count--; @@ -443,7 +462,8 @@ ClockFmtScnStorageGC_In(ClockFmtScnStorage *entry) */ static inline void -ClockFmtScnStorage_GC_Out(ClockFmtScnStorage *entry) +ClockFmtScnStorage_GC_Out( + ClockFmtScnStorage *entry) { TclSpliceOut(entry, ClockFmtScnStorage_GC.stackPtr); ClockFmtScnStorage_GC.count--; @@ -452,10 +472,8 @@ ClockFmtScnStorage_GC_Out(ClockFmtScnStorage *entry) } entry->prevPtr = entry->nextPtr = NULL; } - #endif - /* * Global format storage hash table of type ClockFmtScnStorageHashKeyType * (contains list of scan/format object storages, shared across all threads). @@ -463,20 +481,25 @@ ClockFmtScnStorage_GC_Out(ClockFmtScnStorage *entry) * Used for fast searching by format string. */ static Tcl_HashTable FmtScnHashTable; -static int initialized = 0; +static int initialized = 0; /* * Wrappers between pointers to hash entry and format storage object */ static inline Tcl_HashEntry * -HashEntry4FmtScn(ClockFmtScnStorage *fss) { +HashEntry4FmtScn( + ClockFmtScnStorage *fss) +{ return (Tcl_HashEntry*)(fss + 1); -}; +} + static inline ClockFmtScnStorage * -FmtScn4HashEntry(Tcl_HashEntry *hKeyPtr) { +FmtScn4HashEntry( + Tcl_HashEntry *hKeyPtr) +{ return (ClockFmtScnStorage*)(((char*)hKeyPtr) - sizeof(ClockFmtScnStorage)); -}; - +} + /* *---------------------------------------------------------------------- * @@ -499,26 +522,26 @@ ClockFmtScnStorageAllocProc( ClockFmtScnStorage *fss; const char *string = (const char *) keyPtr; Tcl_HashEntry *hPtr; - unsigned int size, - allocsize = sizeof(ClockFmtScnStorage) + sizeof(Tcl_HashEntry); + unsigned size = strlen(string) + 1; + unsigned allocsize = sizeof(ClockFmtScnStorage) + sizeof(Tcl_HashEntry); - allocsize += (size = strlen(string) + 1); + allocsize += size; if (size > sizeof(hPtr->key)) { allocsize -= sizeof(hPtr->key); } - fss = (ClockFmtScnStorage *)ckalloc(allocsize); + fss = (ClockFmtScnStorage *) ckalloc(allocsize); /* initialize */ memset(fss, 0, sizeof(*fss)); hPtr = HashEntry4FmtScn(fss); memcpy(&hPtr->key.string, string, size); - hPtr->clientData = 0; /* currently unused */ + hPtr->clientData = 0; /* currently unused */ return hPtr; } - + /* *---------------------------------------------------------------------- * @@ -551,7 +574,7 @@ ClockFmtScnStorageFreeProc( ckfree(fss); } - + /* *---------------------------------------------------------------------- * @@ -566,33 +589,27 @@ ClockFmtScnStorageFreeProc( */ static void -ClockFmtScnStorageDelete(ClockFmtScnStorage *fss) { - Tcl_HashEntry *hPtr = HashEntry4FmtScn(fss); +ClockFmtScnStorageDelete( + ClockFmtScnStorage *fss) +{ + Tcl_HashEntry *hPtr = HashEntry4FmtScn(fss); /* * This will delete a hash entry and call "Tcl_Free" for storage self, if * some additionally handling required, freeEntryProc can be used instead */ Tcl_DeleteHashEntry(hPtr); } - - -/* - * Derivation of tclStringHashKeyType with another allocEntryProc - */ - -static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; - /* * Type definition of clock-format tcl object type. */ static const Tcl_ObjType ClockFmtObjType = { - "clock-format", /* name */ - ClockFmtObj_FreeInternalRep, /* freeIntRepProc */ - ClockFmtObj_DupInternalRep, /* dupIntRepProc */ - ClockFmtObj_UpdateString, /* updateStringProc */ - ClockFmtObj_SetFromAny /* setFromAnyProc */ + "clock-format", /* name */ + ClockFmtObj_FreeInternalRep, /* freeIntRepProc */ + ClockFmtObj_DupInternalRep, /* dupIntRepProc */ + ClockFmtObj_UpdateString, /* updateStringProc */ + ClockFmtObj_SetFromAny /* setFromAnyProc */ }; #define ObjClockFmtScn(objPtr) \ @@ -623,10 +640,9 @@ ClockFmtObj_DupInternalRep( } copyPtr->typePtr = &ClockFmtObjType; - /* if no format representation, dup string representation */ if (fss == NULL) { - copyPtr->bytes = (char *)ckalloc(srcPtr->length + 1); + copyPtr->bytes = (char *) ckalloc(srcPtr->length + 1); memcpy(copyPtr->bytes, srcPtr->bytes, srcPtr->length + 1); copyPtr->length = srcPtr->length; } @@ -641,13 +657,13 @@ ClockFmtObj_FreeInternalRep( Tcl_MutexLock(&ClockFmtMutex); /* decrement object reference count of format/scan storage */ if (--fss->objRefCount <= 0) { - #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 - /* don't remove it right now (may be reusable), just add to GC */ - ClockFmtScnStorageGC_In(fss); - #else - /* remove storage (format representation) */ - ClockFmtScnStorageDelete(fss); - #endif +#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 + /* don't remove it right now (may be reusable), just add to GC */ + ClockFmtScnStorageGC_In(fss); +#else + /* remove storage (format representation) */ + ClockFmtScnStorageDelete(fss); +#endif } Tcl_MutexUnlock(&ClockFmtMutex); } @@ -658,12 +674,12 @@ ClockFmtObj_FreeInternalRep( ObjLocFmtKey(objPtr) = NULL; } objPtr->typePtr = NULL; -}; +} static int ClockFmtObj_SetFromAny( TCL_UNUSED(Tcl_Interp *), - Tcl_Obj *objPtr) + Tcl_Obj *objPtr) { /* validate string representation before free old internal representation */ (void)TclGetString(objPtr); @@ -677,11 +693,11 @@ ClockFmtObj_SetFromAny( objPtr->typePtr = &ClockFmtObjType; return TCL_OK; -}; +} static void ClockFmtObj_UpdateString( - Tcl_Obj *objPtr) + Tcl_Obj *objPtr) { const char *name = "UNKNOWN"; size_t len; @@ -693,7 +709,7 @@ ClockFmtObj_UpdateString( } len = strlen(name); objPtr->length = len++, - objPtr->bytes = (char *)ckalloc(len); + objPtr->bytes = (char *) attemptckalloc(len); if (objPtr->bytes) { memcpy(objPtr->bytes, name, len); } @@ -723,7 +739,7 @@ ClockFmtObj_UpdateString( Tcl_Obj* ClockFrmObjGetLocFmtKey( Tcl_Interp *interp, - Tcl_Obj *objPtr) + Tcl_Obj *objPtr) { Tcl_Obj *keyObj; @@ -770,7 +786,7 @@ ClockFrmObjGetLocFmtKey( static ClockFmtScnStorage * FindOrCreateFmtScnStorage( Tcl_Interp *interp, - Tcl_Obj *objPtr) + Tcl_Obj *objPtr) { const char *strFmt = TclGetString(objPtr); ClockFmtScnStorage *fss = NULL; @@ -788,7 +804,7 @@ FindOrCreateFmtScnStorage( /* initialize hash table */ Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS, - &ClockFmtScnStorageHashKeyType); + &ClockFmtScnStorageHashKeyType); initialized = 1; Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL); @@ -797,19 +813,17 @@ FindOrCreateFmtScnStorage( /* get or create entry (and alocate storage) */ hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew); if (hPtr != NULL) { - fss = FmtScn4HashEntry(hPtr); - #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 - /* unlink if it is currently in GC */ - if (isNew == 0 && fss->objRefCount == 0) { - ClockFmtScnStorage_GC_Out(fss); - } - #endif +#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 + /* unlink if it is currently in GC */ + if (isNew == 0 && fss->objRefCount == 0) { + ClockFmtScnStorage_GC_Out(fss); + } +#endif /* new reference, so increment in lock right now */ fss->objRefCount++; - ObjClockFmtScn(objPtr) = fss; } @@ -817,7 +831,7 @@ FindOrCreateFmtScnStorage( if (fss == NULL && interp != NULL) { Tcl_AppendResult(interp, "retrieve clock format failed \"", - strFmt ? strFmt : "", "\"", NULL); + strFmt ? strFmt : "", "\"", NULL); Tcl_SetErrorCode(interp, "TCL", "EINVAL", (char *)NULL); } @@ -905,25 +919,25 @@ ClockLocalizeFormat( if (opts->mcDictObj == NULL) { ClockMCDict(opts); - if (opts->mcDictObj == NULL) + if (opts->mcDictObj == NULL) { goto done; + } } /* try to find in cache within locale mc-catalog */ - if (Tcl_DictObjGet(NULL, opts->mcDictObj, - keyObj, &valObj) != TCL_OK) { + if (Tcl_DictObjGet(NULL, opts->mcDictObj, keyObj, &valObj) != TCL_OK) { goto done; } /* call LocalizeFormat locale format fmtkey */ if (valObj == NULL) { Tcl_Obj *callargs[4]; + callargs[0] = dataPtr->literals[LIT_LOCALIZE_FORMAT]; callargs[1] = opts->localeObj; callargs[2] = opts->formatObj; callargs[3] = opts->mcDictObj; - if (Tcl_EvalObjv(opts->interp, 4, callargs, 0) == TCL_OK - ) { + if (Tcl_EvalObjv(opts->interp, 4, callargs, 0) == TCL_OK) { valObj = Tcl_GetObjResult(opts->interp); } @@ -931,15 +945,13 @@ ClockLocalizeFormat( if (opts->mcDictObj->refCount > 1) { /* smart reference (shared dict as object with no ref-counter) */ opts->mcDictObj = TclDictObjSmartRef(opts->interp, - opts->mcDictObj); + opts->mcDictObj); } if (!valObj) { goto done; } /* cache it inside mc-dictionary (this incr. ref count of keyObj/valObj) */ - if (Tcl_DictObjPut(opts->interp, opts->mcDictObj, - keyObj, valObj) != TCL_OK - ) { + if (Tcl_DictObjPut(opts->interp, opts->mcDictObj, keyObj, valObj) != TCL_OK) { valObj = NULL; goto done; } @@ -984,31 +996,31 @@ FindTokenBegin( const char *end, ClockScanToken *tok) { - char c; if (p < end) { + char c; + /* next token a known token type */ switch (tok->map->type) { case CTOKT_INT: case CTOKT_WIDE: /* should match at least one digit */ - while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}; + while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} return p; - break; + case CTOKT_WORD: c = *(tok->tokWord.start); /* should match at least to the first char of this word */ - while (*p != c && (p = Tcl_UtfNext(p)) < end) {}; + while (*p != c && (p = Tcl_UtfNext(p)) < end) {} return p; - break; + case CTOKT_SPACE: - while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}; + while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} return p; - break; + case CTOKT_CHAR: c = *((char *)tok->map->data); - while (*p != c && (p = Tcl_UtfNext(p)) < end) {}; + while (*p != c && (p = Tcl_UtfNext(p)) < end) {} return p; - break; } } return p; @@ -1032,8 +1044,10 @@ FindTokenBegin( static void DetermineGreedySearchLen( - DateInfo *info, ClockScanToken *tok, - int *minLenPtr, int *maxLenPtr) + DateInfo *info, + ClockScanToken *tok, + int *minLenPtr, + int *maxLenPtr) { int minLen = tok->map->minSize; int maxLen; @@ -1041,10 +1055,10 @@ DetermineGreedySearchLen( *end = info->dateEnd; /* if still tokens available, try to correct minimum length */ - if ((tok+1)->map) { + if ((tok + 1)->map) { end -= tok->endDistance + yySpaceCount; /* find position of next known token */ - p = FindTokenBegin(p, end, tok+1); + p = FindTokenBegin(p, end, tok + 1); if (p < end) { minLen = p - yyInput; } @@ -1055,7 +1069,7 @@ DetermineGreedySearchLen( /* several amendments */ if (maxLen > tok->map->maxSize) { maxLen = tok->map->maxSize; - }; + } if (minLen < tok->map->minSize) { minLen = tok->map->minSize; } @@ -1070,8 +1084,12 @@ DetermineGreedySearchLen( if (tok->map->type == CTOKT_INT || tok->map->type == CTOKT_WIDE) { p = yyInput; end = p + maxLen; - if (end > info->dateEnd) { end = info->dateEnd; }; - while (isdigit(UCHAR(*p)) && p < end) { p++; }; + if (end > info->dateEnd) { + end = info->dateEnd; + } + while (isdigit(UCHAR(*p)) && p < end) { + p++; + } maxLen = p - yyInput; } @@ -1079,6 +1097,7 @@ DetermineGreedySearchLen( * check the next ahead token available there */ if (minLen < maxLen && tok->lookAhTok) { ClockScanToken *laTok = tok + tok->lookAhTok + 1; + p = yyInput + maxLen; /* regards all possible spaces here (because they are optional) */ end = p + tok->lookAhMax + yySpaceCount + 1; @@ -1087,10 +1106,10 @@ DetermineGreedySearchLen( } p += tok->lookAhMin; if (laTok->map && p < end) { - const char *f; + /* try to find laTok between [lookAhMin, lookAhMax] */ while (minLen < maxLen) { - f = FindTokenBegin(p, end, laTok); + const char *f = FindTokenBegin(p, end, laTok); /* if found (not below lookAhMax) */ if (f < end) { break; @@ -1131,19 +1150,22 @@ DetermineGreedySearchLen( static inline int ObjListSearch( - DateInfo *info, int *val, - Tcl_Obj **lstv, Tcl_Size lstc, - int minLen, int maxLen) + DateInfo *info, + int *val, + Tcl_Obj **lstv, + Tcl_Size lstc, + int minLen, + int maxLen) { Tcl_Size i, l, lf = -1; const char *s, *f, *sf; + /* search in list */ for (i = 0; i < lstc; i++) { s = TclGetStringFromObj(lstv[i], &l); - if ( l >= minLen - && (f = TclUtfFindEqualNC(yyInput, yyInput + maxLen, s, s + l, &sf)) > yyInput - ) { + if (l >= minLen + && (f = TclUtfFindEqualNC(yyInput, yyInput + maxLen, s, s + l, &sf)) > yyInput) { l = f - yyInput; if (l < minLen) { continue; @@ -1197,7 +1219,7 @@ LocaleListSearch(ClockFmtScnCmdArgs *opts, /* search in list */ return ObjListSearch(info, val, lstv, lstc, - minLen, maxLen); + minLen, maxLen); } #endif @@ -1224,15 +1246,14 @@ LocaleListSearch(ClockFmtScnCmdArgs *opts, static TclStrIdxTree * ClockMCGetListIdxTree( ClockFmtScnCmdArgs *opts, - int mcKey) + int mcKey) { - TclStrIdxTree * idxTree; + TclStrIdxTree *idxTree; Tcl_Obj *objPtr = ClockMCGetIdx(opts, mcKey); - if ( objPtr != NULL - && (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL - ) { - return idxTree; + if (objPtr != NULL + && (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL) { + return idxTree; } else { /* build new index */ @@ -1242,28 +1263,25 @@ ClockMCGetListIdxTree( objPtr = TclStrIdxTreeNewObj(); if ((idxTree = TclStrIdxTreeGetFromObj(objPtr)) == NULL) { - goto done; /* unexpected, but ...*/ + goto done; /* unexpected, but ...*/ } valObj = ClockMCGet(opts, mcKey); if (valObj == NULL) { goto done; } - - if (TclListObjGetElements(opts->interp, valObj, - &lstc, &lstv) != TCL_OK) { + if (TclListObjGetElements(opts->interp, valObj, &lstc, &lstv) != TCL_OK) { goto done; - }; - + } if (TclStrIdxTreeBuildFromList(idxTree, lstc, lstv, NULL) != TCL_OK) { goto done; } ClockMCSetIdx(opts, mcKey, objPtr); objPtr = NULL; - }; + } -done: + done: if (objPtr) { Tcl_DecrRefCount(objPtr); idxTree = NULL; @@ -1296,40 +1314,35 @@ done: static TclStrIdxTree * ClockMCGetMultiListIdxTree( ClockFmtScnCmdArgs *opts, - int mcKey, + int mcKey, int *mcKeys) { TclStrIdxTree * idxTree; Tcl_Obj *objPtr = ClockMCGetIdx(opts, mcKey); - if ( objPtr != NULL - && (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL - ) { - return idxTree; + if (objPtr != NULL + && (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL) { + return idxTree; } else { /* build new index */ Tcl_Obj **lstv; - Tcl_Size lstc; + Tcl_Size lstc; Tcl_Obj *valObj; objPtr = TclStrIdxTreeNewObj(); if ((idxTree = TclStrIdxTreeGetFromObj(objPtr)) == NULL) { - goto done; /* unexpected, but ...*/ + goto done; /* unexpected, but ...*/ } while (*mcKeys) { - valObj = ClockMCGet(opts, *mcKeys); if (valObj == NULL) { goto done; } - - if (TclListObjGetElements(opts->interp, valObj, - &lstc, &lstv) != TCL_OK) { + if (TclListObjGetElements(opts->interp, valObj, &lstc, &lstv) != TCL_OK) { goto done; - }; - + } if (TclStrIdxTreeBuildFromList(idxTree, lstc, lstv, NULL) != TCL_OK) { goto done; } @@ -1338,9 +1351,9 @@ ClockMCGetMultiListIdxTree( ClockMCSetIdx(opts, mcKey, objPtr); objPtr = NULL; - }; + } -done: + done: if (objPtr) { Tcl_DecrRefCount(objPtr); idxTree = NULL; @@ -1370,12 +1383,14 @@ done: static inline int ClockStrIdxTreeSearch( - DateInfo *info, TclStrIdxTree *idxTree, int *val, - int minLen, int maxLen) + DateInfo *info, + TclStrIdxTree *idxTree, + int *val, + int minLen, + int maxLen) { - const char *f; - TclStrIdx *foundItem; - f = TclStrIdxTreeSearch(NULL, &foundItem, idxTree, + TclStrIdx *foundItem; + const char *f = TclStrIdxTreeSearch(NULL, &foundItem, idxTree, yyInput, yyInput + maxLen); if (f <= yyInput || (f - yyInput) < minLen) { @@ -1398,16 +1413,19 @@ ClockStrIdxTreeSearch( /* currently unused */ static int -StaticListSearch(ClockFmtScnCmdArgs *opts, - DateInfo *info, const char **lst, int *val) +StaticListSearch( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + const char **lst, + int *val) { size_t len; const char **s = lst; + while (*s != NULL) { len = strlen(*s); - if ( len <= info->dateEnd - yyInput - && strncasecmp(yyInput, *s, len) == 0 - ) { + if (len <= info->dateEnd - yyInput + && strncasecmp(yyInput, *s, len) == 0) { *val = (s - lst); yyInput += len; break; @@ -1424,10 +1442,12 @@ StaticListSearch(ClockFmtScnCmdArgs *opts, static inline const char * FindWordEnd( ClockScanToken *tok, - const char * p, const char * end) + const char *p, + const char *end) { const char *x = tok->tokWord.start; const char *pfnd = p; + if (x == tok->tokWord.end - 1) { /* fast phase-out for single char word */ if (*p == *x) { return ++p; @@ -1443,8 +1463,10 @@ FindWordEnd( } static int -ClockScnToken_Month_Proc(ClockFmtScnCmdArgs *opts, - DateInfo *info, ClockScanToken *tok) +ClockScnToken_Month_Proc( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + ClockScanToken *tok) { #if 0 /* currently unused, test purposes only */ @@ -1464,9 +1486,7 @@ ClockScnToken_Month_Proc(ClockFmtScnCmdArgs *opts, return TCL_RETURN; } yyMonth = (val % 12) + 1; - return TCL_OK; -#endif - +#else static int monthsKeys[] = {MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, 0}; int ret, val; @@ -1488,13 +1508,15 @@ ClockScnToken_Month_Proc(ClockFmtScnCmdArgs *opts, } yyMonth = val; +#endif return TCL_OK; - } static int -ClockScnToken_DayOfWeek_Proc(ClockFmtScnCmdArgs *opts, - DateInfo *info, ClockScanToken *tok) +ClockScnToken_DayOfWeek_Proc( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + ClockScanToken *tok) { static int dowKeys[] = {MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_FULL, 0}; @@ -1506,10 +1528,8 @@ ClockScnToken_DayOfWeek_Proc(ClockFmtScnCmdArgs *opts, DetermineGreedySearchLen(info, tok, &minLen, &maxLen); /* %u %w %Ou %Ow */ - if ( curTok != 'a' && curTok != 'A' - && ((minLen <= 1 && maxLen >= 1) || PTR2INT(tok->map->data)) - ) { - + if (curTok != 'a' && curTok != 'A' + && ((minLen <= 1 && maxLen >= 1) || PTR2INT(tok->map->data))) { val = -1; if (PTR2INT(tok->map->data) == 0) { @@ -1529,22 +1549,22 @@ ClockScnToken_DayOfWeek_Proc(ClockFmtScnCmdArgs *opts, --val; } - if (val != -1) { - if (val == 0) { - val = 7; - } - if (val > 7) { - Tcl_SetObjResult(opts->interp, Tcl_NewStringObj("day of week is greater than 7", -1)); - Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL); - return TCL_ERROR; - } - info->date.dayOfWeek = val; - yyInput++; - return TCL_OK; + if (val == -1) { + return TCL_RETURN; } - - return TCL_RETURN; + if (val == 0) { + val = 7; + } + if (val > 7) { + Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( + "day of week is greater than 7", -1)); + Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL); + return TCL_ERROR; + } + info->date.dayOfWeek = val; + yyInput++; + return TCL_OK; } /* %a %A */ @@ -1564,12 +1584,13 @@ ClockScnToken_DayOfWeek_Proc(ClockFmtScnCmdArgs *opts, } info->date.dayOfWeek = val; return TCL_OK; - } static int -ClockScnToken_amPmInd_Proc(ClockFmtScnCmdArgs *opts, - DateInfo *info, ClockScanToken *tok) +ClockScnToken_amPmInd_Proc( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + ClockScanToken *tok) { int ret, val; int minLen, maxLen; @@ -1584,8 +1605,7 @@ ClockScnToken_amPmInd_Proc(ClockFmtScnCmdArgs *opts, return TCL_ERROR; } - ret = ObjListSearch(info, &val, amPmObj, 2, - minLen, maxLen); + ret = ObjListSearch(info, &val, amPmObj, 2, minLen, maxLen); if (ret != TCL_OK) { return ret; } @@ -1600,8 +1620,10 @@ ClockScnToken_amPmInd_Proc(ClockFmtScnCmdArgs *opts, } static int -ClockScnToken_LocaleERA_Proc(ClockFmtScnCmdArgs *opts, - DateInfo *info, ClockScanToken *tok) +ClockScnToken_LocaleERA_Proc( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + ClockScanToken *tok) { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; @@ -1622,8 +1644,7 @@ ClockScnToken_LocaleERA_Proc(ClockFmtScnCmdArgs *opts, return TCL_ERROR; } - ret = ObjListSearch(info, &val, eraObj, 6, - minLen, maxLen); + ret = ObjListSearch(info, &val, eraObj, 6, minLen, maxLen); if (ret != TCL_OK) { return ret; } @@ -1638,8 +1659,10 @@ ClockScnToken_LocaleERA_Proc(ClockFmtScnCmdArgs *opts, } static int -ClockScnToken_LocaleListMatcher_Proc(ClockFmtScnCmdArgs *opts, - DateInfo *info, ClockScanToken *tok) +ClockScnToken_LocaleListMatcher_Proc( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + ClockScanToken *tok) { int ret, val; int minLen, maxLen; @@ -1667,26 +1690,31 @@ ClockScnToken_LocaleListMatcher_Proc(ClockFmtScnCmdArgs *opts, } static int -ClockScnToken_JDN_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), - DateInfo *info, ClockScanToken *tok) +ClockScnToken_JDN_Proc( + TCL_UNUSED(ClockFmtScnCmdArgs *), + DateInfo *info, + ClockScanToken *tok) { int minLen, maxLen; - const char *p = yyInput, *end; const char *s; - Tcl_WideInt intJD; int fractJD = 0, fractJDDiv = 1; + const char *p = yyInput, *end, *s; + Tcl_WideInt intJD; + int fractJD = 0, fractJDDiv = 1; DetermineGreedySearchLen(info, tok, &minLen, &maxLen); end = yyInput + maxLen; /* currently positive astronomic dates only */ - if (*p == '+' || *p == '-') { p++; }; + if (*p == '+' || *p == '-') { + p++; + } s = p; while (p < end && isdigit(UCHAR(*p))) { p++; } - if ( _str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { + if (_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { return TCL_RETURN; - }; + } yyInput = p; if (p >= end || *p++ != '.') { /* allow pure integer JDN */ /* by astronomical JD the seconds of day offs is 12 hours */ @@ -1702,12 +1730,12 @@ ClockScnToken_JDN_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), fractJDDiv *= 10; p++; } - if ( _str2int(&fractJD, s, p, 1) != TCL_OK) { + if (_str2int(&fractJD, s, p, 1) != TCL_OK) { return TCL_RETURN; - }; + } yyInput = p; -done: + done: /* * Build a date from julian day (integer and fraction). * Note, astronomical JDN starts at noon in opposite to calendar julianday. @@ -1723,9 +1751,9 @@ done: yydate.julianDay = intJD; yydate.seconds = - -210866803200LL - + ( SECONDS_PER_DAY * intJD ) - + ( fractJD ); + -210866803200LL + + (SECONDS_PER_DAY * intJD) + + fractJD; info->flags |= CLF_POSIXSEC; @@ -1733,8 +1761,10 @@ done: } static int -ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts, - DateInfo *info, ClockScanToken *tok) +ClockScnToken_TimeZone_Proc( + ClockFmtScnCmdArgs *opts, + DateInfo *info, + ClockScanToken *tok) { int minLen, maxLen; int len = 0; @@ -1746,21 +1776,31 @@ ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts, /* numeric timezone */ if (*p == '+' || *p == '-') { /* max chars in numeric zone = "+00:00:00" */ - #define MAX_ZONE_LEN 9 +#define MAX_ZONE_LEN 9 char buf[MAX_ZONE_LEN + 1]; char *bp = buf; - *bp++ = *p++; len++; - if (maxLen > MAX_ZONE_LEN) + + *bp++ = *p++; + len++; + if (maxLen > MAX_ZONE_LEN) { maxLen = MAX_ZONE_LEN; + } /* cumulate zone into buf without ':' */ while (len + 1 < maxLen) { - if (!isdigit(UCHAR(*p))) break; - *bp++ = *p++; len++; - if (!isdigit(UCHAR(*p))) break; - *bp++ = *p++; len++; + if (!isdigit(UCHAR(*p))) { + break; + } + *bp++ = *p++; + len++; + if (!isdigit(UCHAR(*p))) { + break; + } + *bp++ = *p++; + len++; if (len + 2 < maxLen) { if (*p == ':') { - p++; len++; + p++; + len++; } } } @@ -1769,21 +1809,22 @@ ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts, if (len < minLen) { return TCL_RETURN; } - #undef MAX_ZONE_LEN +#undef MAX_ZONE_LEN /* timezone */ - tzObjStor = Tcl_NewStringObj(buf, bp-buf); + tzObjStor = Tcl_NewStringObj(buf, bp - buf); } else { /* legacy (alnum) timezone like CEST, etc. */ - if (maxLen > 4) + if (maxLen > 4) { maxLen = 4; + } while (len < maxLen) { - if ( (*p & 0x80) - || (!isalpha(UCHAR(*p)) && !isdigit(UCHAR(*p))) - ) { /* INTL: ISO only. */ + if ((*p & 0x80) + || (!isalpha(UCHAR(*p)) && !isdigit(UCHAR(*p)))) { /* INTL: ISO only. */ break; } - p++; len++; + p++; + len++; } if (len < minLen) { @@ -1791,7 +1832,7 @@ ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts, } /* timezone */ - tzObjStor = Tcl_NewStringObj(yyInput, p-yyInput); + tzObjStor = Tcl_NewStringObj(yyInput, p - yyInput); /* convert using dict */ } @@ -1800,7 +1841,7 @@ ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts, Tcl_IncrRefCount(tzObjStor); opts->timezoneObj = ClockSetupTimeZone(opts->clientData, opts->interp, - tzObjStor); + tzObjStor); Tcl_DecrRefCount(tzObjStor); if (opts->timezoneObj == NULL) { @@ -1808,16 +1849,17 @@ ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts, } yyInput += len; - return TCL_OK; } static int -ClockScnToken_StarDate_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), - DateInfo *info, ClockScanToken *tok) +ClockScnToken_StarDate_Proc( + TCL_UNUSED(ClockFmtScnCmdArgs *), + DateInfo *info, + ClockScanToken *tok) { int minLen, maxLen; - const char *p = yyInput, *end; const char *s; + const char *p = yyInput, *end, *s; int year, fractYear, fractDayDiv, fractDay; static const char *stardatePref = "stardate "; @@ -1838,7 +1880,9 @@ ClockScnToken_StarDate_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), return TCL_RETURN; } /* currently positive stardate only */ - if (*p == '+') { p++; }; + if (*p == '+') { + p++; + } s = p; while (p < end && isdigit(UCHAR(*p))) { p++; @@ -1846,10 +1890,10 @@ ClockScnToken_StarDate_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), if (p >= end || p - s < 4) { return TCL_RETURN; } - if ( _str2int(&year, s, p-3, 1) != TCL_OK - || _str2int(&fractYear, p-3, p, 1) != TCL_OK) { + if (_str2int(&year, s, p - 3, 1) != TCL_OK + || _str2int(&fractYear, p - 3, p, 1) != TCL_OK) { return TCL_RETURN; - }; + } if (*p++ != '.') { return TCL_RETURN; } @@ -1859,9 +1903,9 @@ ClockScnToken_StarDate_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), fractDayDiv *= 10; p++; } - if ( _str2int(&fractDay, s, p, 1) != TCL_OK) { + if (_str2int(&fractDay, s, p, 1) != TCL_OK) { return TCL_RETURN; - }; + } yyInput = p; /* Build a date from year and fraction. */ @@ -1883,16 +1927,15 @@ ClockScnToken_StarDate_Proc(TCL_UNUSED(ClockFmtScnCmdArgs *), GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE); yydate.localSeconds = - -210866803200LL - + ( SECONDS_PER_DAY * yydate.julianDay ) - + ( SECONDS_PER_DAY * fractDay / fractDayDiv ); + -210866803200LL + + (SECONDS_PER_DAY * yydate.julianDay) + + (SECONDS_PER_DAY * fractDay / fractDayDiv); return TCL_OK; } -static const char *ScnSTokenMapIndex = - "dmbyYHMSpJjCgGVazUsntQ"; -static ClockScanTokenMap ScnSTokenMap[] = { +static const char *ScnSTokenMapIndex = "dmbyYHMSpJjCgGVazUsntQ"; +static const ClockScanTokenMap ScnSTokenMap[] = { /* %d %e */ {CTOKT_INT, CLF_DAYOFMONTH, 0, 1, 2, offsetof(DateInfo, date.dayOfMonth), NULL, NULL}, @@ -1963,9 +2006,8 @@ static const char *ScnSTokenMapAliasIndex[2] = { "dmbbHHHpaaazU" }; -static const char *ScnETokenMapIndex = - "EJjys"; -static ClockScanTokenMap ScnETokenMap[] = { +static const char *ScnETokenMapIndex = "EJjys"; +static const ClockScanTokenMap ScnETokenMap[] = { /* %EE */ {CTOKT_PARSER, 0, 0, 0, 0xffff, offsetof(DateInfo, date.year), ClockScnToken_LocaleERA_Proc, (void *)MCLIT_LOCALE_NUMERALS}, @@ -1987,9 +2029,8 @@ static const char *ScnETokenMapAliasIndex[2] = { "" }; -static const char *ScnOTokenMapIndex = - "dmyHMSu"; -static ClockScanTokenMap ScnOTokenMap[] = { +static const char *ScnOTokenMapIndex = "dmyHMSu"; +static const ClockScanTokenMap ScnOTokenMap[] = { /* %Od %Oe */ {CTOKT_PARSER, CLF_DAYOFMONTH, 0, 0, 0xffff, offsetof(DateInfo, date.dayOfMonth), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, @@ -2018,24 +2059,21 @@ static const char *ScnOTokenMapAliasIndex[2] = { }; /* Token map reserved for CTOKT_SPACE */ -static ClockScanTokenMap ScnSpaceTokenMap = { - CTOKT_SPACE, 0, 0, 1, 1, 0, - NULL, NULL +static const ClockScanTokenMap ScnSpaceTokenMap = { + CTOKT_SPACE, 0, 0, 1, 1, 0, NULL, NULL }; -static ClockScanTokenMap ScnWordTokenMap = { - CTOKT_WORD, 0, 0, 1, 1, 0, - NULL, NULL +static const ClockScanTokenMap ScnWordTokenMap = { + CTOKT_WORD, 0, 0, 1, 1, 0, NULL, NULL }; - -static inline unsigned int +static inline unsigned EstimateTokenCount( const char *fmt, const char *end) { const char *p = fmt; - unsigned int tokcnt; + unsigned tokcnt; /* estimate token count by % char and format length */ tokcnt = 0; while (p <= end) { @@ -2046,7 +2084,7 @@ EstimateTokenCount( } p = fmt + tokcnt * 2; if (p < end) { - if ((unsigned int)(end - p) < tokcnt) { + if ((unsigned)(end - p) < tokcnt) { tokcnt += (end - p); } else { tokcnt += tokcnt; @@ -2056,13 +2094,15 @@ EstimateTokenCount( } #define AllocTokenInChain(tok, chain, tokCnt, type) \ - if (++(tok) >= (chain) + (tokCnt)) { \ - chain = (type)ckrealloc((char *)(chain), \ + if (++(tok) >= (chain) + (tokCnt)) { \ + chain = (type) attemptckrealloc((char *)(chain), \ (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \ - if ((chain) == NULL) { goto done; }; \ - (tok) = (chain) + (tokCnt); \ - (tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \ - } \ + if ((chain) == NULL) { \ + goto done; \ + } \ + (tok) = (chain) + (tokCnt); \ + (tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \ + } \ memset(tok, 0, sizeof(*(tok))); /* @@ -2071,7 +2111,7 @@ EstimateTokenCount( ClockFmtScnStorage * ClockGetOrParseScanFormat( Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_Obj *formatObj) /* Format container */ + Tcl_Obj *formatObj) /* Format container */ { ClockFmtScnStorage *fss; @@ -2090,7 +2130,7 @@ ClockGetOrParseScanFormat( /* first time scanning - tokenize format */ if (fss->scnTok == NULL) { ClockScanToken *tok, *scnTok; - unsigned int tokCnt; + unsigned tokCnt; const char *p, *e, *cp; e = p = HashEntry4FmtScn(fss)->key.string; @@ -2101,17 +2141,17 @@ ClockGetOrParseScanFormat( fss->scnSpaceCount = 0; - scnTok = tok = (ClockScanToken *)ckalloc(sizeof(*tok) * fss->scnTokC); + scnTok = tok = (ClockScanToken *) ckalloc(sizeof(*tok) * fss->scnTokC); memset(tok, 0, sizeof(*(tok))); tokCnt = 1; while (p < e) { switch (*p) { - case '%': - if (1) { - ClockScanTokenMap * scnMap = ScnSTokenMap; - const char *mapIndex = ScnSTokenMapIndex, - **aliasIndex = ScnSTokenMapAliasIndex; - if (p+1 >= e) { + case '%': { + const ClockScanTokenMap *scnMap = ScnSTokenMap; + const char *mapIndex = ScnSTokenMapIndex; + const char **aliasIndex = ScnSTokenMapAliasIndex; + + if (p + 1 >= e) { goto word_tok; } p++; @@ -2122,23 +2162,23 @@ ClockGetOrParseScanFormat( * because current mapping should be "...%%..." -> "...%..." */ tok->map = &ScnWordTokenMap; tok->tokWord.start = p; - tok->tokWord.end = p+1; - AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; + tok->tokWord.end = p + 1; + AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); + tokCnt++; p++; continue; - break; case 'E': scnMap = ScnETokenMap, mapIndex = ScnETokenMapIndex, aliasIndex = ScnETokenMapAliasIndex; p++; - break; + break; case 'O': scnMap = ScnOTokenMap, mapIndex = ScnOTokenMapIndex, aliasIndex = ScnOTokenMapAliasIndex; p++; - break; + break; } /* search direct index */ cp = strchr(mapIndex, *p); @@ -2146,15 +2186,21 @@ ClockGetOrParseScanFormat( /* search wrapper index (multiple chars for same token) */ cp = strchr(aliasIndex[0], *p); if (!cp || *cp == '\0') { - p--; if (scnMap != ScnSTokenMap) p--; + p--; + if (scnMap != ScnSTokenMap) { + p--; + } goto word_tok; } cp = strchr(mapIndex, aliasIndex[1][cp - aliasIndex[0]]); if (!cp || *cp == '\0') { /* unexpected, but ... */ - #ifdef DEBUG +#ifdef DEBUG Tcl_Panic("token \"%c\" has no map in wrapper resolver", *p); - #endif - p--; if (scnMap != ScnSTokenMap) p--; +#endif + p--; + if (scnMap != ScnSTokenMap) { + p--; + } goto word_tok; } } @@ -2163,7 +2209,7 @@ ClockGetOrParseScanFormat( /* calculate look ahead value by standing together tokens */ if (tok > scnTok) { - ClockScanToken *prevTok = tok - 1; + ClockScanToken *prevTok = tok - 1; while (prevTok >= scnTok) { if (prevTok->map->type != tok->map->type) { @@ -2177,58 +2223,59 @@ ClockGetOrParseScanFormat( } /* increase space count used in format */ - if ( tok->map->type == CTOKT_CHAR - && isspace(UCHAR(*((char *)tok->map->data))) - ) { + if (tok->map->type == CTOKT_CHAR + && isspace(UCHAR(*((char *)tok->map->data)))) { fss->scnSpaceCount++; } /* next token */ - AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; + AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); + tokCnt++; p++; continue; } - break; default: - if ( *p == ' ' || isspace(UCHAR(*p)) ) { - tok->map = &ScnSpaceTokenMap; - tok->tokWord.start = p++; - while (p < e && isspace(UCHAR(*p))) { - p++; + if (*p == ' ' || isspace(UCHAR(*p))) { + tok->map = &ScnSpaceTokenMap; + tok->tokWord.start = p++; + while (p < e && isspace(UCHAR(*p))) { + p++; + } + tok->tokWord.end = p; + /* increase space count used in format */ + fss->scnSpaceCount++; + /* next token */ + AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); + tokCnt++; + continue; } - tok->tokWord.end = p; - /* increase space count used in format */ - fss->scnSpaceCount++; - /* next token */ - AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; - continue; - } word_tok: - if (1) { - ClockScanToken *wordTok = tok; + { + ClockScanToken *wordTok = tok; if (tok > scnTok && (tok-1)->map == &ScnWordTokenMap) { - wordTok = tok-1; + wordTok = tok - 1; } /* new word token */ if (wordTok == tok) { wordTok->tokWord.start = p; wordTok->map = &ScnWordTokenMap; - AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; + AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); + tokCnt++; } if (isspace(UCHAR(*p))) { fss->scnSpaceCount++; } p = Tcl_UtfNext(p); wordTok->tokWord.end = p; + break; } - break; } } /* calculate end distance value for each tokens */ if (tok > scnTok) { - unsigned int endDist = 0; - ClockScanToken *prevTok = tok-1; + unsigned endDist = 0; + ClockScanToken *prevTok = tok-1; while (prevTok >= scnTok) { prevTok->endDistance = endDist; @@ -2244,7 +2291,8 @@ word_tok: /* correct count of real used tokens and free mem if desired * (1 is acceptable delta to prevent memory fragmentation) */ if (fss->scnTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) { - if ( (tok = (ClockScanToken *)ckrealloc(scnTok, tokCnt * sizeof(*tok))) != NULL ) { + if ((tok = (ClockScanToken *) + attemptckrealloc(scnTok, tokCnt * sizeof(*tok))) != NULL) { scnTok = tok; } } @@ -2253,7 +2301,7 @@ word_tok: fss->scnTok = scnTok; fss->scnTokC = tokCnt; } -done: + done: Tcl_MutexUnlock(&ClockFmtMutex); return fss; @@ -2264,16 +2312,16 @@ done: */ int ClockScan( - DateInfo *info, /* Date fields used for parsing & converting */ + DateInfo *info, /* Date fields used for parsing & converting */ Tcl_Obj *strObj, /* String containing the time to scan */ ClockFmtScnCmdArgs *opts) /* Command options */ { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - ClockFmtScnStorage *fss; - ClockScanToken *tok; - ClockScanTokenMap *map; + ClockFmtScnStorage *fss; + ClockScanToken *tok; + const ClockScanTokenMap *map; const char *p, *x, *end; - unsigned short int flags = 0; + unsigned short flags = 0; int ret = TCL_ERROR; /* get localized format */ @@ -2281,9 +2329,8 @@ ClockScan( return TCL_ERROR; } - if ( !(fss = ClockGetOrParseScanFormat(opts->interp, opts->formatObj)) - || !(tok = fss->scnTok) - ) { + if (!(fss = ClockGetOrParseScanFormat(opts->interp, opts->formatObj)) + || !(tok = fss->scnTok)) { return TCL_ERROR; } @@ -2304,7 +2351,7 @@ ClockScan( x = end; while (p < end) { if (isspace(UCHAR(*p))) { - x = ++p; /* after first space in space block */ + x = ++p; /* after first space in space block */ yySpaceCount++; while (p < end && isspace(UCHAR(*p))) { p++; @@ -2330,11 +2377,10 @@ ClockScan( for (; tok->map != NULL; tok++) { map = tok->map; /* bypass spaces at begin of input before parsing each token */ - if ( !(opts->flags & CLF_STRICT) - && ( map->type != CTOKT_SPACE - && map->type != CTOKT_WORD - && map->type != CTOKT_CHAR ) - ) { + if (!(opts->flags & CLF_STRICT) + && (map->type != CTOKT_SPACE + && map->type != CTOKT_WORD + && map->type != CTOKT_CHAR)) { while (p < end && isspace(UCHAR(*p))) { yySpaceCount--; p++; @@ -2345,17 +2391,19 @@ ClockScan( if (p >= end) { break; } - switch (map->type) - { + switch (map->type) { case CTOKT_INT: - case CTOKT_WIDE: - if (1) { + case CTOKT_WIDE: { int minLen, size; int sign = 1; + if (map->flags & CLF_SIGNED) { - if (*p == '+') { yyInput = ++p; } - else - if (*p == '-') { yyInput = ++p; sign = -1; }; + if (*p == '+') { + yyInput = ++p; + } else if (*p == '-') { + yyInput = ++p; + sign = -1; + } } DetermineGreedySearchLen(info, tok, &minLen, &size); @@ -2369,7 +2417,8 @@ ClockScan( } /* string 2 number, put number into info structure by offset */ if (map->offs) { - p = yyInput; x = p + size; + p = yyInput; + x = p + size; if (map->type == CTOKT_INT) { if (size <= 10) { _str2int_no((int *)(((char *)info) + map->offs), @@ -2395,23 +2444,21 @@ ClockScan( } flags = (flags & ~map->clearFlags) | map->flags; } + break; } - break; case CTOKT_PARSER: switch (map->parser(opts, info, tok)) { - case TCL_OK: + case TCL_OK: break; - case TCL_RETURN: - if ((map->flags & CLF_OPTIONAL)) { - yyInput = p; - continue; - } - goto not_match; - break; - default: - goto done; - break; - }; + case TCL_RETURN: + if ((map->flags & CLF_OPTIONAL)) { + yyInput = p; + continue; + } + goto not_match; + default: + goto done; + } /* decrement count for possible spaces in match */ while (p < yyInput) { if (isspace(UCHAR(*p))) { @@ -2421,7 +2468,7 @@ ClockScan( } p = yyInput; flags = (flags & ~map->clearFlags) | map->flags; - break; + break; case CTOKT_SPACE: /* at least one space */ if (!isspace(UCHAR(*p))) { @@ -2435,7 +2482,7 @@ ClockScan( yySpaceCount--; p++; } - break; + break; case CTOKT_WORD: x = FindWordEnd(tok, p, end); if (!x) { @@ -2443,7 +2490,7 @@ ClockScan( goto not_match; } p = x; - break; + break; case CTOKT_CHAR: x = (char *)map->data; if (*x != *p) { @@ -2454,13 +2501,13 @@ ClockScan( yySpaceCount--; } p++; - break; + break; } } /* check end was reached */ if (p < end) { /* in non-strict mode bypass spaces at end of input */ - if ( !(opts->flags & CLF_STRICT) && isspace(UCHAR(*p)) ) { + if (!(opts->flags & CLF_STRICT) && isspace(UCHAR(*p))) { p++; while (p < end && isspace(UCHAR(*p))) { p++; @@ -2500,27 +2547,27 @@ ClockScan( /* dd precedence below ddd */ switch (flags & (CLF_MONTH|CLF_DAYOFYEAR|CLF_DAYOFMONTH)) { - case (CLF_DAYOFYEAR|CLF_DAYOFMONTH): + case (CLF_DAYOFYEAR | CLF_DAYOFMONTH): /* miss month: ddd over dd (without month) */ flags &= ~CLF_DAYOFMONTH; /* fallthrough */ - case (CLF_DAYOFYEAR): + case CLF_DAYOFYEAR: /* ddd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { flags &= ~CLF_ISO8601WEAK; } break; - case (CLF_MONTH|CLF_DAYOFYEAR|CLF_DAYOFMONTH): + case CLF_MONTH | CLF_DAYOFYEAR | CLF_DAYOFMONTH: /* both available: mmdd over ddd */ - case (CLF_MONTH|CLF_DAYOFMONTH): - case (CLF_DAYOFMONTH): + case CLF_MONTH | CLF_DAYOFMONTH: + case CLF_DAYOFMONTH: /* mmdd / dd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { flags &= ~CLF_ISO8601WEAK; } break; /* neither mmdd nor ddd available */ - case 0: + case 0: /* but we have day of the week, which can be used */ if (flags & CLF_DAYOFWEEK) { /* prefer week based calculation of julianday */ @@ -2529,24 +2576,21 @@ ClockScan( } /* YearWeekDay below YearMonthDay */ - if ( (flags & CLF_ISO8601WEAK) - && ( (flags & (CLF_YEAR|CLF_DAYOFYEAR)) == (CLF_YEAR|CLF_DAYOFYEAR) - || (flags & (CLF_YEAR|CLF_DAYOFMONTH|CLF_MONTH)) == (CLF_YEAR|CLF_DAYOFMONTH|CLF_MONTH) - ) - ) { + if ((flags & CLF_ISO8601WEAK) + && ((flags & (CLF_YEAR | CLF_DAYOFYEAR)) == (CLF_YEAR | CLF_DAYOFYEAR) + || (flags & (CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH)) == ( + CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH))) { /* yy precedence below yyyy */ if (!(flags & CLF_ISO8601CENTURY) && (flags & CLF_CENTURY)) { /* normally precedence of ISO is higher, but no century - so put it down */ flags &= ~CLF_ISO8601WEAK; - } - else - /* yymmdd or yyddd over naked weekday */ - if (!(flags & CLF_ISO8601YEAR)) { + } else if (!(flags & CLF_ISO8601YEAR)) { + /* yymmdd or yyddd over naked weekday */ flags &= ~CLF_ISO8601WEAK; } } - if ( (flags & CLF_YEAR) ) { + if (flags & CLF_YEAR) { if (yyYear < 100) { if (!(flags & CLF_CENTURY)) { if (yyYear >= dataPtr->yearOfCenturySwitch) { @@ -2558,13 +2602,11 @@ ClockScan( } } } - if ( (flags & (CLF_ISO8601WEAK|CLF_ISO8601YEAR)) ) { - if ((flags & (CLF_ISO8601YEAR|CLF_YEAR)) == CLF_YEAR) { + if (flags & (CLF_ISO8601WEAK | CLF_ISO8601YEAR)) { + if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_YEAR) { /* for calculations expected iso year */ info->date.iso8601Year = yyYear; - } - else - if (info->date.iso8601Year < 100) { + } else if (info->date.iso8601Year < 100) { if (!(flags & CLF_ISO8601CENTURY)) { if (info->date.iso8601Year >= dataPtr->yearOfCenturySwitch) { info->date.iso8601Year -= 100; @@ -2574,7 +2616,7 @@ ClockScan( info->date.iso8601Year += info->dateCentury * 100; } } - if ((flags & (CLF_ISO8601YEAR|CLF_YEAR)) == CLF_ISO8601YEAR) { + if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_ISO8601YEAR) { /* for calculations expected year (e. g. CLF_ISO8601WEAK not set) */ yyYear = info->date.iso8601Year; } @@ -2583,7 +2625,7 @@ ClockScan( } /* if no time - reset time */ - if (!(flags & (CLF_TIME|CLF_LOCALSEC|CLF_POSIXSEC))) { + if (!(flags & (CLF_TIME | CLF_LOCALSEC | CLF_POSIXSEC))) { info->flags |= CLF_ASSEMBLE_SECONDS; yydate.localSeconds = 0; } @@ -2591,9 +2633,8 @@ ClockScan( if (flags & CLF_TIME) { info->flags |= CLF_ASSEMBLE_SECONDS; yySecondOfDay = ToSeconds(yyHour, yyMinutes, - yySeconds, yyMeridian); - } else - if (!(flags & (CLF_LOCALSEC|CLF_POSIXSEC))) { + yySeconds, yyMeridian); + } else if (!(flags & (CLF_LOCALSEC | CLF_POSIXSEC))) { info->flags |= CLF_ASSEMBLE_SECONDS; yySecondOfDay = yydate.localSeconds % SECONDS_PER_DAY; } @@ -2603,34 +2644,32 @@ ClockScan( info->flags |= flags; ret = TCL_OK; - goto done; + done: + return ret; -overflow: + /* Error case reporting. */ - Tcl_SetObjResult(opts->interp, Tcl_NewStringObj("integer value too large to represent", - -1)); + overflow: + Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( + "integer value too large to represent", -1)); Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL); goto done; -not_match: - - #if 1 - Tcl_SetObjResult(opts->interp, Tcl_NewStringObj("input string does not match supplied format", - -1)); - #else - /* to debug where exactly scan breaks */ + not_match: +#if 1 + Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( + "input string does not match supplied format", -1)); +#else + /* to debug where exactly scan breaks */ Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf( - "input string \"%s\" does not match supplied format \"%s\"," - " locale \"%s\" - token \"%s\"", - info->dateStart, HashEntry4FmtScn(fss)->key.string, - TclGetString(opts->localeObj), - tok && tok->tokWord.start ? tok->tokWord.start : "NULL")); - #endif + "input string \"%s\" does not match supplied format \"%s\"," + " locale \"%s\" - token \"%s\"", + info->dateStart, HashEntry4FmtScn(fss)->key.string, + TclGetString(opts->localeObj), + tok && tok->tokWord.start ? tok->tokWord.start : "NULL")); +#endif Tcl_SetErrorCode(opts->interp, "CLOCK", "badInputString", (char *)NULL); - -done: - - return ret; + goto done; } #define FrmResultIsAllocated(dateFmt) \ @@ -2642,19 +2681,19 @@ FrmResultAllocate( int len) { int needed = dateFmt->output + len - dateFmt->resEnd; - if (needed >= 0) { /* >= 0 - regards NTS zero */ + if (needed >= 0) { /* >= 0 - regards NTS zero */ int newsize = dateFmt->resEnd - dateFmt->resMem - + needed + MIN_FMT_RESULT_BLOCK_ALLOC*2; + + needed + MIN_FMT_RESULT_BLOCK_ALLOC * 2; char *newRes; /* differentiate between stack and memory */ if (!FrmResultIsAllocated(dateFmt)) { - newRes = (char *)ckalloc(newsize); + newRes = (char *) attemptckalloc(newsize); if (newRes == NULL) { return TCL_ERROR; } memcpy(newRes, dateFmt->resMem, dateFmt->output - dateFmt->resMem); } else { - newRes = (char *)ckrealloc(dateFmt->resMem, newsize); + newRes = (char *) attemptckrealloc(dateFmt->resMem, newsize); if (newRes == NULL) { return TCL_ERROR; } @@ -2673,7 +2712,7 @@ ClockFmtToken_HourAMPM_Proc( TCL_UNUSED(ClockFormatToken *), int *val) { - *val = ( ( *val + SECONDS_PER_DAY - 3600 ) / 3600 ) % 12 + 1; + *val = ((*val + SECONDS_PER_DAY - 3600) / 3600) % 12 + 1; return TCL_OK; } @@ -2697,7 +2736,9 @@ ClockFmtToken_AMPM_Proc( return TCL_ERROR; } s = TclGetStringFromObj(mcObj, &len); - if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, len) != TCL_OK) { + return TCL_ERROR; + } memcpy(dateFmt->output, s, len + 1); if (*tok->tokWord.start == 'p') { len = Tcl_UtfToUpper(dateFmt->output); @@ -2726,19 +2767,22 @@ ClockFmtToken_StarDate_Proc( } /* Put together the StarDate as "Stardate %02d%03d.%1d" */ - if (FrmResultAllocate(dateFmt, 30) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 30) != TCL_OK) { + return TCL_ERROR; + } memcpy(dateFmt->output, "Stardate ", 9); dateFmt->output += 9; dateFmt->output = _itoaw(dateFmt->output, - dateFmt->date.year - RODDENBERRY, '0', 2); + dateFmt->date.year - RODDENBERRY, '0', 2); dateFmt->output = _itoaw(dateFmt->output, - fractYear, '0', 3); + fractYear, '0', 3); *dateFmt->output++ = '.'; /* be sure positive after decimal point (note: clock-value can be negative) */ - v = dateFmt->date.secondOfDay / ( SECONDS_PER_DAY / 10 ); - if (v < 0) v = 10 + v; + v = dateFmt->date.secondOfDay / (SECONDS_PER_DAY / 10); + if (v < 0) { + v = 10 + v; + } dateFmt->output = _itoaw(dateFmt->output, v, '0', 1); - return TCL_OK; } static int @@ -2756,7 +2800,7 @@ ClockFmtToken_WeekOfYear_Proc( } dow++; } - *val = ( dateFmt->date.dayOfYear - dow + 7 ) / 7; + *val = (dateFmt->date.dayOfYear - dow + 7) / 7; return TCL_OK; } static int @@ -2771,16 +2815,18 @@ ClockFmtToken_JDN_Proc( /* Convert to JDN parts (regarding start offset) and time fraction */ fractJD = dateFmt->date.secondOfDay - - (int)tok->map->offs; /* 0 for calendar or 43200 for astro JD */ + - (int)tok->map->offs; /* 0 for calendar or 43200 for astro JD */ if (fractJD < 0) { intJD--; fractJD += SECONDS_PER_DAY; } - if (fractJD && intJD < 0) { /* avoid jump over 0, by negative JD's */ + if (fractJD && intJD < 0) { /* avoid jump over 0, by negative JD's */ intJD++; if (intJD == 0) { /* -0.0 / -0.9 has zero integer part, so append "-" extra */ - if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { + return TCL_ERROR; + } *dateFmt->output++ = '-'; } /* and inverse seconds of day, -0(75) -> -0.25 as float */ @@ -2788,33 +2834,42 @@ ClockFmtToken_JDN_Proc( } /* 21 is max width of (negative) wide-int (rather smaller, but anyway a time fraction below) */ - if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { + return TCL_ERROR; + } dateFmt->output = _witoaw(dateFmt->output, intJD, '0', 1); /* simplest cases .0 and .5 */ if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) { /* point + 0 or 5 */ - if (FrmResultAllocate(dateFmt, 1+1) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 1 + 1) != TCL_OK) { + return TCL_ERROR; + } *dateFmt->output++ = '.'; *dateFmt->output++ = !fractJD ? '0' : '5'; *dateFmt->output = '\0'; return TCL_OK; } else { /* wrap the time fraction */ - #define JDN_MAX_PRECISION 8 - #define JDN_MAX_PRECBOUND 100000000 /* 10**JDN_MAX_PRECISION */ +#define JDN_MAX_PRECISION 8 +#define JDN_MAX_PRECBOUND 100000000 /* 10**JDN_MAX_PRECISION */ char *p; /* to float (part after floating point, + 0.5 to round it up) */ fractJD = (int)( - (double)fractJD * JDN_MAX_PRECBOUND / SECONDS_PER_DAY + 0.5 - ); + (double)fractJD * JDN_MAX_PRECBOUND / SECONDS_PER_DAY + 0.5); + /* point + integer (as time fraction after floating point) */ - if (FrmResultAllocate(dateFmt, 1+JDN_MAX_PRECISION) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 1 + JDN_MAX_PRECISION) != TCL_OK) { + return TCL_ERROR; + } *dateFmt->output++ = '.'; p = _itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); + /* remove trailing zero's */ dateFmt->output++; - while (p > dateFmt->output && *(p-1) == '0') {p--;} + while (p > dateFmt->output && *(p-1) == '0') { + p--; + } *p = '\0'; dateFmt->output = p; } @@ -2831,11 +2886,13 @@ ClockFmtToken_TimeZone_Proc( int z = dateFmt->date.tzOffset; char sign = '+'; - if ( z < 0 ) { + if (z < 0) { z = -z; sign = '-'; } - if (FrmResultAllocate(dateFmt, 7) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 7) != TCL_OK) { + return TCL_ERROR; + } *dateFmt->output++ = sign; dateFmt->output = _itoaw(dateFmt->output, z / 3600, '0', 2); z %= 3600; @@ -2846,16 +2903,20 @@ ClockFmtToken_TimeZone_Proc( } } else { Tcl_Obj * objPtr; - const char *s; Tcl_Size len; + const char *s; + Tcl_Size len; + /* convert seconds to local seconds to obtain tzName object */ if (ConvertUTCToLocal(opts->clientData, opts->interp, &dateFmt->date, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { return TCL_ERROR; - }; + } objPtr = dateFmt->date.tzName; s = TclGetStringFromObj(objPtr, &len); - if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, len) != TCL_OK) { + return TCL_ERROR; + } memcpy(dateFmt->output, s, len + 1); dateFmt->output += len; } @@ -2882,10 +2943,12 @@ ClockFmtToken_LocaleERA_Proc( return TCL_ERROR; } s = TclGetStringFromObj(mcObj, &len); - if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, len) != TCL_OK) { + return TCL_ERROR; + } + memcpy(dateFmt->output, s, len + 1); dateFmt->output += len; - return TCL_OK; } @@ -2909,7 +2972,7 @@ ClockFmtToken_LocaleERAYear_Proc( } if (rowc != 0) { dateFmt->localeEra = LookupLastTransition(opts->interp, - dateFmt->date.localSeconds, rowc, rowv, NULL); + dateFmt->date.localSeconds, rowc, rowv, NULL); } if (dateFmt->localeEra == NULL) { dateFmt->localeEra = (Tcl_Obj*)1; @@ -2918,28 +2981,31 @@ ClockFmtToken_LocaleERAYear_Proc( /* if no LOCALE_ERAS in catalog or era not found */ if (dateFmt->localeEra == (Tcl_Obj*)1) { - if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; }; - if (*tok->tokWord.start == 'C') { /* %EC */ + if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { + return TCL_ERROR; + } + if (*tok->tokWord.start == 'C') { /* %EC */ *val = dateFmt->date.year / 100; dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); - } else { /* %Ey */ + *val, '0', 2); + } else { /* %Ey */ *val = dateFmt->date.year % 100; dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + *val, '0', 2); } } else { Tcl_Obj *objPtr; const char *s; Tcl_Size len; - if (*tok->tokWord.start == 'C') { /* %EC */ + + if (*tok->tokWord.start == 'C') { /* %EC */ if (Tcl_ListObjIndex(opts->interp, dateFmt->localeEra, 1, - &objPtr) != TCL_OK ) { + &objPtr) != TCL_OK) { return TCL_ERROR; } - } else { /* %Ey */ + } else { /* %Ey */ if (Tcl_ListObjIndex(opts->interp, dateFmt->localeEra, 2, - &objPtr) != TCL_OK ) { + &objPtr) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIntFromObj(opts->interp, objPtr, val) != TCL_OK) { @@ -2958,24 +3024,27 @@ ClockFmtToken_LocaleERAYear_Proc( } } else { /* year as integer */ - if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { + return TCL_ERROR; + } dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + *val, '0', 2); return TCL_OK; } } s = TclGetStringFromObj(objPtr, &len); - if (FrmResultAllocate(dateFmt, len) != TCL_OK) { return TCL_ERROR; }; + if (FrmResultAllocate(dateFmt, len) != TCL_OK) { + return TCL_ERROR; + } memcpy(dateFmt->output, s, len + 1); dateFmt->output += len; } return TCL_OK; } - static const char *FmtSTokenMapIndex = "demNbByYCHMSIklpaAuwUVzgGjJsntQ"; -static ClockFormatTokenMap FmtSTokenMap[] = { +static const ClockFormatTokenMap FmtSTokenMap[] = { /* %d */ {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL, NULL}, /* %e */ @@ -3054,9 +3123,8 @@ static const char *FmtSTokenMapAliasIndex[2] = { "bpUz" }; -static const char *FmtETokenMapIndex = - "EJjys"; -static ClockFormatTokenMap FmtETokenMap[] = { +static const char *FmtETokenMapIndex = "EJjys"; +static const ClockFormatTokenMap FmtETokenMap[] = { /* %EE */ {CFMTT_PROC, NULL, 0, 0, 0, 0, 0, ClockFmtToken_LocaleERA_Proc, NULL}, @@ -3077,9 +3145,8 @@ static const char *FmtETokenMapAliasIndex[2] = { "y" }; -static const char *FmtOTokenMapIndex = - "dmyHIMSuw"; -static ClockFormatTokenMap FmtOTokenMap[] = { +static const char *FmtOTokenMapIndex = "dmyHIMSuw"; +static const ClockFormatTokenMap FmtOTokenMap[] = { /* %Od %Oe */ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfMonth), NULL, (void *)MCLIT_LOCALE_NUMERALS}, @@ -3113,7 +3180,7 @@ static const char *FmtOTokenMapAliasIndex[2] = { "dHI" }; -static ClockFormatTokenMap FmtWordTokenMap = { +static const ClockFormatTokenMap FmtWordTokenMap = { CTOKT_WORD, NULL, 0, 0, 0, 0, 0, NULL, NULL }; @@ -3123,7 +3190,7 @@ static ClockFormatTokenMap FmtWordTokenMap = { ClockFmtScnStorage * ClockGetOrParseFmtFormat( Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_Obj *formatObj) /* Format container */ + Tcl_Obj *formatObj) /* Format container */ { ClockFmtScnStorage *fss; @@ -3142,7 +3209,7 @@ ClockGetOrParseFmtFormat( /* first time formatting - tokenize format */ if (fss->fmtTok == NULL) { ClockFormatToken *tok, *fmtTok; - unsigned int tokCnt; + unsigned tokCnt; const char *p, *e, *cp; e = p = HashEntry4FmtScn(fss)->key.string; @@ -3151,17 +3218,17 @@ ClockGetOrParseFmtFormat( /* estimate token count by % char and format length */ fss->fmtTokC = EstimateTokenCount(p, e); - fmtTok = tok = (ClockFormatToken *)ckalloc(sizeof(*tok) * fss->fmtTokC); + fmtTok = tok = (ClockFormatToken *) ckalloc(sizeof(*tok) * fss->fmtTokC); memset(tok, 0, sizeof(*(tok))); tokCnt = 1; while (p < e) { switch (*p) { - case '%': - if (1) { - ClockFormatTokenMap * fmtMap = FmtSTokenMap; - const char *mapIndex = FmtSTokenMapIndex, - **aliasIndex = FmtSTokenMapAliasIndex; - if (p+1 >= e) { + case '%': { + const ClockFormatTokenMap *fmtMap = FmtSTokenMap; + const char *mapIndex = FmtSTokenMapIndex; + const char **aliasIndex = FmtSTokenMapAliasIndex; + + if (p + 1 >= e) { goto word_tok; } p++; @@ -3172,23 +3239,23 @@ ClockGetOrParseFmtFormat( * because current mapping should be "...%%..." -> "...%..." */ tok->map = &FmtWordTokenMap; tok->tokWord.start = p; - tok->tokWord.end = p+1; - AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++; + tok->tokWord.end = p + 1; + AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); + tokCnt++; p++; continue; - break; case 'E': fmtMap = FmtETokenMap, mapIndex = FmtETokenMapIndex, aliasIndex = FmtETokenMapAliasIndex; p++; - break; + break; case 'O': fmtMap = FmtOTokenMap, mapIndex = FmtOTokenMapIndex, aliasIndex = FmtOTokenMapAliasIndex; p++; - break; + break; } /* search direct index */ cp = strchr(mapIndex, *p); @@ -3196,49 +3263,57 @@ ClockGetOrParseFmtFormat( /* search wrapper index (multiple chars for same token) */ cp = strchr(aliasIndex[0], *p); if (!cp || *cp == '\0') { - p--; if (fmtMap != FmtSTokenMap) p--; + p--; + if (fmtMap != FmtSTokenMap) { + p--; + } goto word_tok; } cp = strchr(mapIndex, aliasIndex[1][cp - aliasIndex[0]]); - if (!cp || *cp == '\0') { /* unexpected, but ... */ - #ifdef DEBUG + if (!cp || *cp == '\0') { /* unexpected, but ... */ +#ifdef DEBUG Tcl_Panic("token \"%c\" has no map in wrapper resolver", *p); - #endif - p--; if (fmtMap != FmtSTokenMap) p--; +#endif + p--; + if (fmtMap != FmtSTokenMap) { + p--; + } goto word_tok; } } tok->map = &fmtMap[cp - mapIndex]; tok->tokWord.start = p; /* next token */ - AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++; + AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); + tokCnt++; p++; continue; } - break; default: -word_tok: - if (1) { + word_tok: { ClockFormatToken *wordTok = tok; + if (tok > fmtTok && (tok-1)->map == &FmtWordTokenMap) { wordTok = tok-1; } if (wordTok == tok) { wordTok->tokWord.start = p; wordTok->map = &FmtWordTokenMap; - AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++; + AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); + tokCnt++; } p = Tcl_UtfNext(p); wordTok->tokWord.end = p; + break; } - break; } } /* correct count of real used tokens and free mem if desired * (1 is acceptable delta to prevent memory fragmentation) */ if (fss->fmtTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) { - if ( (tok = (ClockFormatToken *)ckrealloc(fmtTok, tokCnt * sizeof(*tok))) != NULL ) { + if ((tok = (ClockFormatToken *) + attemptckrealloc(fmtTok, tokCnt * sizeof(*tok))) != NULL) { fmtTok = tok; } } @@ -3247,9 +3322,8 @@ word_tok: fss->fmtTok = fmtTok; fss->fmtTokC = tokCnt; } -done: + done: Tcl_MutexUnlock(&ClockFmtMutex); - return fss; } @@ -3258,12 +3332,12 @@ done: */ int ClockFormat( - DateFormat *dateFmt, /* Date fields used for parsing & converting */ - ClockFmtScnCmdArgs *opts) /* Command options */ + DateFormat *dateFmt, /* Date fields used for parsing & converting */ + ClockFmtScnCmdArgs *opts) /* Command options */ { - ClockFmtScnStorage *fss; - ClockFormatToken *tok; - ClockFormatTokenMap *map; + ClockFmtScnStorage *fss; + ClockFormatToken *tok; + const ClockFormatTokenMap *map; char resMem[MIN_FMT_RESULT_BLOCK_ALLOC]; /* get localized format */ @@ -3271,9 +3345,8 @@ ClockFormat( return TCL_ERROR; } - if ( !(fss = ClockGetOrParseFmtFormat(opts->interp, opts->formatObj)) - || !(tok = fss->fmtTok) - ) { + if (!(fss = ClockGetOrParseFmtFormat(opts->interp, opts->formatObj)) + || !(tok = fss->fmtTok)) { return TCL_ERROR; } @@ -3281,11 +3354,11 @@ ClockFormat( dateFmt->resMem = resMem; dateFmt->resEnd = dateFmt->resMem + sizeof(resMem); if (fss->fmtMinAlloc > sizeof(resMem)) { - dateFmt->resMem = (char *)ckalloc(fss->fmtMinAlloc); - dateFmt->resEnd = dateFmt->resMem + fss->fmtMinAlloc; + dateFmt->resMem = (char *) attemptckalloc(fss->fmtMinAlloc); if (dateFmt->resMem == NULL) { return TCL_ERROR; } + dateFmt->resEnd = dateFmt->resMem + fss->fmtMinAlloc; } dateFmt->output = dateFmt->resMem; *dateFmt->output = '\0'; @@ -3293,11 +3366,10 @@ ClockFormat( /* do format each token */ for (; tok->map != NULL; tok++) { map = tok->map; - switch (map->type) - { - case CTOKT_INT: - if (1) { + switch (map->type) { + case CTOKT_INT: { int val = (int)*(int *)(((char *)dateFmt) + map->offs); + if (map->fmtproc == NULL) { if (map->flags & CLFMT_DECR) { val--; @@ -3321,7 +3393,9 @@ ClockFormat( } } if (!(map->flags & CLFMT_LOCALE_INDX)) { - if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { goto error; }; + if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { + goto error; + } if (map->width) { dateFmt->output = _itoaw(dateFmt->output, val, *map->tostr, map->width); } else { @@ -3333,78 +3407,83 @@ ClockFormat( if (mcObj == NULL) { goto error; } - if ( Tcl_ListObjIndex(opts->interp, mcObj, val, &mcObj) != TCL_OK - || mcObj == NULL - ) { + if (Tcl_ListObjIndex(opts->interp, mcObj, val, &mcObj) != TCL_OK + || mcObj == NULL) { goto error; } s = TclGetString(mcObj); - if (FrmResultAllocate(dateFmt, mcObj->length) != TCL_OK) { goto error; }; + if (FrmResultAllocate(dateFmt, mcObj->length) != TCL_OK) { + goto error; + } memcpy(dateFmt->output, s, mcObj->length + 1); dateFmt->output += mcObj->length; } + break; } - break; - case CTOKT_WIDE: - if (1) { + case CTOKT_WIDE: { Tcl_WideInt val = *(Tcl_WideInt *)(((char *)dateFmt) + map->offs); - if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { goto error; }; + + if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { + goto error; + } if (map->width) { dateFmt->output = _witoaw(dateFmt->output, val, *map->tostr, map->width); } else { dateFmt->output += sprintf(dateFmt->output, map->tostr, val); } + break; } - break; case CTOKT_CHAR: - if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { goto error; }; + if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { + goto error; + } *dateFmt->output++ = *map->tostr; - break; + break; case CFMTT_PROC: if (map->fmtproc(opts, dateFmt, tok, NULL) != TCL_OK) { goto error; - }; - break; - case CTOKT_WORD: - if (1) { - Tcl_Size len = tok->tokWord.end - tok->tokWord.start; - if (FrmResultAllocate(dateFmt, len) != TCL_OK) { goto error; }; - if (len == 1) { - *dateFmt->output++ = *tok->tokWord.start; - } else { - memcpy(dateFmt->output, tok->tokWord.start, len); - dateFmt->output += len; - } } - break; + break; + case CTOKT_WORD: { + Tcl_Size len = tok->tokWord.end - tok->tokWord.start; + + if (FrmResultAllocate(dateFmt, len) != TCL_OK) { + goto error; + } + if (len == 1) { + *dateFmt->output++ = *tok->tokWord.start; + } else { + memcpy(dateFmt->output, tok->tokWord.start, len); + dateFmt->output += len; + } + break; + } } } - goto done; -error: - + error: if (dateFmt->resMem != resMem) { ckfree(dateFmt->resMem); } dateFmt->resMem = NULL; -done: - + done: if (dateFmt->resMem) { size_t size; Tcl_Obj *result; + TclNewObj(result); result->length = dateFmt->output - dateFmt->resMem; - size = result->length+1; + size = result->length + 1; if (dateFmt->resMem == resMem) { - result->bytes = (char *)ckalloc(size); + result->bytes = (char *) attemptckalloc(size); if (result->bytes == NULL) { return TCL_ERROR; } memcpy(result->bytes, dateFmt->resMem, size); } else if ((dateFmt->resEnd - dateFmt->resMem) / size > MAX_FMT_RESULT_THRESHOLD) { - result->bytes = (char *)ckrealloc(dateFmt->resMem, size); + result->bytes = (char *) attemptckrealloc(dateFmt->resMem, size); if (result->bytes == NULL) { result->bytes = dateFmt->resMem; } @@ -3412,9 +3491,8 @@ done: result->bytes = dateFmt->resMem; } /* save last used buffer length */ - if ( dateFmt->resMem != resMem - && fss->fmtMinAlloc < size + MIN_FMT_RESULT_BLOCK_DELTA - ) { + if (dateFmt->resMem != resMem + && fss->fmtMinAlloc < size + MIN_FMT_RESULT_BLOCK_DELTA) { fss->fmtMinAlloc = size + MIN_FMT_RESULT_BLOCK_DELTA; } result->bytes[result->length] = '\0'; diff --git a/generic/tclDate.h b/generic/tclDate.h index 60aca7b..8b71827 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -205,8 +205,8 @@ typedef struct DateInfo { TclDateFields date; - int flags; /* Signals parts of date/time get found */ - int errFlags; /* Signals error (part of date/time found twice) */ + int flags; /* Signals parts of date/time get found */ + int errFlags; /* Signals error (part of date/time found twice) */ MERIDIAN dateMeridian; @@ -229,8 +229,8 @@ typedef struct DateInfo { int dateCentury; - Tcl_Obj* messages; /* Error messages */ - const char* separatrix; /* String separating messages */ + Tcl_Obj *messages; /* Error messages */ + const char* separatrix; /* String separating messages */ } DateInfo; #define yydate (info->date) /* Date fields used for converting */ @@ -260,7 +260,9 @@ typedef struct DateInfo { #define yySpaceCount (info->dateSpaceCount) static inline void -ClockInitDateInfo(DateInfo *info) { +ClockInitDateInfo( + DateInfo *info) +{ memset(info, 0, sizeof(DateInfo)); } @@ -276,28 +278,26 @@ ClockInitDateInfo(DateInfo *info) { #define CLF_LOCALE_USED (1 << 15) typedef struct ClockFmtScnCmdArgs { - void *clientData; /* Opaque pointer to literal pool, etc. */ - Tcl_Interp *interp; /* Tcl interpreter */ - - Tcl_Obj *formatObj; /* Format */ - Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */ - Tcl_Obj *timezoneObj; /* Default time zone in which the time will be expressed */ - Tcl_Obj *baseObj; /* Base (scan and add) or clockValue (format) */ - int flags; /* Flags control scanning */ - - Tcl_Obj *mcDictObj; /* Current dictionary of tcl::clock package for given localeObj*/ + void *clientData; /* Opaque pointer to literal pool, etc. */ + Tcl_Interp *interp; /* Tcl interpreter */ + Tcl_Obj *formatObj; /* Format */ + Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */ + Tcl_Obj *timezoneObj; /* Default time zone in which the time will be expressed */ + Tcl_Obj *baseObj; /* Base (scan and add) or clockValue (format) */ + int flags; /* Flags control scanning */ + Tcl_Obj *mcDictObj; /* Current dictionary of tcl::clock package for given localeObj*/ } ClockFmtScnCmdArgs; /* Last-period cache for fast UTC to local and backwards conversion */ typedef struct ClockLastTZOffs { /* keys */ - Tcl_Obj *timezoneObj; - int changeover; + Tcl_Obj *timezoneObj; + int changeover; Tcl_WideInt localSeconds; Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */ /* values */ - int tzOffset; - Tcl_Obj *tzName; /* Name (abbreviation) of this area in TZ */ + int tzOffset; + Tcl_Obj *tzName; /* Name (abbreviation) of this area in TZ */ } ClockLastTZOffs; /* @@ -305,12 +305,11 @@ typedef struct ClockLastTZOffs { */ typedef struct ClockClientData { - size_t refCount; /* Number of live references. */ + size_t refCount; /* Number of live references. */ Tcl_Obj **literals; /* Pool of object literals (common, locale independent). */ Tcl_Obj **mcLiterals; /* Msgcat object literals with mc-keys for search with locale. */ Tcl_Obj **mcLitIdxs; /* Msgcat object indices prefixed with _IDX_, * used for quick dictionary search */ - Tcl_Obj *mcDicts; /* Msgcat collection, contains weak pointers to locale * catalogs, and owns it references (onetime referenced) */ @@ -376,42 +375,39 @@ typedef struct ClockClientData { typedef struct ClockScanToken ClockScanToken; - typedef int ClockScanTokenProc( ClockFmtScnCmdArgs *opts, DateInfo *info, ClockScanToken *tok); - typedef enum _CLCKTOK_TYPE { CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR, CFMTT_PROC } CLCKTOK_TYPE; typedef struct ClockScanTokenMap { - unsigned short int type; - unsigned short int flags; - unsigned short int clearFlags; - unsigned short int minSize; - unsigned short int maxSize; - unsigned short int offs; + unsigned short type; + unsigned short flags; + unsigned short clearFlags; + unsigned short minSize; + unsigned short maxSize; + unsigned short offs; ClockScanTokenProc *parser; - const void *data; + const void *data; } ClockScanTokenMap; struct ClockScanToken { - ClockScanTokenMap *map; + const ClockScanTokenMap *map; struct { const char *start; const char *end; } tokWord; - unsigned short int endDistance; - unsigned short int lookAhMin; - unsigned short int lookAhMax; - unsigned short int lookAhTok; + unsigned short endDistance; + unsigned short lookAhMin; + unsigned short lookAhMax; + unsigned short lookAhTok; }; - #define MIN_FMT_RESULT_BLOCK_ALLOC 80 #define MIN_FMT_RESULT_BLOCK_DELTA 0 /* Maximal permitted threshold (buffer size > result size) in percent, @@ -422,9 +418,7 @@ typedef struct DateFormat { char *resMem; char *resEnd; char *output; - TclDateFields date; - Tcl_Obj *localeEra; } DateFormat; @@ -442,42 +436,41 @@ typedef int ClockFormatTokenProc( int *val); typedef struct ClockFormatTokenMap { - unsigned short int type; - const char *tostr; - unsigned short int width; - unsigned short int flags; - unsigned short int divider; - unsigned short int divmod; - unsigned short int offs; + unsigned short type; + const char *tostr; + unsigned short width; + unsigned short flags; + unsigned short divider; + unsigned short divmod; + unsigned short offs; ClockFormatTokenProc *fmtproc; - void *data; + void *data; } ClockFormatTokenMap; struct ClockFormatToken { - ClockFormatTokenMap *map; + const ClockFormatTokenMap *map; struct { const char *start; const char *end; } tokWord; }; - typedef struct ClockFmtScnStorage ClockFmtScnStorage; struct ClockFmtScnStorage { - int objRefCount; /* Reference count shared across threads */ - ClockScanToken *scnTok; - unsigned int scnTokC; - unsigned int scnSpaceCount; /* Count of mandatory spaces used in format */ - ClockFormatToken *fmtTok; - unsigned int fmtTokC; + int objRefCount; /* Reference count shared across threads */ + ClockScanToken *scnTok; + unsigned scnTokC; + unsigned scnSpaceCount; /* Count of mandatory spaces used in format */ + ClockFormatToken *fmtTok; + unsigned fmtTokC; #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 - ClockFmtScnStorage *nextPtr; - ClockFmtScnStorage *prevPtr; + ClockFmtScnStorage *nextPtr; + ClockFmtScnStorage *prevPtr; #endif - size_t fmtMinAlloc; + size_t fmtMinAlloc; #if 0 - +Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry, + Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry, * stored by offset +sizeof(self) */ #endif }; @@ -490,86 +483,66 @@ struct ClockFmtScnStorage { * Extracts Julian day and seconds of the day from posix seconds (tm). */ #define ClockExtractJDAndSODFromSeconds(jd, sod, tm) \ - do { \ - jd = (tm + JULIAN_SEC_POSIX_EPOCH); \ - if (jd >= SECONDS_PER_DAY || jd <= -SECONDS_PER_DAY) { \ - jd /= SECONDS_PER_DAY; \ - sod = (int)(tm % SECONDS_PER_DAY); \ - } else { \ - sod = (int)jd, jd = 0; \ - } \ - if (sod < 0) { \ - sod += SECONDS_PER_DAY; \ + do { \ + jd = (tm + JULIAN_SEC_POSIX_EPOCH); \ + if (jd >= SECONDS_PER_DAY || jd <= -SECONDS_PER_DAY) { \ + jd /= SECONDS_PER_DAY; \ + sod = (int)(tm % SECONDS_PER_DAY); \ + } else { \ + sod = (int)jd, jd = 0; \ + } \ + if (sod < 0) { \ + sod += SECONDS_PER_DAY; \ /* JD is affected, if switched into negative (avoid 24 hours difference) */ \ - if (jd <= 0) { \ - jd--; \ - } \ - } \ + if (jd <= 0) { \ + jd--; \ + } \ + } \ } while(0) /* * Prototypes of module functions. */ -MODULE_SCOPE int ToSeconds(int Hours, int Minutes, +MODULE_SCOPE int ToSeconds(int Hours, int Minutes, int Seconds, MERIDIAN Meridian); -MODULE_SCOPE int IsGregorianLeapYear(TclDateFields *); -MODULE_SCOPE void - GetJulianDayFromEraYearWeekDay( +MODULE_SCOPE int IsGregorianLeapYear(TclDateFields *); +MODULE_SCOPE void GetJulianDayFromEraYearWeekDay( TclDateFields *fields, int changeover); -MODULE_SCOPE void - GetJulianDayFromEraYearMonthDay( +MODULE_SCOPE void GetJulianDayFromEraYearMonthDay( TclDateFields *fields, int changeover); -MODULE_SCOPE void - GetJulianDayFromEraYearDay( +MODULE_SCOPE void GetJulianDayFromEraYearDay( TclDateFields *fields, int changeover); -MODULE_SCOPE int ConvertUTCToLocal(void *clientData, Tcl_Interp *, +MODULE_SCOPE int ConvertUTCToLocal(void *clientData, Tcl_Interp *, TclDateFields *, Tcl_Obj *timezoneObj, int); -MODULE_SCOPE Tcl_Obj * - LookupLastTransition(Tcl_Interp *, Tcl_WideInt, +MODULE_SCOPE Tcl_Obj * LookupLastTransition(Tcl_Interp *, Tcl_WideInt, Tcl_Size, Tcl_Obj *const *, Tcl_WideInt *rangesVal); - -MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info); +MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info); /* tclClock.c module declarations */ -MODULE_SCOPE Tcl_Obj * - ClockSetupTimeZone(void *clientData, - Tcl_Interp *interp, Tcl_Obj *timezoneObj); - -MODULE_SCOPE Tcl_Obj * - ClockMCDict(ClockFmtScnCmdArgs *opts); -MODULE_SCOPE Tcl_Obj * - ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey); -MODULE_SCOPE Tcl_Obj * - ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey); -MODULE_SCOPE int ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey, - Tcl_Obj *valObj); +MODULE_SCOPE Tcl_Obj * ClockSetupTimeZone(void *clientData, + Tcl_Interp *interp, Tcl_Obj *timezoneObj); +MODULE_SCOPE Tcl_Obj * ClockMCDict(ClockFmtScnCmdArgs *opts); +MODULE_SCOPE Tcl_Obj * ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey); +MODULE_SCOPE Tcl_Obj * ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey); +MODULE_SCOPE int ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey, + Tcl_Obj *valObj); /* tclClockFmt.c module declarations */ - -MODULE_SCOPE char * - TclItoAw(char *buf, int val, char padchar, unsigned short int width); -MODULE_SCOPE int - TclAtoWIe(Tcl_WideInt *out, const char *p, const char *e, int sign); - -MODULE_SCOPE Tcl_Obj* - ClockFrmObjGetLocFmtKey(Tcl_Interp *interp, - Tcl_Obj *objPtr); - -MODULE_SCOPE ClockFmtScnStorage * - Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp, - Tcl_Obj *objPtr); -MODULE_SCOPE Tcl_Obj * - ClockLocalizeFormat(ClockFmtScnCmdArgs *opts); - -MODULE_SCOPE int ClockScan(DateInfo *info, - Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts); - -MODULE_SCOPE int ClockFormat(DateFormat *dateFmt, - ClockFmtScnCmdArgs *opts); - -MODULE_SCOPE void ClockFrmScnClearCaches(void); +MODULE_SCOPE char * TclItoAw(char *buf, int val, char padchar, unsigned short width); +MODULE_SCOPE int TclAtoWIe(Tcl_WideInt *out, const char *p, const char *e, int sign); + +MODULE_SCOPE Tcl_Obj* ClockFrmObjGetLocFmtKey(Tcl_Interp *interp, + Tcl_Obj *objPtr); +MODULE_SCOPE ClockFmtScnStorage *Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr); +MODULE_SCOPE Tcl_Obj * ClockLocalizeFormat(ClockFmtScnCmdArgs *opts); +MODULE_SCOPE int ClockScan(DateInfo *info, Tcl_Obj *strObj, + ClockFmtScnCmdArgs *opts); +MODULE_SCOPE int ClockFormat(DateFormat *dateFmt, + ClockFmtScnCmdArgs *opts); +MODULE_SCOPE void ClockFrmScnClearCaches(void); #endif /* _TCLCLOCK_H */ -- cgit v0.12 From 99d959852d8f600c2aa00f02305896287c067adf Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 11 Apr 2024 16:14:29 +0000 Subject: Clean up the code style of the rest of clock --- generic/tclClock.c | 927 +++++++++++++++++++++++++---------------------------- 1 file changed, 440 insertions(+), 487 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index ce66ef5..acb5349 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -89,38 +89,32 @@ static void GetYearWeekDay(TclDateFields *, int); static void GetGregorianEraYearDay(TclDateFields *, int); static void GetMonthDay(TclDateFields *); static Tcl_WideInt WeekdayOnOrBefore(int, Tcl_WideInt); -static Tcl_ObjCmdProc ClockClicksObjCmd; -static Tcl_ObjCmdProc ClockConvertlocaltoutcObjCmd; - +static Tcl_ObjCmdProc ClockClicksObjCmd; +static Tcl_ObjCmdProc ClockConvertlocaltoutcObjCmd; static int ClockGetDateFields(void *clientData, Tcl_Interp *interp, TclDateFields *fields, Tcl_Obj *timezoneObj, int changeover); -static Tcl_ObjCmdProc ClockGetdatefieldsObjCmd; -static Tcl_ObjCmdProc ClockGetjuliandayfromerayearmonthdayObjCmd; -static Tcl_ObjCmdProc ClockGetjuliandayfromerayearweekdayObjCmd; -static Tcl_ObjCmdProc ClockGetenvObjCmd; -static Tcl_ObjCmdProc ClockMicrosecondsObjCmd; -static Tcl_ObjCmdProc ClockMillisecondsObjCmd; -static Tcl_ObjCmdProc ClockSecondsObjCmd; -static Tcl_ObjCmdProc ClockFormatObjCmd; -static Tcl_ObjCmdProc ClockScanObjCmd; -static int ClockScanCommit( - DateInfo *info, +static Tcl_ObjCmdProc ClockGetdatefieldsObjCmd; +static Tcl_ObjCmdProc ClockGetjuliandayfromerayearmonthdayObjCmd; +static Tcl_ObjCmdProc ClockGetjuliandayfromerayearweekdayObjCmd; +static Tcl_ObjCmdProc ClockGetenvObjCmd; +static Tcl_ObjCmdProc ClockMicrosecondsObjCmd; +static Tcl_ObjCmdProc ClockMillisecondsObjCmd; +static Tcl_ObjCmdProc ClockSecondsObjCmd; +static Tcl_ObjCmdProc ClockFormatObjCmd; +static Tcl_ObjCmdProc ClockScanObjCmd; +static int ClockScanCommit(DateInfo *info, ClockFmtScnCmdArgs *opts); -static int ClockFreeScan( - DateInfo *info, +static int ClockFreeScan(DateInfo *info, Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts); -static int ClockCalcRelTime( - DateInfo *info); -static Tcl_ObjCmdProc ClockAddObjCmd; -static int ClockValidDate( - DateInfo *, +static int ClockCalcRelTime(DateInfo *info); +static Tcl_ObjCmdProc ClockAddObjCmd; +static int ClockValidDate(DateInfo *, ClockFmtScnCmdArgs *, int stage); static struct tm * ThreadSafeLocalTime(const time_t *); static size_t TzsetIfNecessary(void); static void ClockDeleteCmdProc(void *); - -static Tcl_ObjCmdProc ClockSafeCatchCmd; +static Tcl_ObjCmdProc ClockSafeCatchCmd; /* * Structure containing description of "native" clock commands to create. */ @@ -133,7 +127,7 @@ struct ClockCommand { * will always have the ClockClientData sent * to it, but may well ignore this data. */ CompileProc *compileProc; /* The compiler for the command. */ - void *clientData; /* Any clientData to give the command (if NULL + void *clientData; /* Any clientData to give the command (if NULL * a reference to ClockClientData will be sent) */ }; @@ -182,7 +176,7 @@ TclClockInit( char cmdName[50]; /* Buffer large enough to hold the string *::tcl::clock::GetJulianDayFromEraYearMonthDay * plus a terminating NUL. */ - Command *cmdPtr; + Command *cmdPtr; ClockClientData *data; int i; @@ -199,9 +193,9 @@ TclClockInit( * Create the client data, which is a refcounted literal pool. */ - data = (ClockClientData *)ckalloc(sizeof(ClockClientData)); + data = (ClockClientData *) ckalloc(sizeof(ClockClientData)); data->refCount = 0; - data->literals = (Tcl_Obj **)ckalloc(LIT__END * sizeof(Tcl_Obj*)); + data->literals = (Tcl_Obj **) ckalloc(LIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < LIT__END; ++i) { TclInitObjRef(data->literals[i], Tcl_NewStringObj(Literals[i], -1)); } @@ -266,7 +260,7 @@ TclClockInit( cmdPtr->compileProc = clockCmdPtr->compileProc ? clockCmdPtr->compileProc : TclCompileBasicMin0ArgCmd; } - cmdPtr = (Command *)Tcl_CreateObjCommand(interp, + cmdPtr = (Command *) Tcl_CreateObjCommand(interp, "::tcl::unsupported::clock::configure", ClockConfigureObjCmd, data, ClockDeleteCmdProc); data->refCount++; @@ -419,51 +413,44 @@ SavePrevTimezoneObj( static Tcl_Obj * NormTimezoneObj( ClockClientData *dataPtr, /* Client data containing literal pool */ - Tcl_Obj *timezoneObj, /* Name of zone to find */ - int *loaded) /* Used to recognized TZ was loaded */ + Tcl_Obj *timezoneObj, /* Name of zone to find */ + int *loaded) /* Used to recognized TZ was loaded */ { const char *tz; *loaded = 1; - if ( timezoneObj == dataPtr->lastSetupTimeZoneUnnorm - && dataPtr->lastSetupTimeZone != NULL - ) { + if (timezoneObj == dataPtr->lastSetupTimeZoneUnnorm + && dataPtr->lastSetupTimeZone != NULL) { return dataPtr->lastSetupTimeZone; } - if ( timezoneObj == dataPtr->prevSetupTimeZoneUnnorm - && dataPtr->prevSetupTimeZone != NULL - ) { + if (timezoneObj == dataPtr->prevSetupTimeZoneUnnorm + && dataPtr->prevSetupTimeZone != NULL) { return dataPtr->prevSetupTimeZone; } if (timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm - && dataPtr->gmtSetupTimeZone != NULL - ) { + && dataPtr->gmtSetupTimeZone != NULL) { return dataPtr->literals[LIT_GMT]; } - if ( timezoneObj == dataPtr->lastSetupTimeZone - || timezoneObj == dataPtr->prevSetupTimeZone - || timezoneObj == dataPtr->gmtSetupTimeZone - || timezoneObj == dataPtr->systemTimeZone - ) { + if (timezoneObj == dataPtr->lastSetupTimeZone + || timezoneObj == dataPtr->prevSetupTimeZone + || timezoneObj == dataPtr->gmtSetupTimeZone + || timezoneObj == dataPtr->systemTimeZone) { return timezoneObj; } tz = TclGetString(timezoneObj); - if (dataPtr->lastSetupTimeZone != NULL && - strcmp(tz, TclGetString(dataPtr->lastSetupTimeZone)) == 0 - ) { + if (dataPtr->lastSetupTimeZone != NULL + && strcmp(tz, TclGetString(dataPtr->lastSetupTimeZone)) == 0) { TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, timezoneObj); return dataPtr->lastSetupTimeZone; } - if (dataPtr->prevSetupTimeZone != NULL && - strcmp(tz, TclGetString(dataPtr->prevSetupTimeZone)) == 0 - ) { + if (dataPtr->prevSetupTimeZone != NULL + && strcmp(tz, TclGetString(dataPtr->prevSetupTimeZone)) == 0) { TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, timezoneObj); return dataPtr->prevSetupTimeZone; } - if (dataPtr->systemTimeZone != NULL && - strcmp(tz, TclGetString(dataPtr->systemTimeZone)) == 0 - ) { + if (dataPtr->systemTimeZone != NULL + && strcmp(tz, TclGetString(dataPtr->systemTimeZone)) == 0) { return dataPtr->systemTimeZone; } if (strcmp(tz, Literals[LIT_GMT]) == 0) { @@ -555,6 +542,7 @@ SavePrevLocaleObj( ClockClientData *dataPtr) /* Client data containing literal pool */ { Tcl_Obj *localeObj = dataPtr->lastUsedLocale; + if (localeObj && localeObj != dataPtr->prevUsedLocale) { TclSetObjRef(dataPtr->prevUsedLocaleUnnorm, dataPtr->lastUsedLocaleUnnorm); TclSetObjRef(dataPtr->prevUsedLocale, localeObj); @@ -583,97 +571,88 @@ static Tcl_Obj * NormLocaleObj( ClockClientData *dataPtr, /* Client data containing literal pool */ Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_Obj *localeObj, - Tcl_Obj **mcDictObj) + Tcl_Obj *localeObj, + Tcl_Obj **mcDictObj) { const char *loc, *loc2; - if ( localeObj == NULL - || localeObj == dataPtr->literals[LIT_C] - || localeObj == dataPtr->defaultLocale - ) { + + if (localeObj == NULL + || localeObj == dataPtr->literals[LIT_C] + || localeObj == dataPtr->defaultLocale) { *mcDictObj = dataPtr->defaultLocaleDict; return dataPtr->defaultLocale ? - dataPtr->defaultLocale : dataPtr->literals[LIT_C]; + dataPtr->defaultLocale : dataPtr->literals[LIT_C]; } - if ( localeObj == dataPtr->currentLocale - || localeObj == dataPtr->literals[LIT_CURRENT] - ) { + + if (localeObj == dataPtr->currentLocale + || localeObj == dataPtr->literals[LIT_CURRENT]) { if (dataPtr->currentLocale == NULL) { ClockGetCurrentLocale(dataPtr, interp); } *mcDictObj = dataPtr->currentLocaleDict; return dataPtr->currentLocale; } - if ( localeObj == dataPtr->lastUsedLocale - || localeObj == dataPtr->lastUsedLocaleUnnorm - ) { + + if (localeObj == dataPtr->lastUsedLocale + || localeObj == dataPtr->lastUsedLocaleUnnorm) { *mcDictObj = dataPtr->lastUsedLocaleDict; return dataPtr->lastUsedLocale; } - if ( localeObj == dataPtr->prevUsedLocale - || localeObj == dataPtr->prevUsedLocaleUnnorm - ) { + + if (localeObj == dataPtr->prevUsedLocale + || localeObj == dataPtr->prevUsedLocaleUnnorm) { *mcDictObj = dataPtr->prevUsedLocaleDict; return dataPtr->prevUsedLocale; } loc = TclGetString(localeObj); - if ( dataPtr->currentLocale != NULL - && ( localeObj == dataPtr->currentLocale - || (localeObj->length == dataPtr->currentLocale->length - && strcasecmp(loc, TclGetString(dataPtr->currentLocale)) == 0 - ) - ) - ) { + if (dataPtr->currentLocale != NULL + && (localeObj == dataPtr->currentLocale + || (localeObj->length == dataPtr->currentLocale->length + && strcasecmp(loc, TclGetString(dataPtr->currentLocale)) == 0))) { *mcDictObj = dataPtr->currentLocaleDict; return dataPtr->currentLocale; } - if ( dataPtr->lastUsedLocale != NULL - && ( localeObj == dataPtr->lastUsedLocale - || (localeObj->length == dataPtr->lastUsedLocale->length - && strcasecmp(loc, TclGetString(dataPtr->lastUsedLocale)) == 0 - ) - ) - ) { + + if (dataPtr->lastUsedLocale != NULL + && (localeObj == dataPtr->lastUsedLocale + || (localeObj->length == dataPtr->lastUsedLocale->length + && strcasecmp(loc, TclGetString(dataPtr->lastUsedLocale)) == 0))) { *mcDictObj = dataPtr->lastUsedLocaleDict; TclSetObjRef(dataPtr->lastUsedLocaleUnnorm, localeObj); return dataPtr->lastUsedLocale; } - if ( dataPtr->prevUsedLocale != NULL - && ( localeObj == dataPtr->prevUsedLocale - || (localeObj->length == dataPtr->prevUsedLocale->length - && strcasecmp(loc, TclGetString(dataPtr->prevUsedLocale)) == 0 - ) - ) - ) { + + if (dataPtr->prevUsedLocale != NULL + && (localeObj == dataPtr->prevUsedLocale + || (localeObj->length == dataPtr->prevUsedLocale->length + && strcasecmp(loc, TclGetString(dataPtr->prevUsedLocale)) == 0))) { *mcDictObj = dataPtr->prevUsedLocaleDict; TclSetObjRef(dataPtr->prevUsedLocaleUnnorm, localeObj); return dataPtr->prevUsedLocale; } - if ( - (localeObj->length == 1 /* C */ - && strcasecmp(loc, Literals[LIT_C]) == 0) - || (dataPtr->defaultLocale && (loc2 = TclGetString(dataPtr->defaultLocale)) - && localeObj->length == dataPtr->defaultLocale->length - && strcasecmp(loc, loc2) == 0) - ) { + + if ((localeObj->length == 1 /* C */ + && strcasecmp(loc, Literals[LIT_C]) == 0) + || (dataPtr->defaultLocale && (loc2 = TclGetString(dataPtr->defaultLocale)) + && localeObj->length == dataPtr->defaultLocale->length + && strcasecmp(loc, loc2) == 0)) { *mcDictObj = dataPtr->defaultLocaleDict; return dataPtr->defaultLocale ? - dataPtr->defaultLocale : dataPtr->literals[LIT_C]; + dataPtr->defaultLocale : dataPtr->literals[LIT_C]; } - if ( localeObj->length == 7 /* current */ - && strcasecmp(loc, Literals[LIT_CURRENT]) == 0 - ) { + + if (localeObj->length == 7 /* current */ + && strcasecmp(loc, Literals[LIT_CURRENT]) == 0) { if (dataPtr->currentLocale == NULL) { ClockGetCurrentLocale(dataPtr, interp); } *mcDictObj = dataPtr->currentLocaleDict; return dataPtr->currentLocale; } - if ( - (localeObj->length == 6 /* system */ - && strcasecmp(loc, Literals[LIT_SYSTEM]) == 0) - ) { + + if ((localeObj->length == 6 /* system */ + && strcasecmp(loc, Literals[LIT_SYSTEM]) == 0)) { SavePrevLocaleObj(dataPtr); TclSetObjRef(dataPtr->lastUsedLocaleUnnorm, localeObj); localeObj = ClockGetSystemLocale(dataPtr, interp); @@ -681,6 +660,7 @@ NormLocaleObj( *mcDictObj = NULL; return localeObj; } + *mcDictObj = NULL; return localeObj; } @@ -703,7 +683,8 @@ NormLocaleObj( */ Tcl_Obj * -ClockMCDict(ClockFmtScnCmdArgs *opts) +ClockMCDict( + ClockFmtScnCmdArgs *opts) { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; @@ -711,14 +692,13 @@ ClockMCDict(ClockFmtScnCmdArgs *opts) if (opts->mcDictObj == NULL) { /* if locale was not yet used */ - if ( !(opts->flags & CLF_LOCALE_USED) ) { - - opts->localeObj = NormLocaleObj((ClockClientData *)opts->clientData, opts->interp, - opts->localeObj, &opts->mcDictObj); + if (!(opts->flags & CLF_LOCALE_USED)) { + opts->localeObj = NormLocaleObj((ClockClientData *) opts->clientData, opts->interp, + opts->localeObj, &opts->mcDictObj); if (opts->localeObj == NULL) { - Tcl_SetObjResult(opts->interp, - Tcl_NewStringObj("locale not specified and no default locale set", -1)); + Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( + "locale not specified and no default locale set", -1)); Tcl_SetErrorCode(opts->interp, "CLOCK", "badOption", (char *)NULL); return NULL; } @@ -727,10 +707,12 @@ ClockMCDict(ClockFmtScnCmdArgs *opts) /* check locale literals already available (on demand creation) */ if (dataPtr->mcLiterals == NULL) { int i; - dataPtr->mcLiterals = (Tcl_Obj **)ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); + + dataPtr->mcLiterals = (Tcl_Obj **) + ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { TclInitObjRef(dataPtr->mcLiterals[i], - Tcl_NewStringObj(MsgCtLiterals[i], -1)); + Tcl_NewStringObj(MsgCtLiterals[i], -1)); } } } @@ -744,7 +726,7 @@ ClockMCDict(ClockFmtScnCmdArgs *opts) TclSetObjRef(dataPtr->mcDicts, Tcl_NewDictObj()); } Tcl_DictObjGet(NULL, dataPtr->mcDicts, - opts->localeObj, &opts->mcDictObj); + opts->localeObj, &opts->mcDictObj); if (opts->mcDictObj == NULL) { /* get msgcat dictionary - ::tcl::clock::mcget locale */ @@ -766,21 +748,20 @@ ClockMCDict(ClockFmtScnCmdArgs *opts) if (opts->mcDictObj->refCount > ref) { /* smart reference (shared dict as object with no ref-counter) */ opts->mcDictObj = TclDictObjSmartRef(opts->interp, - opts->mcDictObj); + opts->mcDictObj); } /* create exactly one reference to catalog / make it searchable for future */ Tcl_DictObjPut(NULL, dataPtr->mcDicts, opts->localeObj, - opts->mcDictObj); + opts->mcDictObj); - if ( opts->localeObj == dataPtr->literals[LIT_C] - || opts->localeObj == dataPtr->defaultLocale - ) { + if (opts->localeObj == dataPtr->literals[LIT_C] + || opts->localeObj == dataPtr->defaultLocale) { dataPtr->defaultLocaleDict = opts->mcDictObj; } - if ( opts->localeObj == dataPtr->currentLocale ) { + if (opts->localeObj == dataPtr->currentLocale) { dataPtr->currentLocaleDict = opts->mcDictObj; - } else if ( opts->localeObj == dataPtr->lastUsedLocale ) { + } else if (opts->localeObj == dataPtr->lastUsedLocale) { dataPtr->lastUsedLocaleDict = opts->mcDictObj; } else { SavePrevLocaleObj(dataPtr); @@ -815,17 +796,17 @@ ClockMCGet( int mcKey) { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - Tcl_Obj *valObj = NULL; if (opts->mcDictObj == NULL) { ClockMCDict(opts); - if (opts->mcDictObj == NULL) + if (opts->mcDictObj == NULL) { return NULL; + } } Tcl_DictObjGet(opts->interp, opts->mcDictObj, - dataPtr->mcLiterals[mcKey], &valObj); + dataPtr->mcLiterals[mcKey], &valObj); return valObj; /* or NULL in obscure case if Tcl_DictObjGet failed */ } @@ -851,13 +832,13 @@ ClockMCGetIdx( int mcKey) { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - Tcl_Obj *valObj = NULL; if (opts->mcDictObj == NULL) { ClockMCDict(opts); - if (opts->mcDictObj == NULL) + if (opts->mcDictObj == NULL) { return NULL; + } } /* try to get indices object */ @@ -866,11 +847,9 @@ ClockMCGetIdx( } if (Tcl_DictObjGet(NULL, opts->mcDictObj, - dataPtr->mcLitIdxs[mcKey], &valObj) != TCL_OK - ) { + dataPtr->mcLitIdxs[mcKey], &valObj) != TCL_OK) { return NULL; } - return valObj; } @@ -892,23 +871,26 @@ ClockMCGetIdx( int ClockMCSetIdx( ClockFmtScnCmdArgs *opts, - int mcKey, Tcl_Obj *valObj) + int mcKey, + Tcl_Obj *valObj) { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; if (opts->mcDictObj == NULL) { ClockMCDict(opts); - if (opts->mcDictObj == NULL) + if (opts->mcDictObj == NULL) { return TCL_ERROR; + } } /* if literal storage for indices not yet created */ if (dataPtr->mcLitIdxs == NULL) { int i; - dataPtr->mcLitIdxs = (Tcl_Obj **)ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); + + dataPtr->mcLitIdxs = (Tcl_Obj **) ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { TclInitObjRef(dataPtr->mcLitIdxs[i], - Tcl_NewStringObj(MsgCtLitIdxs[i], -1)); + Tcl_NewStringObj(MsgCtLitIdxs[i], -1)); } } @@ -919,8 +901,8 @@ ClockMCSetIdx( static void TimezoneLoaded( ClockClientData *dataPtr, - Tcl_Obj *timezoneObj, /* Name of zone was loaded */ - Tcl_Obj *tzUnnormObj) /* Name of zone was loaded */ + Tcl_Obj *timezoneObj, /* Name of zone was loaded */ + Tcl_Obj *tzUnnormObj) /* Name of zone was loaded */ { /* don't overwrite last-setup with GMT (special case) */ if (timezoneObj == dataPtr->literals[LIT_GMT]) { @@ -962,13 +944,12 @@ TimezoneLoaded( static int ClockConfigureObjCmd( - void *clientData, /* Client data containing literal pool */ - Tcl_Interp *interp, /* Tcl interpreter */ - int objc, /* Parameter count */ - Tcl_Obj *const objv[]) /* Parameter vector */ + void *clientData, /* Client data containing literal pool */ + Tcl_Interp *interp, /* Tcl interpreter */ + int objc, /* Parameter count */ + Tcl_Obj *const objv[]) /* Parameter vector */ { ClockClientData *dataPtr = (ClockClientData *)clientData; - static const char *const options[] = { "-system-tz", "-setup-tz", "-default-locale", "-current-locale", "-clear", @@ -989,15 +970,16 @@ ClockConfigureObjCmd( for (i = 1; i < objc; i++) { if (Tcl_GetIndexFromObj(interp, objv[i++], options, - "option", 0, &optionIndex) != TCL_OK) { + "option", 0, &optionIndex) != TCL_OK) { Tcl_SetErrorCode(interp, "CLOCK", "badOption", - TclGetString(objv[i-1]), (char *)NULL); + TclGetString(objv[i - 1]), (char *)NULL); return TCL_ERROR; } switch (optionIndex) { case CLOCK_SYSTEM_TZ: { /* validate current tz-epoch */ size_t lastTZEpoch = TzsetIfNecessary(); + if (i < objc) { if (dataPtr->systemTimeZone != objv[i]) { TclSetObjRef(dataPtr->systemTimeZone, objv[i]); @@ -1005,26 +987,25 @@ ClockConfigureObjCmd( } dataPtr->lastTZEpoch = lastTZEpoch; } - if (i+1 >= objc && dataPtr->systemTimeZone != NULL - && dataPtr->lastTZEpoch == lastTZEpoch) { + if (i + 1 >= objc && dataPtr->systemTimeZone != NULL + && dataPtr->lastTZEpoch == lastTZEpoch) { Tcl_SetObjResult(interp, dataPtr->systemTimeZone); } + break; } - break; case CLOCK_SETUP_TZ: if (i < objc) { int loaded; Tcl_Obj *timezoneObj = NormTimezoneObj(dataPtr, objv[i], &loaded); + if (!loaded) { TimezoneLoaded(dataPtr, timezoneObj, objv[i]); } Tcl_SetObjResult(interp, timezoneObj); - } - else - if (i+1 >= objc && dataPtr->lastSetupTimeZone != NULL) { + } else if (i + 1 >= objc && dataPtr->lastSetupTimeZone != NULL) { Tcl_SetObjResult(interp, dataPtr->lastSetupTimeZone); } - break; + break; case CLOCK_DEFAULT_LOCALE: if (i < objc) { if (dataPtr->defaultLocale != objv[i]) { @@ -1032,11 +1013,11 @@ ClockConfigureObjCmd( dataPtr->defaultLocaleDict = NULL; } } - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, dataPtr->defaultLocale ? - dataPtr->defaultLocale : dataPtr->literals[LIT_C]); + dataPtr->defaultLocale : dataPtr->literals[LIT_C]); } - break; + break; case CLOCK_CURRENT_LOCALE: if (i < objc) { if (dataPtr->currentLocale != objv[i]) { @@ -1044,30 +1025,32 @@ ClockConfigureObjCmd( dataPtr->currentLocaleDict = NULL; } } - if (i+1 >= objc && dataPtr->currentLocale != NULL) { + if (i + 1 >= objc && dataPtr->currentLocale != NULL) { Tcl_SetObjResult(interp, dataPtr->currentLocale); } - break; + break; case CLOCK_YEAR_CENTURY: if (i < objc) { int year; + if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) { return TCL_ERROR; } dataPtr->currentYearCentury = year; - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, objv[i]); } continue; } - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, - Tcl_NewWideIntObj(dataPtr->currentYearCentury)); + Tcl_NewWideIntObj(dataPtr->currentYearCentury)); } - break; + break; case CLOCK_CENTURY_SWITCH: if (i < objc) { int year; + if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) { return TCL_ERROR; } @@ -1075,14 +1058,15 @@ ClockConfigureObjCmd( Tcl_SetObjResult(interp, objv[i]); continue; } - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, - Tcl_NewWideIntObj(dataPtr->yearOfCenturySwitch)); + Tcl_NewWideIntObj(dataPtr->yearOfCenturySwitch)); } - break; + break; case CLOCK_MIN_YEAR: if (i < objc) { int year; + if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) { return TCL_ERROR; } @@ -1090,14 +1074,15 @@ ClockConfigureObjCmd( Tcl_SetObjResult(interp, objv[i]); continue; } - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, - Tcl_NewWideIntObj(dataPtr->validMinYear)); + Tcl_NewWideIntObj(dataPtr->validMinYear)); } - break; + break; case CLOCK_MAX_YEAR: if (i < objc) { int year; + if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) { return TCL_ERROR; } @@ -1105,14 +1090,15 @@ ClockConfigureObjCmd( Tcl_SetObjResult(interp, objv[i]); continue; } - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, - Tcl_NewWideIntObj(dataPtr->validMaxYear)); + Tcl_NewWideIntObj(dataPtr->validMaxYear)); } - break; + break; case CLOCK_MAX_JDN: if (i < objc) { double jd; + if (Tcl_GetDoubleFromObj(interp, objv[i], &jd) != TCL_OK) { return TCL_ERROR; } @@ -1120,14 +1106,14 @@ ClockConfigureObjCmd( Tcl_SetObjResult(interp, objv[i]); continue; } - if (i+1 >= objc) { - Tcl_SetObjResult(interp, - Tcl_NewDoubleObj(dataPtr->maxJDN)); + if (i + 1 >= objc) { + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dataPtr->maxJDN)); } - break; + break; case CLOCK_VALIDATE: if (i < objc) { int val; + if (Tcl_GetBooleanFromObj(interp, objv[i], &val) != TCL_OK) { return TCL_ERROR; } @@ -1137,35 +1123,34 @@ ClockConfigureObjCmd( dataPtr->defFlags &= ~CLF_VALIDATE; } } - if (i+1 >= objc) { + if (i + 1 >= objc) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(dataPtr->defFlags & CLF_VALIDATE)); } - break; + break; case CLOCK_CLEAR_CACHE: ClockConfigureClear(dataPtr); - break; - case CLOCK_INIT_COMPLETE: - { - /* - * Init completed. - * Compile clock ensemble (performance purposes). - */ - Tcl_Command token = Tcl_FindCommand(interp, "::clock", + break; + case CLOCK_INIT_COMPLETE: { + /* + * Init completed. + * Compile clock ensemble (performance purposes). + */ + Tcl_Command token = Tcl_FindCommand(interp, "::clock", NULL, TCL_GLOBAL_ONLY); - if (!token) { - return TCL_ERROR; - } - int ensFlags = 0; - if (Tcl_GetEnsembleFlags(interp, token, &ensFlags) != TCL_OK) { - return TCL_ERROR; - } - ensFlags |= ENSEMBLE_COMPILE; - if (Tcl_SetEnsembleFlags(interp, token, ensFlags) != TCL_OK) { - return TCL_ERROR; - } + if (!token) { + return TCL_ERROR; } - break; + int ensFlags = 0; + if (Tcl_GetEnsembleFlags(interp, token, &ensFlags) != TCL_OK) { + return TCL_ERROR; + } + ensFlags |= ENSEMBLE_COMPILE; + if (Tcl_SetEnsembleFlags(interp, token, ensFlags) != TCL_OK) { + return TCL_ERROR; + } + break; + } } } @@ -1190,7 +1175,7 @@ ClockConfigureObjCmd( static inline Tcl_Obj * ClockGetTZData( - void *clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *timezoneObj) /* Name of the timezone */ { @@ -1198,9 +1183,8 @@ ClockGetTZData( Tcl_Obj *ret, **out = NULL; /* if cached (if already setup this one) */ - if ( timezoneObj == dataPtr->lastSetupTimeZone - || timezoneObj == dataPtr->lastSetupTimeZoneUnnorm - ) { + if (timezoneObj == dataPtr->lastSetupTimeZone + || timezoneObj == dataPtr->lastSetupTimeZoneUnnorm) { if (dataPtr->lastSetupTZData != NULL) { return dataPtr->lastSetupTZData; } @@ -1214,20 +1198,14 @@ ClockGetTZData( return dataPtr->systemSetupTZData; } out = &dataPtr->systemSetupTZData; - } - else - if ( timezoneObj == dataPtr->literals[LIT_GMT] - || timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm - ) { + } else if (timezoneObj == dataPtr->literals[LIT_GMT] + || timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm) { if (dataPtr->gmtSetupTZData != NULL) { return dataPtr->gmtSetupTZData; } out = &dataPtr->gmtSetupTZData; - } - else - if ( timezoneObj == dataPtr->prevSetupTimeZone - || timezoneObj == dataPtr->prevSetupTimeZoneUnnorm - ) { + } else if (timezoneObj == dataPtr->prevSetupTimeZone + || timezoneObj == dataPtr->prevSetupTimeZoneUnnorm) { if (dataPtr->prevSetupTZData != NULL) { return dataPtr->prevSetupTZData; } @@ -1235,14 +1213,12 @@ ClockGetTZData( } ret = Tcl_ObjGetVar2(interp, dataPtr->literals[LIT_TZDATA], - timezoneObj, TCL_LEAVE_ERR_MSG); + timezoneObj, TCL_LEAVE_ERR_MSG); /* cache using corresponding slot and as last used */ if (out != NULL) { TclSetObjRef(*out, ret); - } - else - if (dataPtr->lastSetupTimeZone != timezoneObj) { + } else if (dataPtr->lastSetupTimeZone != timezoneObj) { SavePrevTimezoneObj(dataPtr); TclSetObjRef(dataPtr->lastSetupTimeZone, timezoneObj); TclUnsetObjRef(dataPtr->lastSetupTimeZoneUnnorm); @@ -1269,7 +1245,7 @@ ClockGetTZData( static Tcl_Obj * ClockGetSystemTimeZone( - void *clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp) /* Tcl interpreter */ { ClockClientData *dataPtr = (ClockClientData *)clientData; @@ -1308,7 +1284,7 @@ ClockGetSystemTimeZone( Tcl_Obj * ClockSetupTimeZone( - void *clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *timezoneObj) { @@ -1317,21 +1293,18 @@ ClockSetupTimeZone( Tcl_Obj *callargs[2]; /* if cached (if already setup this one) */ - if ( timezoneObj == dataPtr->literals[LIT_GMT] - && dataPtr->gmtSetupTZData != NULL - ) { + if (timezoneObj == dataPtr->literals[LIT_GMT] + && dataPtr->gmtSetupTZData != NULL) { return timezoneObj; } - if ( ( timezoneObj == dataPtr->lastSetupTimeZone - || timezoneObj == dataPtr->lastSetupTimeZoneUnnorm - ) && dataPtr->lastSetupTimeZone != NULL - ) { + if ((timezoneObj == dataPtr->lastSetupTimeZone + || timezoneObj == dataPtr->lastSetupTimeZoneUnnorm) + && dataPtr->lastSetupTimeZone != NULL) { return dataPtr->lastSetupTimeZone; } - if ( ( timezoneObj == dataPtr->prevSetupTimeZone - || timezoneObj == dataPtr->prevSetupTimeZoneUnnorm - ) && dataPtr->prevSetupTimeZone != NULL - ) { + if ((timezoneObj == dataPtr->prevSetupTimeZone + || timezoneObj == dataPtr->prevSetupTimeZoneUnnorm) + && dataPtr->prevSetupTimeZone != NULL) { return dataPtr->prevSetupTimeZone; } @@ -1378,19 +1351,23 @@ ClockSetupTimeZone( */ Tcl_Obj * -ClockFormatNumericTimeZone(int z) { - char buf[12+1], *p; +ClockFormatNumericTimeZone( + int z) +{ + char buf[12 + 1], *p; - if ( z < 0 ) { + if (z < 0) { z = -z; *buf = '-'; } else { *buf = '+'; } - TclItoAw(buf+1, z / 3600, '0', 2); z %= 3600; - p = TclItoAw(buf+3, z / 60, '0', 2); z %= 60; + TclItoAw(buf + 1, z / 3600, '0', 2); + z %= 3600; + p = TclItoAw(buf + 3, z / 60, '0', 2); + z %= 60; if (z != 0) { - p = TclItoAw(buf+5, z, '0', 2); + p = TclItoAw(buf + 5, z, '0', 2); } return Tcl_NewStringObj(buf, p - buf); } @@ -1424,7 +1401,7 @@ ClockFormatNumericTimeZone(int z) { static int ClockConvertlocaltoutcObjCmd( - void *clientData, /* Client data */ + void *clientData, /* Client data */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ @@ -1456,10 +1433,9 @@ ClockConvertlocaltoutcObjCmd( "found in dictionary", -1)); return TCL_ERROR; } - if ((TclGetWideIntFromObj(interp, secondsObj, - &fields.localSeconds) != TCL_OK) - || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) - || ConvertLocalToUTC(clientData, interp, &fields, objv[2], changeover)) { + if ((TclGetWideIntFromObj(interp, secondsObj, &fields.localSeconds) != TCL_OK) + || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) + || ConvertLocalToUTC(clientData, interp, &fields, objv[2], changeover)) { return TCL_ERROR; } @@ -1515,7 +1491,7 @@ ClockConvertlocaltoutcObjCmd( int ClockGetdatefieldsObjCmd( - void *clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ @@ -1554,7 +1530,7 @@ ClockGetdatefieldsObjCmd( /* Extract fields */ if (ClockGetDateFields(clientData, interp, &fields, objv[2], - changeover) != TCL_OK) { + changeover) != TCL_OK) { return TCL_ERROR; } @@ -1612,7 +1588,7 @@ ClockGetdatefieldsObjCmd( int ClockGetDateFields( - void *clientData, /* Client data of the interpreter */ + void *clientData, /* Client data of the interpreter */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Pointer to result fields, where * fields->seconds contains date to extract */ @@ -1709,7 +1685,7 @@ FetchIntField( static int ClockGetjuliandayfromerayearmonthdayObjCmd( - void *clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ @@ -1795,7 +1771,7 @@ ClockGetjuliandayfromerayearmonthdayObjCmd( static int ClockGetjuliandayfromerayearweekdayObjCmd( - void *clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ @@ -1878,7 +1854,7 @@ ClockGetjuliandayfromerayearweekdayObjCmd( static int ConvertLocalToUTC( - void *clientData, /* Client data of the interpreter */ + void *clientData, /* Client data of the interpreter */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *timezoneObj, /* Time zone */ @@ -1886,7 +1862,7 @@ ConvertLocalToUTC( { ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *tzdata; /* Time zone data */ - Tcl_Size rowc; /* Number of rows in tzdata */ + Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ Tcl_WideInt seconds; ClockLastTZOffs * ltzoc = NULL; @@ -1909,9 +1885,8 @@ ConvertLocalToUTC( continue; } seconds = fields->localSeconds - ltzoc->tzOffset; - if ( seconds >= ltzoc->rangesVal[0] - && seconds < ltzoc->rangesVal[1] - ) { + if (seconds >= ltzoc->rangesVal[0] + && seconds < ltzoc->rangesVal[1]) { /* the same time zone and offset (UTC time inside the last minute) */ fields->tzOffset = ltzoc->tzOffset; fields->seconds = seconds; @@ -1945,21 +1920,19 @@ ConvertLocalToUTC( */ if (rowc == 0) { - if (ConvertLocalToUTCUsingC(interp, fields, changeover) != TCL_OK) { return TCL_ERROR; - }; + } /* we cannot cache (ranges unknown yet) - todo: check later the DST-hole here */ return TCL_OK; - } else { Tcl_WideInt rangesVal[2]; if (ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv, rangesVal) != TCL_OK) { return TCL_ERROR; - }; + } seconds = fields->seconds; @@ -1985,14 +1958,14 @@ ConvertLocalToUTC( /* check DST-hole: if retrieved seconds is out of range */ - if ( ltzoc->rangesVal[0] > seconds || seconds >= ltzoc->rangesVal[1] ) { + if (ltzoc->rangesVal[0] > seconds || seconds >= ltzoc->rangesVal[1]) { dstHole: - #if 0 +#if 0 printf("given local-time is outside the time-zone (in DST-hole): " "%d - offs %d => %d <= %d < %d\n", (int)fields->localSeconds, fields->tzOffset, (int)ltzoc->rangesVal[0], (int)seconds, (int)ltzoc->rangesVal[1]); - #endif +#endif /* because we don't know real TZ (we're outsize), just invalidate local * time (which could be verified in ClockValidDate later) */ fields->localSeconds = TCL_INV_SECONDS; /* not valid seconds */ @@ -2050,7 +2023,7 @@ ConvertLocalToUTCUsingTable( fields->seconds = fields->localSeconds; while (1) { row = LookupLastTransition(interp, fields->seconds, rowc, rowv, - rangesVal); + rangesVal); if ((row == NULL) || TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK @@ -2060,7 +2033,7 @@ ConvertLocalToUTCUsingTable( } for (i = 0; i < nHave; ++i) { if (have[i].tzOffset == fields->tzOffset) { - goto found; + break; } } if (nHave == 8) { @@ -2071,7 +2044,6 @@ ConvertLocalToUTCUsingTable( fields->seconds = fields->localSeconds - fields->tzOffset; } - found: fields->tzOffset = have[i].tzOffset; fields->seconds = fields->localSeconds - fields->tzOffset; TclSetObjRef(fields->tzName, have[i].tzName); @@ -2112,7 +2084,7 @@ ConvertLocalToUTCUsingC( */ ClockExtractJDAndSODFromSeconds(fields->julianDay, secondOfDay, - fields->localSeconds); + fields->localSeconds); GetGregorianEraYearDay(fields, changeover); GetMonthDay(fields); @@ -2174,7 +2146,7 @@ ConvertLocalToUTCUsingC( int ConvertUTCToLocal( - void *clientData, /* Client data of the interpreter */ + void *clientData, /* Client data of the interpreter */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *timezoneObj, /* Time zone */ @@ -2182,7 +2154,7 @@ ConvertUTCToLocal( { ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *tzdata; /* Time zone data */ - Tcl_Size rowc; /* Number of rows in tzdata */ + Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ ClockLastTZOffs * ltzoc = NULL; @@ -2192,9 +2164,10 @@ ConvertUTCToLocal( fields->tzOffset = 0; if (dataPtr->gmtTZName == NULL) { Tcl_Obj *tzName; + tzdata = ClockGetTZData(clientData, interp, timezoneObj); - if ( TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK - || Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) { + if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK + || Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) { return TCL_ERROR; } TclSetObjRef(dataPtr->gmtTZName, tzName); @@ -2213,9 +2186,8 @@ ConvertUTCToLocal( ltzoc = NULL; continue; } - if ( fields->seconds >= ltzoc->rangesVal[0] - && fields->seconds < ltzoc->rangesVal[1] - ) { + if (fields->seconds >= ltzoc->rangesVal[0] + && fields->seconds < ltzoc->rangesVal[1]) { /* the same time zone and offset (UTC time inside the last minute) */ fields->tzOffset = ltzoc->tzOffset; fields->localSeconds = fields->seconds + fields->tzOffset; @@ -2243,7 +2215,6 @@ ConvertUTCToLocal( */ if (rowc == 0) { - if (ConvertUTCToLocalUsingC(interp, fields, changeover) != TCL_OK) { return TCL_ERROR; } @@ -2308,13 +2279,13 @@ static int ConvertUTCToLocalUsingTable( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the date */ - Tcl_Size rowc, /* Number of rows in the conversion table + Tcl_Size rowc, /* Number of rows in the conversion table * (>= 1) */ Tcl_Obj *const rowv[], /* Rows of the conversion table */ Tcl_WideInt *rangesVal) /* Return bounds for time period */ { Tcl_Obj *row; /* Row containing the current information */ - Tcl_Size cellc; /* Count of cells in the row (must be 4) */ + Tcl_Size cellc; /* Count of cells in the row (must be 4) */ Tcl_Obj **cellv; /* Pointers to the cells */ /* @@ -2322,9 +2293,9 @@ ConvertUTCToLocalUsingTable( */ row = LookupLastTransition(interp, fields->seconds, rowc, rowv, rangesVal); - if (row == NULL || - TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK || - TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) { + if (row == NULL + || TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK + || TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) { return TCL_ERROR; } @@ -2418,10 +2389,12 @@ ConvertUTCToLocalUsingC( } else { *buffer = '+'; } - TclItoAw(buffer+1, diff / 3600, '0', 2); diff %= 3600; - p = TclItoAw(buffer+3, diff / 60, '0', 2); diff %= 60; + TclItoAw(buffer + 1, diff / 3600, '0', 2); + diff %= 3600; + p = TclItoAw(buffer + 3, diff / 60, '0', 2); + diff %= 60; if (diff != 0) { - p = TclItoAw(buffer+5, diff, '0', 2); + p = TclItoAw(buffer + 5, diff, '0', 2); } TclSetObjRef(fields->tzName, Tcl_NewStringObj(buffer, p - buffer)); return TCL_OK; @@ -2445,11 +2418,11 @@ Tcl_Obj * LookupLastTransition( Tcl_Interp *interp, /* Interpreter for error messages */ Tcl_WideInt tick, /* Time from the epoch */ - Tcl_Size rowc, /* Number of rows of tzdata */ + Tcl_Size rowc, /* Number of rows of tzdata */ Tcl_Obj *const *rowv, /* Rows in tzdata */ Tcl_WideInt *rangesVal) /* Return bounds for time period */ { - Tcl_Size l, u; + Tcl_Size l, u; Tcl_Obj *compObj; Tcl_WideInt compVal, fromVal = LLONG_MIN, toVal = LLONG_MAX; @@ -2480,7 +2453,7 @@ LookupLastTransition( */ l = 0; - u = rowc-1; + u = rowc - 1; while (l < u) { Tcl_Size m = (l + u + 1) / 2; @@ -2492,7 +2465,7 @@ LookupLastTransition( l = m; fromVal = compVal; } else { - u = m-1; + u = m - 1; toVal = compVal; } } @@ -2722,7 +2695,7 @@ GetMonthDay( /* then do forwards backwards correction */ while (1) { if (day > dipm[month]) { - if (month >= 11 || day <= dipm[month+1]) { + if (month >= 11 || day <= dipm[month + 1]) { break; } month++; @@ -2734,7 +2707,7 @@ GetMonthDay( } } day -= dipm[month]; - fields->month = month+1; + fields->month = month + 1; fields->dayOfMonth = day; } @@ -2845,7 +2818,7 @@ GetJulianDayFromEraYearMonthDay( fields->gregorian = 1; if (year < 1) { fields->isBce = 1; - fields->year = 1-year; + fields->year = 1 - year; } else { fields->isBce = 0; fields->year = year; @@ -2939,22 +2912,22 @@ GetJulianDayFromEraYearDay( /* Try the Gregorian calendar first. */ fields->gregorian = 1; fields->julianDay = - 1721425 - + fields->dayOfYear - + ( 365 * ym1 ) - + ( ym1 / 4 ) - - ( ym1 / 100 ) - + ( ym1 / 400 ); + 1721425 + + fields->dayOfYear + + (365 * ym1) + + (ym1 / 4) + - (ym1 / 100) + + (ym1 / 400); /* If the date is before the Gregorian change, use the Julian calendar. */ - if ( fields->julianDay < changeover ) { + if (fields->julianDay < changeover) { fields->gregorian = 0; fields->julianDay = - 1721423 - + fields->dayOfYear - + ( 365 * ym1 ) - + ( ym1 / 4 ); + 1721423 + + fields->dayOfYear + + (365 * ym1) + + (ym1 / 4); } } /* @@ -2980,13 +2953,13 @@ IsGregorianLeapYear( if (fields->isBce) { year = 1 - year; } - if (year%4 != 0) { + if (year % 4 != 0) { return 0; } else if (!(fields->gregorian)) { return 1; - } else if (year%400 == 0) { + } else if (year % 400 == 0) { return 1; - } else if (year%100 == 0) { + } else if (year % 100 == 0) { return 0; } else { return 1; @@ -3107,7 +3080,7 @@ ThreadSafeLocalTime( * Get a thread-local buffer to hold the returned time. */ - struct tm *tmPtr = (struct tm *)Tcl_GetThreadData(&tmKey, sizeof(struct tm)); + struct tm *tmPtr = (struct tm *) Tcl_GetThreadData(&tmKey, sizeof(struct tm)); #ifdef HAVE_LOCALTIME_R tmPtr = localtime_r(timePtr, tmPtr); #else @@ -3307,10 +3280,10 @@ ClockParseFmtScnArgs( * (by scan or add) resp. clockval (by format) */ int objc, /* Parameter count */ Tcl_Obj *const objv[], /* Parameter vector */ - int flags, /* Flags, differentiates between format, scan, add */ - const char *syntax /* Syntax of the current command */ -) { - Tcl_Interp *interp = opts->interp; + int flags, /* Flags, differentiates between format, scan, add */ + const char *syntax) /* Syntax of the current command */ +{ + Tcl_Interp *interp = opts->interp; ClockClientData *dataPtr = (ClockClientData *)opts->clientData; int gmtFlag = 0; static const char *const options[] = { @@ -3325,7 +3298,7 @@ ClockParseFmtScnArgs( int i, baseIdx; Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */ - if ( flags & (CLC_SCN_ARGS) ) { + if (flags & CLC_SCN_ARGS) { /* default flags (from configure) */ opts->flags |= dataPtr->defFlags & (CLF_VALIDATE); } else { @@ -3342,25 +3315,25 @@ ClockParseFmtScnArgs( /* bypass integers (offsets) by "clock add" */ if (flags & CLC_ADD_ARGS) { Tcl_WideInt num; + if (TclGetWideIntFromObj(NULL, objv[i], &num) == TCL_OK) { continue; } } /* get option */ if (Tcl_GetIndexFromObj(interp, objv[i], options, - "option", 0, &optionIndex) != TCL_OK) { + "option", 0, &optionIndex) != TCL_OK) { goto badOptionMsg; } /* if already specified */ if (saw & (1 << optionIndex)) { - if ( !(flags & CLC_SCN_ARGS) - && optionIndex == CLC_ARGS_BASE) { + if (!(flags & CLC_SCN_ARGS) + && optionIndex == CLC_ARGS_BASE) { goto badOptionMsg; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": doubly present", - TclGetString(objv[i])) - ); + "bad option \"%s\": doubly present", + TclGetString(objv[i]))); goto badOption; } switch (optionIndex) { @@ -3368,28 +3341,29 @@ ClockParseFmtScnArgs( if (flags & CLC_ADD_ARGS) { goto badOptionMsg; } - opts->formatObj = objv[i+1]; + opts->formatObj = objv[i + 1]; break; case CLC_ARGS_GMT: - if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK){ + if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &gmtFlag) != TCL_OK){ return TCL_ERROR; } break; case CLC_ARGS_LOCALE: - opts->localeObj = objv[i+1]; + opts->localeObj = objv[i + 1]; break; case CLC_ARGS_TIMEZONE: - opts->timezoneObj = objv[i+1]; + opts->timezoneObj = objv[i + 1]; break; case CLC_ARGS_BASE: - opts->baseObj = objv[(baseIdx = i+1)]; + opts->baseObj = objv[(baseIdx = i + 1)]; break; case CLC_ARGS_VALIDATE: - if ( !(flags & CLC_SCN_ARGS) ) { + if (!(flags & CLC_SCN_ARGS)) { goto badOptionMsg; } else { int val; - if (Tcl_GetBooleanFromObj(interp, objv[i+1], &val) != TCL_OK) { + + if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &val) != TCL_OK) { return TCL_ERROR; } if (val) { @@ -3415,13 +3389,10 @@ ClockParseFmtScnArgs( } if (gmtFlag) { opts->timezoneObj = dataPtr->literals[LIT_GMT]; - } - else - /* If time zone not specified use system time zone */ - if ( opts->timezoneObj == NULL - || TclGetString(opts->timezoneObj) == NULL - || opts->timezoneObj->length == 0 - ) { + } else if (opts->timezoneObj == NULL + || TclGetString(opts->timezoneObj) == NULL + || opts->timezoneObj->length == 0) { + /* If time zone not specified use system time zone */ opts->timezoneObj = ClockGetSystemTimeZone(opts->clientData, interp); if (opts->timezoneObj == NULL) { return TCL_ERROR; @@ -3439,20 +3410,18 @@ ClockParseFmtScnArgs( if (opts->baseObj != NULL) { Tcl_Obj *baseObj = opts->baseObj; - /* bypass integer recognition if looks like option "-now" */ - if ( - (baseObj->bytes && baseObj->length == 4 && *(baseObj->bytes+1) == 'n') || - TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK - ) { + /* bypass integer recognition if looks like option "-now" */ + if ((baseObj->bytes && baseObj->length == 4 && *(baseObj->bytes + 1) == 'n') + || TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK) { /* we accept "-now" as current date-time */ static const char *const nowOpts[] = { "-now", NULL }; int idx; + if (Tcl_GetIndexFromObj(interp, baseObj, nowOpts, "seconds", - TCL_EXACT, &idx) == TCL_OK - ) { + TCL_EXACT, &idx) == TCL_OK) { goto baseNow; } @@ -3473,22 +3442,18 @@ ClockParseFmtScnArgs( */ if (TclHasInternalRep(baseObj, &tclBignumType) - || baseVal < TCL_MIN_SECONDS || baseVal > TCL_MAX_SECONDS - ) { -baseOverflow: + || baseVal < TCL_MIN_SECONDS || baseVal > TCL_MAX_SECONDS) { + baseOverflow: Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]); i = baseIdx; goto badOption; } - } else { + Tcl_Time now; -baseNow: - { - Tcl_Time now; - Tcl_GetTime(&now); - baseVal = (Tcl_WideInt) now.sec; - } + baseNow: + Tcl_GetTime(&now); + baseVal = (Tcl_WideInt) now.sec; } /* @@ -3497,17 +3462,17 @@ baseNow: */ /* check base fields already cached (by TZ, last-second cache) */ - if ( dataPtr->lastBase.timezoneObj == opts->timezoneObj - && dataPtr->lastBase.date.seconds == baseVal - && (!(dataPtr->lastBase.date.flags & CLF_CTZ) - || dataPtr->lastTZEpoch == TzsetIfNecessary()) - ) { + if (dataPtr->lastBase.timezoneObj == opts->timezoneObj + && dataPtr->lastBase.date.seconds == baseVal + && (!(dataPtr->lastBase.date.flags & CLF_CTZ) + || dataPtr->lastTZEpoch == TzsetIfNecessary())) { memcpy(date, &dataPtr->lastBase.date, ClockCacheableDateFieldsSize); } else { /* extact fields from base */ date->seconds = baseVal; if (ClockGetDateFields(opts->clientData, interp, date, opts->timezoneObj, - GREGORIAN_CHANGE_DATE) != TCL_OK) { /* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */ + GREGORIAN_CHANGE_DATE) != TCL_OK) { + /* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */ return TCL_ERROR; } /* cache last base */ @@ -3517,18 +3482,14 @@ baseNow: return TCL_OK; -badOptionMsg: - + badOptionMsg: Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be %s", - TclGetString(objv[i]), syntax) - ); - -badOption: + "bad option \"%s\": must be %s", + TclGetString(objv[i]), syntax)); + badOption: Tcl_SetErrorCode(interp, "CLOCK", "badOption", (i < objc) ? TclGetString(objv[i]) : (char *)NULL, (char *)NULL); - return TCL_ERROR; } @@ -3554,7 +3515,7 @@ badOption: int ClockFormatObjCmd( - void *clientData, /* Client data containing literal pool */ + void *clientData, /* Client data containing literal pool */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter values */ @@ -3562,12 +3523,12 @@ ClockFormatObjCmd( ClockClientData *dataPtr = (ClockClientData *)clientData; static const char *syntax = "clock format clockval|-now " - "?-format string? " - "?-gmt boolean? " - "?-locale LOCALE? ?-timezone ZONE?"; + "?-format string? " + "?-gmt boolean? " + "?-locale LOCALE? ?-timezone ZONE?"; int ret; ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */ - DateFormat dateFmt; /* Common structure used for formatting */ + DateFormat dateFmt; /* Common structure used for formatting */ /* even number of arguments */ if ((objc & 1) == 1) { @@ -3595,18 +3556,11 @@ ClockFormatObjCmd( } /* Use compiled version of Format - */ - ret = ClockFormat(&dateFmt, &opts); -done: - + done: TclUnsetObjRef(dateFmt.date.tzName); - - if (ret != TCL_OK) { - return ret; - } - - return TCL_OK; + return ret; } /*---------------------------------------------------------------------- @@ -3631,7 +3585,7 @@ done: int ClockScanObjCmd( - void *clientData, /* Client data containing literal pool */ + void *clientData, /* Client data containing literal pool */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter values */ @@ -3643,8 +3597,8 @@ ClockScanObjCmd( "?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?"; int ret; ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */ - DateInfo yy; /* Common structure used for parsing */ - DateInfo *info = &yy; + DateInfo yy; /* Common structure used for parsing */ + DateInfo *info = &yy; /* even number of arguments */ if ((objc & 1) == 1) { @@ -3673,17 +3627,17 @@ ClockScanObjCmd( if (opts.formatObj == NULL) { /* Use compiled version of FreeScan - */ - /* [SB] TODO: Perhaps someday we'll localize the legacy code. Right now, it's not localized. */ + /* [SB] TODO: Perhaps someday we'll localize the legacy code. Right now, + * it's not localized. */ if (opts.localeObj != NULL) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("legacy [clock scan] does not support -locale", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "legacy [clock scan] does not support -locale", -1)); Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", (char *)NULL); ret = TCL_ERROR; goto done; } ret = ClockFreeScan(&yy, objv[1], &opts); - } - else { + } else { /* Use compiled version of Scan - */ ret = ClockScan(&yy, objv[1], &opts); @@ -3698,9 +3652,8 @@ ClockScanObjCmd( * validate with stage 1 before local time conversion, otherwise it may * adjust date/time tokens to valid values */ - if ( (opts.flags & CLF_VALIDATE_S1) && - info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC) - ) { + if ((opts.flags & CLF_VALIDATE_S1) + && info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)) { ret = ClockValidDate(&yy, &opts, CLF_VALIDATE_S1); if (ret != TCL_OK) { goto done; @@ -3715,21 +3668,18 @@ ClockScanObjCmd( } /* Apply remaining validation rules, if expected */ - if ( (opts.flags & CLF_VALIDATE) ) { + if ((opts.flags & CLF_VALIDATE)) { ret = ClockValidDate(&yy, &opts, opts.flags & CLF_VALIDATE); if (ret != TCL_OK) { goto done; } } -done: - + done: TclUnsetObjRef(yy.date.tzName); - if (ret != TCL_OK) { return ret; } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds)); return TCL_OK; } @@ -3751,19 +3701,16 @@ done: static int ClockScanCommit( - DateInfo *info, /* Clock scan info structure */ + DateInfo *info, /* Clock scan info structure */ ClockFmtScnCmdArgs *opts) /* Format, locale, timezone and base */ { /* If needed assemble julianDay using year, month, etc. */ if (info->flags & CLF_ASSEMBLE_JULIANDAY) { if ((info->flags & CLF_ISO8601WEAK)) { GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE); - } - else - if ( !(info->flags & CLF_DAYOFYEAR) /* no day of year */ - || (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */ - == (CLF_DAYOFMONTH|CLF_MONTH) - ) { + } else if (!(info->flags & CLF_DAYOFYEAR) /* no day of year */ + || (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */ + == (CLF_DAYOFMONTH|CLF_MONTH)) { GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE); } else { GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE); @@ -3775,11 +3722,12 @@ ClockScanCommit( /* some overflow checks */ if (info->flags & CLF_JULIANDAY) { ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + double curJDN = (double)yydate.julianDay - + ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY; + + ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY; if (curJDN > dataPtr->maxJDN) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "requested date too large to represent", -1)); + "requested date too large to represent", -1)); Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL); return TCL_ERROR; } @@ -3789,9 +3737,9 @@ ClockScanCommit( if (info->flags & (CLF_ASSEMBLE_SECONDS)) { yydate.localSeconds = - -210866803200LL - + ( SECONDS_PER_DAY * yydate.julianDay ) - + ( yySecondOfDay % SECONDS_PER_DAY ); + -210866803200LL + + (SECONDS_PER_DAY * yydate.julianDay) + + (yySecondOfDay % SECONDS_PER_DAY); } if (info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)) { @@ -3804,7 +3752,6 @@ ClockScanCommit( /* Increment UTC seconds with relative time */ yydate.seconds += yyRelSeconds; - return TCL_OK; } @@ -3825,7 +3772,7 @@ ClockScanCommit( static int ClockValidDate( - DateInfo *info, /* Clock scan info structure */ + DateInfo *info, /* Clock scan info structure */ ClockFmtScnCmdArgs *opts, /* Scan options */ int stage) /* Stage to validate (1, 2 or 3 for both) */ { @@ -3834,13 +3781,13 @@ ClockValidDate( int tempCpyFlg = 0; ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - #if 0 +#if 0 printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %d, " - "yySecondOfDay %d, sec %d, daySec %d, tzOffset %d\n", - yyMonth, yyDay, yydate.dayOfYear, yyHour, yyMinutes, yySeconds, - yySecondOfDay, (int)yydate.localSeconds, (int)(yydate.localSeconds % SECONDS_PER_DAY), - yydate.tzOffset); - #endif + "yySecondOfDay %d, sec %d, daySec %d, tzOffset %d\n", + yyMonth, yyDay, yydate.dayOfYear, yyHour, yyMinutes, yySeconds, + yySecondOfDay, (int)yydate.localSeconds, (int)(yydate.localSeconds % SECONDS_PER_DAY), + yydate.tzOffset); +#endif if (!(stage & CLF_VALIDATE_S1) || !(opts->flags & CLF_VALIDATE_S1)) { goto stage_2; @@ -3850,15 +3797,19 @@ ClockValidDate( /* first year (used later in hath / daysInPriorMonths) */ if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR))) { if ((info->flags & CLF_ISO8601YEAR)) { - if ( yydate.iso8601Year < dataPtr->validMinYear - || yydate.iso8601Year > dataPtr->validMaxYear ) { - errMsg = "invalid iso year"; errCode = "iso year"; goto error; + if (yydate.iso8601Year < dataPtr->validMinYear + || yydate.iso8601Year > dataPtr->validMaxYear) { + errMsg = "invalid iso year"; + errCode = "iso year"; + goto error; } } if (info->flags & CLF_YEAR) { - if ( yyYear < dataPtr->validMinYear - || yyYear > dataPtr->validMaxYear ) { - errMsg = "invalid year"; errCode = "year"; goto error; + if (yyYear < dataPtr->validMinYear + || yyYear > dataPtr->validMaxYear) { + errMsg = "invalid year"; + errCode = "year"; + goto error; } } else if ((info->flags & CLF_ISO8601YEAR)) { yyYear = yydate.iso8601Year; /* used to recognize leap */ @@ -3866,61 +3817,77 @@ ClockValidDate( if ((info->flags & (CLF_ISO8601YEAR|CLF_YEAR)) == (CLF_ISO8601YEAR|CLF_YEAR)) { if (yyYear != yydate.iso8601Year) { - errMsg = "ambiguous year"; errCode = "year"; goto error; + errMsg = "ambiguous year"; + errCode = "year"; + goto error; } } } /* and month (used later in hath) */ if (info->flags & CLF_MONTH) { - if ( yyMonth < 1 || yyMonth > 12 ) { - errMsg = "invalid month"; errCode = "month"; goto error; + if (yyMonth < 1 || yyMonth > 12) { + errMsg = "invalid month"; + errCode = "month"; + goto error; } } /* day of month */ if (info->flags & (CLF_DAYOFMONTH|CLF_DAYOFWEEK)) { - if ( yyDay < 1 || yyDay > 31 ) { - errMsg = "invalid day"; errCode = "day"; goto error; - } - else - if ( (info->flags & CLF_MONTH) ) { + if (yyDay < 1 || yyDay > 31) { + errMsg = "invalid day"; + errCode = "day"; + goto error; + } else if ((info->flags & CLF_MONTH)) { const int *h = hath[IsGregorianLeapYear(&yydate)]; - if ( yyDay > h[yyMonth-1] ) { - errMsg = "invalid day"; goto error; + + if (yyDay > h[yyMonth - 1]) { + errMsg = "invalid day"; + goto error; } } } if (info->flags & CLF_DAYOFYEAR) { - if ( yydate.dayOfYear < 1 - || yydate.dayOfYear > daysInPriorMonths[IsGregorianLeapYear(&yydate)][12] ) { - errMsg = "invalid day of year"; errCode = "day of year"; goto error; + if (yydate.dayOfYear < 1 + || yydate.dayOfYear > daysInPriorMonths[IsGregorianLeapYear(&yydate)][12]) { + errMsg = "invalid day of year"; + errCode = "day of year"; + goto error; } } /* mmdd !~ ddd */ if ((info->flags & (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH)) - == (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH)) { + == (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH)) { if (!tempCpyFlg) { memcpy(&temp, &yydate, sizeof(temp)); tempCpyFlg = 1; } GetJulianDayFromEraYearDay(&temp, GREGORIAN_CHANGE_DATE); if (temp.julianDay != yydate.julianDay) { - errMsg = "ambiguous day"; errCode = "day"; goto error; + errMsg = "ambiguous day"; + errCode = "day"; + goto error; } } if (info->flags & CLF_TIME) { /* hour */ - if ( yyHour < 0 || yyHour > ((yyMeridian == MER24) ? 23 : 12) ) { - errMsg = "invalid time (hour)"; errCode = "hour"; goto error; + if (yyHour < 0 || yyHour > ((yyMeridian == MER24) ? 23 : 12)) { + errMsg = "invalid time (hour)"; + errCode = "hour"; + goto error; } /* minutes */ - if ( yyMinutes < 0 || yyMinutes > 59 ) { - errMsg = "invalid time (minutes)"; errCode = "minutes"; goto error; + if (yyMinutes < 0 || yyMinutes > 59) { + errMsg = "invalid time (minutes)"; + errCode = "minutes"; + goto error; } /* oldscan could return secondOfDay (parsedTime) -1 by invalid time (ex.: 25:00:00) */ - if ( yySeconds < 0 || yySeconds > 59 || yySecondOfDay <= -1 ) { - errMsg = "invalid time"; errCode = "seconds"; goto error; + if (yySeconds < 0 || yySeconds > 59 || yySecondOfDay <= -1) { + errMsg = "invalid time"; + errCode = "seconds"; + goto error; } } @@ -3944,9 +3911,10 @@ ClockValidDate( * should have valid localSeconds (was not invalidated to TCL_INV_SECONDS), * so if it was invalidated - invalid time, outside the time-zone (in DST-hole) */ - if ( yydate.localSeconds == TCL_INV_SECONDS ) { + if (yydate.localSeconds == TCL_INV_SECONDS) { errMsg = "invalid time (does not exist in this time-zone)"; - errCode = "out-of-time"; goto error; + errCode = "out-of-time"; + goto error; } } @@ -3958,15 +3926,17 @@ ClockValidDate( } GetYearWeekDay(&temp, GREGORIAN_CHANGE_DATE); if (temp.dayOfWeek != yyDayOfWeek) { - errMsg = "invalid day of week"; errCode = "day of week"; goto error; + errMsg = "invalid day of week"; + errCode = "day of week"; + goto error; } } return TCL_OK; error: - Tcl_SetObjResult(opts->interp, - Tcl_ObjPrintf("unable to convert input string: %s", errMsg)); + Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf( + "unable to convert input string: %s", errMsg)); Tcl_SetErrorCode(opts->interp, "CLOCK", "invInpStr", errCode, (char *)NULL); return TCL_ERROR; } @@ -3988,13 +3958,13 @@ ClockValidDate( int ClockFreeScan( - DateInfo *info, /* Date fields used for parsing & converting + DateInfo *info, /* Date fields used for parsing & converting * simultaneously a yy-parse structure of the * TclClockFreeScan */ Tcl_Obj *strObj, /* String containing the time to scan */ ClockFmtScnCmdArgs *opts) /* Command options */ { - Tcl_Interp *interp = opts->interp; + Tcl_Interp *interp = opts->interp; ClockClientData *dataPtr = (ClockClientData *)opts->clientData; int ret = TCL_ERROR; @@ -4011,9 +3981,10 @@ ClockFreeScan( if (TclClockFreeScan(interp, info) != TCL_OK) { Tcl_Obj *msg; + TclNewObj(msg); Tcl_AppendPrintfToObj(msg, "unable to convert date-time string \"%s\": %s", - TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp))); + TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp))); Tcl_SetObjResult(interp, msg); goto done; } @@ -4046,8 +4017,9 @@ ClockFreeScan( Tcl_Obj *tzObjStor = NULL; int minEast = -yyTimezone; int dstFlag = 1 - yyDSTmode; + tzObjStor = ClockFormatNumericTimeZone( - 60 * minEast + 3600 * dstFlag); + 60 * minEast + 3600 * dstFlag); Tcl_IncrRefCount(tzObjStor); opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, tzObjStor); @@ -4056,7 +4028,7 @@ ClockFreeScan( } else { /* simplest case - GMT / UTC */ opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, - dataPtr->literals[LIT_GMT]); + dataPtr->literals[LIT_GMT]); } if (opts->timezoneObj == NULL) { goto done; @@ -4071,7 +4043,7 @@ ClockFreeScan( * For freescan apply validation rules (stage 1) before mixed with * relative time (otherwise always valid recalculated date & time). */ - if ( (opts->flags & CLF_VALIDATE) ) { + if ((opts->flags & CLF_VALIDATE)) { if (ClockValidDate(info, opts, CLF_VALIDATE_S1) != TCL_OK) { goto done; } @@ -4084,24 +4056,17 @@ ClockFreeScan( if ((info->flags & (CLF_TIME|CLF_HAVEDATE)) == CLF_HAVEDATE) { yySecondOfDay = 0; info->flags |= CLF_ASSEMBLE_SECONDS; - } - else - if (info->flags & CLF_TIME) { + } else if (info->flags & CLF_TIME) { yySecondOfDay = ToSeconds(yyHour, yyMinutes, - yySeconds, yyMeridian); + yySeconds, yyMeridian); info->flags |= CLF_ASSEMBLE_SECONDS; - } - else - if ( (info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK + } else if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK || (info->flags & CLF_ORDINALMONTH) - || ( (info->flags & CLF_RELCONV) - && ( yyRelMonth != 0 - || yyRelDay != 0 ) ) - ) { + || ((info->flags & CLF_RELCONV) + && (yyRelMonth != 0 || yyRelDay != 0))) { yySecondOfDay = 0; info->flags |= CLF_ASSEMBLE_SECONDS; - } - else { + } else { yySecondOfDay = yydate.localSeconds % SECONDS_PER_DAY; } @@ -4113,8 +4078,7 @@ ClockFreeScan( /* Free scanning completed - date ready */ -done: - + done: return ret; } @@ -4134,19 +4098,16 @@ done: */ int ClockCalcRelTime( - DateInfo *info) /* Date fields used for converting */ + DateInfo *info) /* Date fields used for converting */ { - int prevDayOfWeek = yyDayOfWeek; /* preserve unchanged day of week */ /* * Because some calculations require in-between conversion of the * julian day, we can repeat this processing multiple times */ -repeat_rel: - + repeat_rel: if (info->flags & CLF_RELCONV) { - /* * Relative conversion normally possible in UTC time only, because * of possible wrong local time increment if ignores in-between DST-hole. @@ -4192,7 +4153,6 @@ repeat_rel: /* add days (or other parts aligned to days) */ if (yyRelDay) { - /* assemble julianDay using new year, month, etc. */ if (info->flags & CLF_ASSEMBLE_JULIANDAY) { GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE); @@ -4202,7 +4162,6 @@ repeat_rel: /* julianDay was changed, on demand (lazy) extract year, month, etc. again */ info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS; - yyRelDay = 0; } @@ -4213,7 +4172,6 @@ repeat_rel: /* if seconds increment outside of current date, increment day */ if (newSecs / SECONDS_PER_DAY != yySecondOfDay / SECONDS_PER_DAY) { - yyRelDay += newSecs / SECONDS_PER_DAY; yySecondOfDay = 0; yyRelSeconds = newSecs % SECONDS_PER_DAY; @@ -4268,7 +4226,6 @@ repeat_rel: */ if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK) { - /* restore scanned day of week */ yyDayOfWeek = prevDayOfWeek; @@ -4280,7 +4237,7 @@ repeat_rel: yydate.isBce = 0; yydate.julianDay = WeekdayOnOrBefore(yyDayOfWeek, yydate.julianDay + 6) - + 7 * yyDayOrdinal; + + 7 * yyDayOrdinal; if (yyDayOrdinal > 0) { yydate.julianDay -= 7; } @@ -4325,6 +4282,7 @@ ClockWeekdaysOffs( /* resulting day of week */ { int day = (offs % 7); + /* compiler fix for negative offs - wrap (0, -1) -> (-1, 6) */ if (day < 0) { day = 7 + day; @@ -4335,13 +4293,14 @@ ClockWeekdaysOffs( /* adjust if we start from a weekend */ if (dayOfWeek > 5) { int adj = 5 - dayOfWeek; + offs += adj; resDayOfWeek += adj; } /* adjust if we end up on a weekend */ if (resDayOfWeek > 5) { - offs += 2; + offs += 2; } return offs; @@ -4392,19 +4351,19 @@ ClockWeekdaysOffs( int ClockAddObjCmd( - void *clientData, /* Client data containing literal pool */ + void *clientData, /* Client data containing literal pool */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter values */ { static const char *syntax = "clock add clockval|-now ?number units?..." - "?-gmt boolean? " - "?-locale LOCALE? ?-timezone ZONE?"; + "?-gmt boolean? " + "?-locale LOCALE? ?-timezone ZONE?"; ClockClientData *dataPtr = (ClockClientData *)clientData; int ret; ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */ - DateInfo yy; /* Common structure used for parsing */ - DateInfo *info = &yy; + DateInfo yy; /* Common structure used for parsing */ + DateInfo *info = &yy; /* add "week" to units also (because otherwise ambiguous) */ static const char *const units[] = { @@ -4459,14 +4418,13 @@ ClockAddObjCmd( continue; } /* get unit */ - if (Tcl_GetIndexFromObj(interp, objv[i+1], units, "unit", 0, + if (Tcl_GetIndexFromObj(interp, objv[i + 1], units, "unit", 0, &unitIndex) != TCL_OK) { goto done; } if (TclHasInternalRep(objv[i], &tclBignumType) - || offs > (unitIndex < CLC_ADD_HOURS ? 0x7fffffff : TCL_MAX_SECONDS) - || offs < (unitIndex < CLC_ADD_HOURS ? -0x7fffffff : TCL_MIN_SECONDS) - ) { + || offs > (unitIndex < CLC_ADD_HOURS ? 0x7fffffff : TCL_MAX_SECONDS) + || offs < (unitIndex < CLC_ADD_HOURS ? -0x7fffffff : TCL_MIN_SECONDS)) { Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]); goto done; } @@ -4480,15 +4438,13 @@ ClockAddObjCmd( * correct date info, because the date may be changed, * so refresh it now */ - if ( (info->flags & CLF_RELCONV) - && ( unitIndex == CLC_ADD_WEEKDAYS - /* some months can be shorter as another */ - || yyRelMonth || yyRelDay - /* day changed */ - || yySeconds + yyRelSeconds > SECONDS_PER_DAY - || yySeconds + yyRelSeconds < 0 - ) - ) { + if ((info->flags & CLF_RELCONV) + && (unitIndex == CLC_ADD_WEEKDAYS + /* some months can be shorter as another */ + || yyRelMonth || yyRelDay + /* day changed */ + || yySeconds + yyRelSeconds > SECONDS_PER_DAY + || yySeconds + yyRelSeconds < 0)) { if (ClockCalcRelTime(info) != TCL_OK) { goto done; } @@ -4542,14 +4498,11 @@ ClockAddObjCmd( ret = ClockScanCommit(&yy, &opts); -done: - + done: TclUnsetObjRef(yy.date.tzName); - if (ret != TCL_OK) { return ret; } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds)); return TCL_OK; } @@ -4633,7 +4586,7 @@ ClockSafeCatchCmd( return Tcl_CatchObjCmd(NULL, interp, objc, objv); } - statePtr = (InterpState *)Tcl_SaveInterpState(interp, 0); + statePtr = (InterpState *) Tcl_SaveInterpState(interp, 0); if (!statePtr->errorInfo) { /* todo: avoid traced get of errorInfo here */ TclInitObjRef(statePtr->errorInfo, -- cgit v0.12 From 8ff9ba3446bccf8007bf64cc536aaad551049333 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 12 Apr 2024 09:46:25 +0000 Subject: Fix panic "loop in ConvertLocalToUTCUsingTable", introduced by previous commit. Some further code cleanup --- generic/tclClock.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index acb5349..5c428d2 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -2033,7 +2033,7 @@ ConvertLocalToUTCUsingTable( } for (i = 0; i < nHave; ++i) { if (have[i].tzOffset == fields->tzOffset) { - break; + goto found; } } if (nHave == 8) { @@ -2044,6 +2044,7 @@ ConvertLocalToUTCUsingTable( fields->seconds = fields->localSeconds - fields->tzOffset; } + found: fields->tzOffset = have[i].tzOffset; fields->seconds = fields->localSeconds - fields->tzOffset; TclSetObjRef(fields->tzName, have[i].tzName); @@ -3080,7 +3081,7 @@ ThreadSafeLocalTime( * Get a thread-local buffer to hold the returned time. */ - struct tm *tmPtr = (struct tm *) Tcl_GetThreadData(&tmKey, sizeof(struct tm)); + struct tm *tmPtr = (struct tm *)Tcl_GetThreadData(&tmKey, sizeof(struct tm)); #ifdef HAVE_LOCALTIME_R tmPtr = localtime_r(timePtr, tmPtr); #else @@ -3668,7 +3669,7 @@ ClockScanObjCmd( } /* Apply remaining validation rules, if expected */ - if ((opts.flags & CLF_VALIDATE)) { + if (opts.flags & CLF_VALIDATE) { ret = ClockValidDate(&yy, &opts, opts.flags & CLF_VALIDATE); if (ret != TCL_OK) { goto done; @@ -4043,7 +4044,7 @@ ClockFreeScan( * For freescan apply validation rules (stage 1) before mixed with * relative time (otherwise always valid recalculated date & time). */ - if ((opts->flags & CLF_VALIDATE)) { + if (opts->flags & CLF_VALIDATE) { if (ClockValidDate(info, opts, CLF_VALIDATE_S1) != TCL_OK) { goto done; } @@ -4586,7 +4587,7 @@ ClockSafeCatchCmd( return Tcl_CatchObjCmd(NULL, interp, objc, objv); } - statePtr = (InterpState *) Tcl_SaveInterpState(interp, 0); + statePtr = (InterpState *)Tcl_SaveInterpState(interp, 0); if (!statePtr->errorInfo) { /* todo: avoid traced get of errorInfo here */ TclInitObjRef(statePtr->errorInfo, -- cgit v0.12 From 0d3a249b6bc3dad80328edff7b09b31f10ade99a Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Apr 2024 13:25:25 +0000 Subject: More cleaning up, notably no more symbols starting with _ as they're a reserved 'namespace' --- generic/tclClock.c | 268 ++++++++++++++++++++++++------------------------ generic/tclClockFmt.c | 178 ++++++++++++++++++-------------- generic/tclDate.h | 116 ++++++++++++--------- generic/tclStrIdxTree.c | 2 +- 4 files changed, 306 insertions(+), 258 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 5c428d2..722aba7 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -76,7 +76,7 @@ static int ConvertUTCToLocalUsingTable(Tcl_Interp *, Tcl_WideInt *rangesVal); static int ConvertUTCToLocalUsingC(Tcl_Interp *, TclDateFields *, int); -static int ConvertLocalToUTC(void *clientData, Tcl_Interp *, +static int ConvertLocalToUTC(ClockClientData *, Tcl_Interp *, TclDateFields *, Tcl_Obj *timezoneObj, int); static int ConvertLocalToUTCUsingTable(Tcl_Interp *, TclDateFields *, int, Tcl_Obj *const[], @@ -91,7 +91,7 @@ static void GetMonthDay(TclDateFields *); static Tcl_WideInt WeekdayOnOrBefore(int, Tcl_WideInt); static Tcl_ObjCmdProc ClockClicksObjCmd; static Tcl_ObjCmdProc ClockConvertlocaltoutcObjCmd; -static int ClockGetDateFields(void *clientData, +static int ClockGetDateFields(ClockClientData *, Tcl_Interp *interp, TclDateFields *fields, Tcl_Obj *timezoneObj, int changeover); static Tcl_ObjCmdProc ClockGetdatefieldsObjCmd; @@ -197,7 +197,8 @@ TclClockInit( data->refCount = 0; data->literals = (Tcl_Obj **) ckalloc(LIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < LIT__END; ++i) { - TclInitObjRef(data->literals[i], Tcl_NewStringObj(Literals[i], -1)); + TclInitObjRef(data->literals[i], Tcl_NewStringObj( + Literals[i], TCL_AUTO_LENGTH)); } data->mcLiterals = NULL; data->mcLitIdxs = NULL; @@ -374,19 +375,20 @@ ClockDeleteCmdProc( * * Used to store previously used/cached time zone (makes it reusable). * - * This enables faster switch between time zones (e. g. to convert from one to another). + * This enables faster switch between time zones (e. g. to convert from + * one to another). * * Results: * None. * *---------------------------------------------------------------------- */ - static inline void SavePrevTimezoneObj( ClockClientData *dataPtr) /* Client data containing literal pool */ { Tcl_Obj *timezoneObj = dataPtr->lastSetupTimeZone; + if (timezoneObj && timezoneObj != dataPtr->prevSetupTimeZone) { TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, dataPtr->lastSetupTimeZoneUnnorm); TclSetObjRef(dataPtr->prevSetupTimeZone, timezoneObj); @@ -686,19 +688,20 @@ Tcl_Obj * ClockMCDict( ClockFmtScnCmdArgs *opts) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; /* if dict not yet retrieved */ if (opts->mcDictObj == NULL) { /* if locale was not yet used */ if (!(opts->flags & CLF_LOCALE_USED)) { - opts->localeObj = NormLocaleObj((ClockClientData *) opts->clientData, opts->interp, + opts->localeObj = NormLocaleObj(dataPtr, opts->interp, opts->localeObj, &opts->mcDictObj); if (opts->localeObj == NULL) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "locale not specified and no default locale set", -1)); + "locale not specified and no default locale set", + TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "badOption", (char *)NULL); return NULL; } @@ -711,8 +714,8 @@ ClockMCDict( dataPtr->mcLiterals = (Tcl_Obj **) ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { - TclInitObjRef(dataPtr->mcLiterals[i], - Tcl_NewStringObj(MsgCtLiterals[i], -1)); + TclInitObjRef(dataPtr->mcLiterals[i], Tcl_NewStringObj( + MsgCtLiterals[i], TCL_AUTO_LENGTH)); } } } @@ -795,7 +798,6 @@ ClockMCGet( ClockFmtScnCmdArgs *opts, int mcKey) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; Tcl_Obj *valObj = NULL; if (opts->mcDictObj == NULL) { @@ -806,8 +808,7 @@ ClockMCGet( } Tcl_DictObjGet(opts->interp, opts->mcDictObj, - dataPtr->mcLiterals[mcKey], &valObj); - + opts->dataPtr->mcLiterals[mcKey], &valObj); return valObj; /* or NULL in obscure case if Tcl_DictObjGet failed */ } @@ -831,7 +832,7 @@ ClockMCGetIdx( ClockFmtScnCmdArgs *opts, int mcKey) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; Tcl_Obj *valObj = NULL; if (opts->mcDictObj == NULL) { @@ -874,7 +875,7 @@ ClockMCSetIdx( int mcKey, Tcl_Obj *valObj) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; if (opts->mcDictObj == NULL) { ClockMCDict(opts); @@ -890,7 +891,7 @@ ClockMCSetIdx( dataPtr->mcLitIdxs = (Tcl_Obj **) ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { TclInitObjRef(dataPtr->mcLitIdxs[i], - Tcl_NewStringObj(MsgCtLitIdxs[i], -1)); + Tcl_NewStringObj(MsgCtLitIdxs[i], TCL_AUTO_LENGTH)); } } @@ -909,7 +910,7 @@ TimezoneLoaded( /* mark GMT zone loaded */ if (dataPtr->gmtSetupTimeZone == NULL) { TclSetObjRef(dataPtr->gmtSetupTimeZone, - dataPtr->literals[LIT_GMT]); + dataPtr->literals[LIT_GMT]); } TclSetObjRef(dataPtr->gmtSetupTimeZoneUnnorm, tzUnnormObj); return; @@ -1175,11 +1176,10 @@ ClockConfigureObjCmd( static inline Tcl_Obj * ClockGetTZData( - void *clientData, /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *timezoneObj) /* Name of the timezone */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *ret, **out = NULL; /* if cached (if already setup this one) */ @@ -1245,11 +1245,9 @@ ClockGetTZData( static Tcl_Obj * ClockGetSystemTimeZone( - void *clientData, /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr, /* Pointer to literal pool, etc. */ Tcl_Interp *interp) /* Tcl interpreter */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; - /* if known (cached and same epoch) - return now */ if (dataPtr->systemTimeZone != NULL && dataPtr->lastTZEpoch == TzsetIfNecessary()) { @@ -1284,11 +1282,10 @@ ClockGetSystemTimeZone( Tcl_Obj * ClockSetupTimeZone( - void *clientData, /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr, /* Pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *timezoneObj) { - ClockClientData *dataPtr = (ClockClientData *)clientData; int loaded; Tcl_Obj *callargs[2]; @@ -1401,12 +1398,12 @@ ClockFormatNumericTimeZone( static int ClockConvertlocaltoutcObjCmd( - void *clientData, /* Client data */ + void *clientData, /* Literal table */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { - ClockClientData *data = (ClockClientData *)clientData; + ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *secondsObj; Tcl_Obj *dict; int changeover; @@ -1424,18 +1421,18 @@ ClockConvertlocaltoutcObjCmd( return TCL_ERROR; } dict = objv[1]; - if (Tcl_DictObjGet(interp, dict, data->literals[LIT_LOCALSECONDS], + if (Tcl_DictObjGet(interp, dict, dataPtr->literals[LIT_LOCALSECONDS], &secondsObj)!= TCL_OK) { return TCL_ERROR; } if (secondsObj == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not " - "found in dictionary", -1)); + "found in dictionary", TCL_AUTO_LENGTH)); return TCL_ERROR; } if ((TclGetWideIntFromObj(interp, secondsObj, &fields.localSeconds) != TCL_OK) || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) - || ConvertLocalToUTC(clientData, interp, &fields, objv[2], changeover)) { + || ConvertLocalToUTC(dataPtr, interp, &fields, objv[2], changeover)) { return TCL_ERROR; } @@ -1449,7 +1446,7 @@ ClockConvertlocaltoutcObjCmd( created = 1; Tcl_IncrRefCount(dict); } - status = Tcl_DictObjPut(interp, dict, data->literals[LIT_SECONDS], + status = Tcl_DictObjPut(interp, dict, dataPtr->literals[LIT_SECONDS], Tcl_NewWideIntObj(fields.seconds)); if (status == TCL_OK) { Tcl_SetObjResult(interp, dict); @@ -1498,8 +1495,8 @@ ClockGetdatefieldsObjCmd( { TclDateFields fields; Tcl_Obj *dict; - ClockClientData *data = (ClockClientData *)clientData; - Tcl_Obj *const *lit = data->literals; + ClockClientData *dataPtr = (ClockClientData *)clientData; + Tcl_Obj *const *lit = dataPtr->literals; int changeover; fields.tzName = NULL; @@ -1529,7 +1526,7 @@ ClockGetdatefieldsObjCmd( /* Extract fields */ - if (ClockGetDateFields(clientData, interp, &fields, objv[2], + if (ClockGetDateFields(dataPtr, interp, &fields, objv[2], changeover) != TCL_OK) { return TCL_ERROR; } @@ -1588,7 +1585,7 @@ ClockGetdatefieldsObjCmd( int ClockGetDateFields( - void *clientData, /* Client data of the interpreter */ + ClockClientData *dataPtr, /* Literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Pointer to result fields, where * fields->seconds contains date to extract */ @@ -1599,7 +1596,7 @@ ClockGetDateFields( * Convert UTC time to local. */ - if (ConvertUTCToLocal(clientData, interp, fields, timezoneObj, + if (ConvertUTCToLocal(dataPtr, interp, fields, timezoneObj, changeover) != TCL_OK) { return TCL_ERROR; } @@ -1609,7 +1606,7 @@ ClockGetDateFields( */ ClockExtractJDAndSODFromSeconds(fields->julianDay, fields->secondOfDay, - fields->localSeconds); + fields->localSeconds); /* * Convert to Julian or Gregorian calendar. @@ -1657,7 +1654,7 @@ FetchEraField( } if (value == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "expected key(s) not found in dictionary", -1)); + "expected key(s) not found in dictionary", TCL_AUTO_LENGTH)); return TCL_ERROR; } return Tcl_GetIndexFromObj(interp, value, eras, "era", TCL_EXACT, storePtr); @@ -1677,7 +1674,7 @@ FetchIntField( } if (value == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "expected key(s) not found in dictionary", -1)); + "expected key(s) not found in dictionary", TCL_AUTO_LENGTH)); return TCL_ERROR; } return TclGetIntFromObj(interp, value, storePtr); @@ -1854,13 +1851,12 @@ ClockGetjuliandayfromerayearweekdayObjCmd( static int ConvertLocalToUTC( - void *clientData, /* Client data of the interpreter */ + ClockClientData *dataPtr, /* Literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *timezoneObj, /* Time zone */ int changeover) /* Julian Day of the Gregorian transition */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *tzdata; /* Time zone data */ Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ @@ -1905,7 +1901,7 @@ ConvertLocalToUTC( * Unpack the tz data. */ - tzdata = ClockGetTZData(clientData, interp, timezoneObj); + tzdata = ClockGetTZData(dataPtr, interp, timezoneObj); if (tzdata == NULL) { return TCL_ERROR; } @@ -2123,7 +2119,7 @@ ConvertLocalToUTCUsingC( if (localErrno != 0 || (fields->seconds == -1 && timeVal.tm_yday == -1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "time value too large/small to represent", -1)); + "time value too large/small to represent", TCL_AUTO_LENGTH)); return TCL_ERROR; } return TCL_OK; @@ -2147,13 +2143,12 @@ ConvertLocalToUTCUsingC( int ConvertUTCToLocal( - void *clientData, /* Client data of the interpreter */ + ClockClientData *dataPtr, /* Literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *timezoneObj, /* Time zone */ int changeover) /* Julian Day of the Gregorian transition */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *tzdata; /* Time zone data */ Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ @@ -2166,7 +2161,7 @@ ConvertUTCToLocal( if (dataPtr->gmtTZName == NULL) { Tcl_Obj *tzName; - tzdata = ClockGetTZData(clientData, interp, timezoneObj); + tzdata = ClockGetTZData(dataPtr, interp, timezoneObj); if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK || Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) { return TCL_ERROR; @@ -2201,7 +2196,7 @@ ConvertUTCToLocal( * Unpack the tz data. */ - tzdata = ClockGetTZData(clientData, interp, timezoneObj); + tzdata = ClockGetTZData(dataPtr, interp, timezoneObj); if (tzdata == NULL) { return TCL_ERROR; } @@ -2346,7 +2341,7 @@ ConvertUTCToLocalUsingC( tock = (time_t) fields->seconds; if ((Tcl_WideInt) tock != fields->seconds) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "number too large to represent as a Posix time", -1)); + "number too large to represent as a Posix time", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", (char *)NULL); return TCL_ERROR; } @@ -2355,7 +2350,7 @@ ConvertUTCToLocalUsingC( if (timeVal == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "localtime failed (clock value may be too " - "large/small to represent)", -1)); + "large/small to represent)", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", (char *)NULL); return TCL_ERROR; } @@ -3049,7 +3044,8 @@ ClockGetenvObjCmd( varName = TclGetString(objv[1]); varValue = getenv(varName); if (varValue != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + varValue, TCL_AUTO_LENGTH)); } #endif return TCL_OK; @@ -3243,12 +3239,12 @@ ClockMicrosecondsObjCmd( static inline void ClockInitFmtScnArgs( - void *clientData, + ClockClientData *dataPtr, Tcl_Interp *interp, ClockFmtScnCmdArgs *opts) { memset(opts, 0, sizeof(*opts)); - opts->clientData = clientData; + opts->dataPtr = dataPtr; opts->interp = interp; } @@ -3270,22 +3266,24 @@ ClockInitFmtScnArgs( *----------------------------------------------------------------------------- */ -#define CLC_FMT_ARGS (0) -#define CLC_SCN_ARGS (1 << 0) -#define CLC_ADD_ARGS (1 << 1) +typedef enum ClockOperation { + CLC_OP_FMT = 0, /* Doing [clock format] */ + CLC_OP_SCN, /* Doing [clock scan] */ + CLC_OP_ADD /* Doing [clock add] */ +} ClockOperation; static int ClockParseFmtScnArgs( ClockFmtScnCmdArgs *opts, /* Result vector: format, locale, timezone... */ - TclDateFields *date, /* Extracted date-time corresponding base + TclDateFields *date, /* Extracted date-time corresponding base * (by scan or add) resp. clockval (by format) */ int objc, /* Parameter count */ Tcl_Obj *const objv[], /* Parameter vector */ - int flags, /* Flags, differentiates between format, scan, add */ + ClockOperation operation, /* What operation are we doing: format, scan, add */ const char *syntax) /* Syntax of the current command */ { Tcl_Interp *interp = opts->interp; - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; int gmtFlag = 0; static const char *const options[] = { "-base", "-format", "-gmt", "-locale", "-timezone", "-validate", NULL @@ -3299,13 +3297,13 @@ ClockParseFmtScnArgs( int i, baseIdx; Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */ - if (flags & CLC_SCN_ARGS) { + if (operation == CLC_OP_SCN) { /* default flags (from configure) */ - opts->flags |= dataPtr->defFlags & (CLF_VALIDATE); + opts->flags |= dataPtr->defFlags & CLF_VALIDATE; } else { /* clock value (as current base) */ opts->baseObj = objv[(baseIdx = 1)]; - saw |= (1 << CLC_ARGS_BASE); + saw |= 1 << CLC_ARGS_BASE; } /* @@ -3314,7 +3312,7 @@ ClockParseFmtScnArgs( for (i = 2; i < objc; i+=2) { /* bypass integers (offsets) by "clock add" */ - if (flags & CLC_ADD_ARGS) { + if (operation == CLC_OP_ADD) { Tcl_WideInt num; if (TclGetWideIntFromObj(NULL, objv[i], &num) == TCL_OK) { @@ -3328,8 +3326,7 @@ ClockParseFmtScnArgs( } /* if already specified */ if (saw & (1 << optionIndex)) { - if (!(flags & CLC_SCN_ARGS) - && optionIndex == CLC_ARGS_BASE) { + if (operation != CLC_OP_SCN && optionIndex == CLC_ARGS_BASE) { goto badOptionMsg; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -3339,7 +3336,7 @@ ClockParseFmtScnArgs( } switch (optionIndex) { case CLC_ARGS_FORMAT: - if (flags & CLC_ADD_ARGS) { + if (operation == CLC_OP_ADD) { goto badOptionMsg; } opts->formatObj = objv[i + 1]; @@ -3359,7 +3356,7 @@ ClockParseFmtScnArgs( opts->baseObj = objv[(baseIdx = i + 1)]; break; case CLC_ARGS_VALIDATE: - if (!(flags & CLC_SCN_ARGS)) { + if (operation != CLC_OP_SCN) { goto badOptionMsg; } else { int val; @@ -3375,7 +3372,7 @@ ClockParseFmtScnArgs( } break; } - saw |= (1 << optionIndex); + saw |= 1 << optionIndex; } /* @@ -3384,7 +3381,8 @@ ClockParseFmtScnArgs( if ((saw & (1 << CLC_ARGS_GMT)) && (saw & (1 << CLC_ARGS_TIMEZONE))) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot use -gmt and -timezone in same call", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "cannot use -gmt and -timezone in same call", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", (char *)NULL); return TCL_ERROR; } @@ -3394,7 +3392,7 @@ ClockParseFmtScnArgs( || TclGetString(opts->timezoneObj) == NULL || opts->timezoneObj->length == 0) { /* If time zone not specified use system time zone */ - opts->timezoneObj = ClockGetSystemTimeZone(opts->clientData, interp); + opts->timezoneObj = ClockGetSystemTimeZone(dataPtr, interp); if (opts->timezoneObj == NULL) { return TCL_ERROR; } @@ -3402,7 +3400,7 @@ ClockParseFmtScnArgs( /* Setup timezone (normalize object if needed and load TZ on demand) */ - opts->timezoneObj = ClockSetupTimeZone(opts->clientData, interp, opts->timezoneObj); + opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, opts->timezoneObj); if (opts->timezoneObj == NULL) { return TCL_ERROR; } @@ -3413,7 +3411,7 @@ ClockParseFmtScnArgs( Tcl_Obj *baseObj = opts->baseObj; /* bypass integer recognition if looks like option "-now" */ - if ((baseObj->bytes && baseObj->length == 4 && *(baseObj->bytes + 1) == 'n') + if ((baseObj->bytes && baseObj->length == 4 && baseObj->bytes[1] == 'n') || TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK) { /* we accept "-now" as current date-time */ static const char *const nowOpts[] = { @@ -3471,7 +3469,7 @@ ClockParseFmtScnArgs( } else { /* extact fields from base */ date->seconds = baseVal; - if (ClockGetDateFields(opts->clientData, interp, date, opts->timezoneObj, + if (ClockGetDateFields(dataPtr, interp, date, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { /* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */ return TCL_ERROR; @@ -3522,7 +3520,6 @@ ClockFormatObjCmd( Tcl_Obj *const objv[]) /* Parameter values */ { ClockClientData *dataPtr = (ClockClientData *)clientData; - static const char *syntax = "clock format clockval|-now " "?-format string? " "?-gmt boolean? " @@ -3544,9 +3541,9 @@ ClockFormatObjCmd( * Extract values for the keywords. */ - ClockInitFmtScnArgs(clientData, interp, &opts); + ClockInitFmtScnArgs(dataPtr, interp, &opts); ret = ClockParseFmtScnArgs(&opts, &dateFmt.date, objc, objv, - CLC_FMT_ARGS, "-format, -gmt, -locale, or -timezone"); + CLC_OP_FMT, "-format, -gmt, -locale, or -timezone"); if (ret != TCL_OK) { goto done; } @@ -3591,6 +3588,7 @@ ClockScanObjCmd( int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter values */ { + ClockClientData *dataPtr = (ClockClientData *)clientData; static const char *syntax = "clock scan string " "?-base seconds? " "?-format string? " @@ -3614,9 +3612,9 @@ ClockScanObjCmd( * Extract values for the keywords. */ - ClockInitFmtScnArgs(clientData, interp, &opts); + ClockInitFmtScnArgs(dataPtr, interp, &opts); ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv, - CLC_SCN_ARGS, "-base, -format, -gmt, -locale, -timezone or -validate"); + CLC_OP_SCN, "-base, -format, -gmt, -locale, -timezone or -validate"); if (ret != TCL_OK) { goto done; } @@ -3632,7 +3630,7 @@ ClockScanObjCmd( * it's not localized. */ if (opts.localeObj != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "legacy [clock scan] does not support -locale", -1)); + "legacy [clock scan] does not support -locale", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", (char *)NULL); ret = TCL_ERROR; goto done; @@ -3722,13 +3720,11 @@ ClockScanCommit( /* some overflow checks */ if (info->flags & CLF_JULIANDAY) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - double curJDN = (double)yydate.julianDay + ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY; - if (curJDN > dataPtr->maxJDN) { + if (curJDN > opts->dataPtr->maxJDN) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "requested date too large to represent", -1)); + "requested date too large to represent", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL); return TCL_ERROR; } @@ -3736,15 +3732,15 @@ ClockScanCommit( /* Local seconds to UTC (stored in yydate.seconds) */ - if (info->flags & (CLF_ASSEMBLE_SECONDS)) { + if (info->flags & CLF_ASSEMBLE_SECONDS) { yydate.localSeconds = -210866803200LL + (SECONDS_PER_DAY * yydate.julianDay) + (yySecondOfDay % SECONDS_PER_DAY); } - if (info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)) { - if (ConvertLocalToUTC(opts->clientData, opts->interp, &yydate, + if (info->flags & (CLF_ASSEMBLE_SECONDS | CLF_LOCALSEC)) { + if (ConvertLocalToUTC(opts->dataPtr, opts->interp, &yydate, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { return TCL_ERROR; } @@ -3780,7 +3776,7 @@ ClockValidDate( const char *errMsg = "", *errCode = ""; TclDateFields temp; int tempCpyFlg = 0; - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; #if 0 printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %d, " @@ -3796,7 +3792,7 @@ ClockValidDate( opts->flags &= ~CLF_VALIDATE_S1; /* stage 1 is done */ /* first year (used later in hath / daysInPriorMonths) */ - if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR))) { + if ((info->flags & (CLF_YEAR | CLF_ISO8601YEAR))) { if ((info->flags & CLF_ISO8601YEAR)) { if (yydate.iso8601Year < dataPtr->validMinYear || yydate.iso8601Year > dataPtr->validMaxYear) { @@ -3815,8 +3811,8 @@ ClockValidDate( } else if ((info->flags & CLF_ISO8601YEAR)) { yyYear = yydate.iso8601Year; /* used to recognize leap */ } - if ((info->flags & (CLF_ISO8601YEAR|CLF_YEAR)) - == (CLF_ISO8601YEAR|CLF_YEAR)) { + if ((info->flags & (CLF_ISO8601YEAR | CLF_YEAR)) + == (CLF_ISO8601YEAR | CLF_YEAR)) { if (yyYear != yydate.iso8601Year) { errMsg = "ambiguous year"; errCode = "year"; @@ -3966,8 +3962,7 @@ ClockFreeScan( ClockFmtScnCmdArgs *opts) /* Command options */ { Tcl_Interp *interp = opts->interp; - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - + ClockClientData *dataPtr = opts->dataPtr; int ret = TCL_ERROR; /* @@ -3981,12 +3976,9 @@ ClockFreeScan( yyInput = TclGetString(strObj); if (TclClockFreeScan(interp, info) != TCL_OK) { - Tcl_Obj *msg; - - TclNewObj(msg); - Tcl_AppendPrintfToObj(msg, "unable to convert date-time string \"%s\": %s", - TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp))); - Tcl_SetObjResult(interp, msg); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "unable to convert date-time string \"%s\": %s", + TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp)))); goto done; } @@ -4054,14 +4046,13 @@ ClockFreeScan( * Assemble date, time, zone into seconds-from-epoch */ - if ((info->flags & (CLF_TIME|CLF_HAVEDATE)) == CLF_HAVEDATE) { + if ((info->flags & (CLF_TIME | CLF_HAVEDATE)) == CLF_HAVEDATE) { yySecondOfDay = 0; info->flags |= CLF_ASSEMBLE_SECONDS; } else if (info->flags & CLF_TIME) { - yySecondOfDay = ToSeconds(yyHour, yyMinutes, - yySeconds, yyMeridian); + yySecondOfDay = ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian); info->flags |= CLF_ASSEMBLE_SECONDS; - } else if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK + } else if ((info->flags & (CLF_DAYOFWEEK | CLF_HAVEDATE)) == CLF_DAYOFWEEK || (info->flags & CLF_ORDINALMONTH) || ((info->flags & CLF_RELCONV) && (yyRelMonth != 0 || yyRelDay != 0))) { @@ -4147,7 +4138,7 @@ ClockCalcRelTime( } /* on demand (lazy) assemble julianDay using new year, month, etc. */ - info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS; + info->flags |= CLF_ASSEMBLE_JULIANDAY | CLF_ASSEMBLE_SECONDS; yyRelMonth = 0; } @@ -4395,9 +4386,9 @@ ClockAddObjCmd( * Extract values for the keywords. */ - ClockInitFmtScnArgs(clientData, interp, &opts); + ClockInitFmtScnArgs(dataPtr, interp, &opts); ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv, - CLC_ADD_ARGS, "-gmt, -locale, or -timezone"); + CLC_OP_ADD, "-gmt, -locale, or -timezone"); if (ret != TCL_OK) { goto done; } @@ -4405,7 +4396,9 @@ ClockAddObjCmd( /* time together as seconds of the day */ yySecondOfDay = yySeconds = yydate.localSeconds % SECONDS_PER_DAY; /* seconds are in localSeconds (relative base date), so reset time here */ - yyHour = 0; yyMinutes = 0; yyMeridian = MER24; + yyHour = 0; + yyMinutes = 0; + yyMeridian = MER24; ret = TCL_ERROR; @@ -4642,58 +4635,69 @@ ClockSafeCatchCmd( #define wcscmp strcmp #define wcscpy strcpy #endif +#define TZ_INIT_MARKER ((WCHAR *) INT2PTR(-1)) static size_t TzsetIfNecessary(void) { - static WCHAR* tzWas = (WCHAR *)INT2PTR(-1); /* Previous value of TZ, protected by - * clockMutex. */ - static long tzLastRefresh = 0; /* Used for latency before next refresh */ - static size_t tzWasEpoch = 0; /* Epoch, signals that TZ changed */ - static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling, - that TZ changed via TCL */ - const WCHAR *tzIsNow; /* Current value of TZ */ + typedef struct ClockTzStatic { + WCHAR *was; /* Previous value of TZ. */ + long lastRefresh; /* Used for latency before next refresh. */ + size_t epoch; /* Epoch, signals that TZ changed. */ + size_t envEpoch; /* Last env epoch, for faster signaling, + * that TZ changed via TCL */ + } ClockTzStatic; + static ClockTzStatic tz = { /* Global timezone info; protected by + * clockMutex.*/ + TZ_INIT_MARKER, 0, 0, 0 + }; + const WCHAR *tzNow; /* Current value of TZ. */ + Tcl_Time now; /* Current time. */ + size_t epoch; /* The tz.epoch that the TZ was read at. */ /* * Prevent performance regression on some platforms by resolving of system time zone: * small latency for check whether environment was changed (once per second) * no latency if environment was changed with tcl-env (compare both epoch values) */ - Tcl_Time now; + Tcl_GetTime(&now); - if (now.sec == tzLastRefresh && tzEnvEpoch == TclEnvEpoch) { - return tzWasEpoch; + if (now.sec == tz.lastRefresh && tz.envEpoch == TclEnvEpoch) { + return tz.epoch; } - tzEnvEpoch = TclEnvEpoch; - tzLastRefresh = now.sec; + tz.envEpoch = TclEnvEpoch; + tz.lastRefresh = now.sec; /* check in lock */ Tcl_MutexLock(&clockMutex); - tzIsNow = getenv("TCL_TZ"); - if (tzIsNow == NULL) { - tzIsNow = getenv("TZ"); + tzNow = getenv("TCL_TZ"); + if (tzNow == NULL) { + tzNow = getenv("TZ"); } - if (tzIsNow != NULL && (tzWas == NULL || tzWas == (WCHAR *)INT2PTR(-1) - || wcscmp(tzIsNow, tzWas) != 0)) { + if (tzNow != NULL && (tz.was == NULL || tz.was == TZ_INIT_MARKER + || wcscmp(tzNow, tz.was) != 0)) { tzset(); - if (tzWas != NULL && tzWas != (WCHAR *)INT2PTR(-1)) { - ckfree(tzWas); + if (tz.was != NULL && tz.was != TZ_INIT_MARKER) { + ckfree(tz.was); } - tzWas = (WCHAR *)ckalloc(sizeof(WCHAR) * (wcslen(tzIsNow) + 1)); - wcscpy(tzWas, tzIsNow); - tzWasEpoch++; - } else if (tzIsNow == NULL && tzWas != NULL) { + tz.was = (WCHAR *) + ckalloc(sizeof(WCHAR) * (wcslen(tzNow) + 1)); + wcscpy(tz.was, tzNow); + epoch = ++tz.epoch; + } else if (tzNow == NULL && tz.was != NULL) { tzset(); - if (tzWas != (WCHAR *)INT2PTR(-1)) { - ckfree(tzWas); + if (tz.was != TZ_INIT_MARKER) { + ckfree(tz.was); } - tzWas = NULL; - tzWasEpoch++; + tz.was = NULL; + epoch = ++tz.epoch; + } else { + epoch = tz.epoch; } Tcl_MutexUnlock(&clockMutex); - return tzWasEpoch; + return epoch; } /* diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 06684a6..cbb935d 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -33,6 +33,11 @@ static void ClockFrmScnFinalize(void *); */ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; + +#define IntFieldAt(info, offset) \ + ((int *) (((char *) (info)) + (offset))) +#define WideFieldAt(info, offset) \ + ((Tcl_WideInt *) (((char *) (info)) + (offset))) /* * Clock scan and format facilities. @@ -41,7 +46,7 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; /* *---------------------------------------------------------------------- * - * _str2int -- , _str2wideInt -- + * Clock_str2int, Clock_str2wideInt -- * * Fast inline-convertion of string to signed int or wide int by given * start/end. @@ -57,7 +62,7 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; */ static inline void -_str2int_no( +Clock_str2int_no( int *out, const char *p, const char *e, @@ -65,8 +70,9 @@ _str2int_no( { /* assert(e <= p + 10); */ int val = 0; + /* overflow impossible for 10 digits ("9..9"), so no needs to check at all */ - while (p < e) { /* never overflows */ + while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } if (sign < 0) { @@ -76,7 +82,7 @@ _str2int_no( } static inline void -_str2wideInt_no( +Clock_str2wideInt_no( Tcl_WideInt *out, const char *p, const char *e, @@ -84,8 +90,9 @@ _str2wideInt_no( { /* assert(e <= p + 18); */ Tcl_WideInt val = 0; + /* overflow impossible for 18 digits ("9..9"), so no needs to check at all */ - while (p < e) { /* never overflows */ + while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } if (sign < 0) { @@ -100,7 +107,7 @@ _str2wideInt_no( #endif static inline int -_str2int( +Clock_str2int( int *out, const char *p, const char *e, @@ -109,6 +116,7 @@ _str2int( int val = 0; /* overflow impossible for 10 digits ("9..9"), so no needs to check before */ const char *eNO = p + 10; + if (eNO > e) { eNO = e; } @@ -118,6 +126,7 @@ _str2int( if (sign >= 0) { while (p < e) { /* check for overflow */ int prev = val; + val = val * 10 + (*p++ - '0'); if (val / 10 < prev) { return TCL_ERROR; @@ -127,6 +136,7 @@ _str2int( val = -val; while (p < e) { /* check for overflow */ int prev = val; + val = val * 10 - (*p++ - '0'); if (val / 10 > prev) { return TCL_ERROR; @@ -138,7 +148,7 @@ _str2int( } static inline int -_str2wideInt( +Clock_str2wideInt( Tcl_WideInt *out, const char *p, const char *e, @@ -147,6 +157,7 @@ _str2wideInt( Tcl_WideInt val = 0; /* overflow impossible for 18 digits ("9..9"), so no needs to check before */ const char *eNO = p + 18; + if (eNO > e) { eNO = e; } @@ -156,6 +167,7 @@ _str2wideInt( if (sign >= 0) { while (p < e) { /* check for overflow */ Tcl_WideInt prev = val; + val = val * 10 + (*p++ - '0'); if (val / 10 < prev) { return TCL_ERROR; @@ -165,6 +177,7 @@ _str2wideInt( val = -val; while (p < e) { /* check for overflow */ Tcl_WideInt prev = val; + val = val * 10 - (*p++ - '0'); if (val / 10 > prev) { return TCL_ERROR; @@ -182,7 +195,7 @@ TclAtoWIe( const char *e, int sign) { - return _str2wideInt(out, p, e, sign); + return Clock_str2wideInt(out, p, e, sign); } #if defined(__GNUC__) || defined(__GNUG__) @@ -192,7 +205,7 @@ TclAtoWIe( /* *---------------------------------------------------------------------- * - * _itoaw -- , _witoaw -- + * Clock_itoaw, Clock_witoaw -- * * Fast inline-convertion of signed int or wide int to string, using * given padding with specified padchar and width (or without padding). @@ -206,14 +219,16 @@ TclAtoWIe( */ static inline char * -_itoaw( +Clock_itoaw( char *buf, int val, char padchar, unsigned short width) { char *p; - static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + static const int wrange[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; /* positive integer */ @@ -226,7 +241,8 @@ _itoaw( p = buf + width; *p-- = '\0'; do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val > 0); @@ -254,13 +270,15 @@ _itoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val < 0); @@ -287,18 +305,20 @@ TclItoAw( char padchar, unsigned short width) { - return _itoaw(buf, val, padchar, width); + return Clock_itoaw(buf, val, padchar, width); } static inline char * -_witoaw( +Clock_witoaw( char *buf, Tcl_WideInt val, char padchar, unsigned short width) { char *p; - static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + static const int wrange[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; /* positive integer */ @@ -306,6 +326,7 @@ _witoaw( /* check resp. recalculate width */ if (val >= 10000000000LL) { Tcl_WideInt val2 = val / 10000000000LL; + while (width <= 9 && val2 >= wrange[width]) { width++; } @@ -340,6 +361,7 @@ _witoaw( width--; if (val <= -10000000000LL) { Tcl_WideInt val2 = val / 10000000000LL; + while (width <= 9 && val2 <= -wrange[width]) { width++; } @@ -356,13 +378,15 @@ _witoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val < 0); @@ -903,7 +927,7 @@ Tcl_Obj * ClockLocalizeFormat( ClockFmtScnCmdArgs *opts) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; Tcl_Obj *valObj = NULL, *keyObj; keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj); @@ -1051,8 +1075,8 @@ DetermineGreedySearchLen( { int minLen = tok->map->minSize; int maxLen; - const char *p = yyInput + minLen, - *end = info->dateEnd; + const char *p = yyInput + minLen; + const char *end = info->dateEnd; /* if still tokens available, try to correct minimum length */ if ((tok + 1)->map) { @@ -1558,7 +1582,7 @@ ClockScnToken_DayOfWeek_Proc( } if (val > 7) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "day of week is greater than 7", -1)); + "day of week is greater than 7", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL); return TCL_ERROR; } @@ -1625,7 +1649,7 @@ ClockScnToken_LocaleERA_Proc( DateInfo *info, ClockScanToken *tok) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; int ret, val; int minLen, maxLen; @@ -1683,7 +1707,7 @@ ClockScnToken_LocaleListMatcher_Proc( } if (tok->map->offs > 0) { - *(int *)(((char *)info) + tok->map->offs) = --val; + *IntFieldAt(info, tok->map->offs) = --val; } return TCL_OK; @@ -1712,7 +1736,7 @@ ClockScnToken_JDN_Proc( while (p < end && isdigit(UCHAR(*p))) { p++; } - if (_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { + if (Clock_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1730,7 +1754,7 @@ ClockScnToken_JDN_Proc( fractJDDiv *= 10; p++; } - if (_str2int(&fractJD, s, p, 1) != TCL_OK) { + if (Clock_str2int(&fractJD, s, p, 1) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1742,7 +1766,7 @@ ClockScnToken_JDN_Proc( */ fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */ - + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv); + + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv); if (fractJD > SECONDS_PER_DAY) { fractJD %= SECONDS_PER_DAY; intJD += 1; @@ -1840,7 +1864,7 @@ ClockScnToken_TimeZone_Proc( /* try to apply new time zone */ Tcl_IncrRefCount(tzObjStor); - opts->timezoneObj = ClockSetupTimeZone(opts->clientData, opts->interp, + opts->timezoneObj = ClockSetupTimeZone(opts->dataPtr, opts->interp, tzObjStor); Tcl_DecrRefCount(tzObjStor); @@ -1890,8 +1914,8 @@ ClockScnToken_StarDate_Proc( if (p >= end || p - s < 4) { return TCL_RETURN; } - if (_str2int(&year, s, p - 3, 1) != TCL_OK - || _str2int(&fractYear, p - 3, p, 1) != TCL_OK) { + if (Clock_str2int(&year, s, p - 3, 1) != TCL_OK + || Clock_str2int(&fractYear, p - 3, p, 1) != TCL_OK) { return TCL_RETURN; } if (*p++ != '.') { @@ -1903,7 +1927,7 @@ ClockScnToken_StarDate_Proc( fractDayDiv *= 10; p++; } - if (_str2int(&fractDay, s, p, 1) != TCL_OK) { + if (Clock_str2int(&fractDay, s, p, 1) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1934,6 +1958,10 @@ ClockScnToken_StarDate_Proc( return TCL_OK; } +/* + * Descriptors for the various fields in [clock scan]. + */ + static const char *ScnSTokenMapIndex = "dmbyYHMSpJjCgGVazUsntQ"; static const ClockScanTokenMap ScnSTokenMap[] = { /* %d %e */ @@ -2142,7 +2170,7 @@ ClockGetOrParseScanFormat( fss->scnSpaceCount = 0; scnTok = tok = (ClockScanToken *) ckalloc(sizeof(*tok) * fss->scnTokC); - memset(tok, 0, sizeof(*(tok))); + memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { switch (*p) { @@ -2249,10 +2277,11 @@ ClockGetOrParseScanFormat( tokCnt++; continue; } -word_tok: + word_tok: { ClockScanToken *wordTok = tok; - if (tok > scnTok && (tok-1)->map == &ScnWordTokenMap) { + + if (tok > scnTok && (tok - 1)->map == &ScnWordTokenMap) { wordTok = tok - 1; } /* new word token */ @@ -2275,7 +2304,7 @@ word_tok: /* calculate end distance value for each tokens */ if (tok > scnTok) { unsigned endDist = 0; - ClockScanToken *prevTok = tok-1; + ClockScanToken *prevTok = tok - 1; while (prevTok >= scnTok) { prevTok->endDistance = endDist; @@ -2316,7 +2345,7 @@ ClockScan( Tcl_Obj *strObj, /* String containing the time to scan */ ClockFmtScnCmdArgs *opts) /* Command options */ { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; ClockFmtScnStorage *fss; ClockScanToken *tok; const ClockScanTokenMap *map; @@ -2421,24 +2450,20 @@ ClockScan( x = p + size; if (map->type == CTOKT_INT) { if (size <= 10) { - _str2int_no((int *)(((char *)info) + map->offs), + Clock_str2int_no(IntFieldAt(info, map->offs), p, x, sign); - } else { - if (_str2int((int *)(((char *)info) + map->offs), - p, x, sign) != TCL_OK) { - goto overflow; - } + } else if (Clock_str2int( + IntFieldAt(info, map->offs), p, x, sign) != TCL_OK) { + goto overflow; } p = x; } else { if (size <= 18) { - _str2wideInt_no((Tcl_WideInt *)(((char *)info) + map->offs), - p, x, sign); - } else { - if (_str2wideInt((Tcl_WideInt *)(((char *)info) + map->offs), - p, x, sign) != TCL_OK) { - goto overflow; - } + Clock_str2wideInt_no( + WideFieldAt(info, map->offs), p, x, sign); + } else if (Clock_str2wideInt( + WideFieldAt(info, map->offs), p, x, sign) != TCL_OK) { + goto overflow; } p = x; } @@ -2651,14 +2676,14 @@ ClockScan( overflow: Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "integer value too large to represent", -1)); + "integer value too large to represent", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL); goto done; not_match: #if 1 Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "input string does not match supplied format", -1)); + "input string does not match supplied format", TCL_AUTO_LENGTH)); #else /* to debug where exactly scan breaks */ Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf( @@ -2772,9 +2797,9 @@ ClockFmtToken_StarDate_Proc( } memcpy(dateFmt->output, "Stardate ", 9); dateFmt->output += 9; - dateFmt->output = _itoaw(dateFmt->output, + dateFmt->output = Clock_itoaw(dateFmt->output, dateFmt->date.year - RODDENBERRY, '0', 2); - dateFmt->output = _itoaw(dateFmt->output, + dateFmt->output = Clock_itoaw(dateFmt->output, fractYear, '0', 3); *dateFmt->output++ = '.'; /* be sure positive after decimal point (note: clock-value can be negative) */ @@ -2782,7 +2807,7 @@ ClockFmtToken_StarDate_Proc( if (v < 0) { v = 10 + v; } - dateFmt->output = _itoaw(dateFmt->output, v, '0', 1); + dateFmt->output = Clock_itoaw(dateFmt->output, v, '0', 1); return TCL_OK; } static int @@ -2837,7 +2862,7 @@ ClockFmtToken_JDN_Proc( if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { return TCL_ERROR; } - dateFmt->output = _witoaw(dateFmt->output, intJD, '0', 1); + dateFmt->output = Clock_witoaw(dateFmt->output, intJD, '0', 1); /* simplest cases .0 and .5 */ if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) { /* point + 0 or 5 */ @@ -2863,11 +2888,11 @@ ClockFmtToken_JDN_Proc( return TCL_ERROR; } *dateFmt->output++ = '.'; - p = _itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); + p = Clock_itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); /* remove trailing zero's */ dateFmt->output++; - while (p > dateFmt->output && *(p-1) == '0') { + while (p > dateFmt->output && p[-1] == '0') { p--; } *p = '\0'; @@ -2894,12 +2919,12 @@ ClockFmtToken_TimeZone_Proc( return TCL_ERROR; } *dateFmt->output++ = sign; - dateFmt->output = _itoaw(dateFmt->output, z / 3600, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z / 3600, '0', 2); z %= 3600; - dateFmt->output = _itoaw(dateFmt->output, z / 60, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z / 60, '0', 2); z %= 60; if (z != 0) { - dateFmt->output = _itoaw(dateFmt->output, z, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z, '0', 2); } } else { Tcl_Obj * objPtr; @@ -2907,7 +2932,7 @@ ClockFmtToken_TimeZone_Proc( Tcl_Size len; /* convert seconds to local seconds to obtain tzName object */ - if (ConvertUTCToLocal(opts->clientData, opts->interp, + if (ConvertUTCToLocal(opts->dataPtr, opts->interp, &dateFmt->date, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { return TCL_ERROR; @@ -2986,12 +3011,10 @@ ClockFmtToken_LocaleERAYear_Proc( } if (*tok->tokWord.start == 'C') { /* %EC */ *val = dateFmt->date.year / 100; - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); } else { /* %Ey */ *val = dateFmt->date.year % 100; - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); } } else { Tcl_Obj *objPtr; @@ -3027,8 +3050,7 @@ ClockFmtToken_LocaleERAYear_Proc( if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; } - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); return TCL_OK; } } @@ -3042,6 +3064,10 @@ ClockFmtToken_LocaleERAYear_Proc( return TCL_OK; } +/* + * Descriptors for the various fields in [clock format]. + */ + static const char *FmtSTokenMapIndex = "demNbByYCHMSIklpaAuwUVzgGjJsntQ"; static const ClockFormatTokenMap FmtSTokenMap[] = { @@ -3219,7 +3245,7 @@ ClockGetOrParseFmtFormat( fss->fmtTokC = EstimateTokenCount(p, e); fmtTok = tok = (ClockFormatToken *) ckalloc(sizeof(*tok) * fss->fmtTokC); - memset(tok, 0, sizeof(*(tok))); + memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { switch (*p) { @@ -3293,8 +3319,8 @@ ClockGetOrParseFmtFormat( word_tok: { ClockFormatToken *wordTok = tok; - if (tok > fmtTok && (tok-1)->map == &FmtWordTokenMap) { - wordTok = tok-1; + if (tok > fmtTok && (tok - 1)->map == &FmtWordTokenMap) { + wordTok = tok - 1; } if (wordTok == tok) { wordTok->tokWord.start = p; @@ -3368,7 +3394,7 @@ ClockFormat( map = tok->map; switch (map->type) { case CTOKT_INT: { - int val = (int)*(int *)(((char *)dateFmt) + map->offs); + int val = *IntFieldAt(dateFmt, map->offs); if (map->fmtproc == NULL) { if (map->flags & CLFMT_DECR) { @@ -3397,13 +3423,15 @@ ClockFormat( goto error; } if (map->width) { - dateFmt->output = _itoaw(dateFmt->output, val, *map->tostr, map->width); + dateFmt->output = Clock_itoaw( + dateFmt->output, val, *map->tostr, map->width); } else { dateFmt->output += sprintf(dateFmt->output, map->tostr, val); } } else { const char *s; Tcl_Obj * mcObj = ClockMCGet(opts, PTR2INT(map->data) /* mcKey */); + if (mcObj == NULL) { goto error; } @@ -3421,13 +3449,13 @@ ClockFormat( break; } case CTOKT_WIDE: { - Tcl_WideInt val = *(Tcl_WideInt *)(((char *)dateFmt) + map->offs); + Tcl_WideInt val = *WideFieldAt(dateFmt, map->offs); if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { goto error; } if (map->width) { - dateFmt->output = _witoaw(dateFmt->output, val, *map->tostr, map->width); + dateFmt->output = Clock_witoaw(dateFmt->output, val, *map->tostr, map->width); } else { dateFmt->output += sprintf(dateFmt->output, map->tostr, val); } diff --git a/generic/tclDate.h b/generic/tclDate.h index 8b71827..60e07ab 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -31,42 +31,51 @@ #define RODDENBERRY 1946 /* Another epoch (Hi, Jeff!) */ +enum DateInfoFlags { + CLF_OPTIONAL = 1 << 0, /* token is non mandatory */ + CLF_POSIXSEC = 1 << 1, + CLF_LOCALSEC = 1 << 2, + CLF_JULIANDAY = 1 << 3, + CLF_TIME = 1 << 4, + CLF_ZONE = 1 << 5, + CLF_CENTURY = 1 << 6, + CLF_DAYOFMONTH = 1 << 7, + CLF_DAYOFYEAR = 1 << 8, + CLF_MONTH = 1 << 9, + CLF_YEAR = 1 << 10, + CLF_DAYOFWEEK = 1 << 11, + CLF_ISO8601YEAR = 1 << 12, + CLF_ISO8601WEAK = 1 << 13, + CLF_ISO8601CENTURY = 1 << 14, + + CLF_SIGNED = 1 << 15, + + /* Compounds */ + + CLF_HAVEDATE = (CLF_DAYOFMONTH | CLF_MONTH | CLF_YEAR), + CLF_DATE = (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR + | CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR + | CLF_DAYOFWEEK | CLF_ISO8601WEAK), + + /* + * Extra flags used outside of scan/format-tokens too (int, not a short). + */ + + CLF_RELCONV = 1 << 17, + CLF_ORDINALMONTH = 1 << 18, + + /* On demand (lazy) assemble flags */ + + CLF_ASSEMBLE_DATE = 1 << 28,/* assemble year, month, etc. using julianDay */ + CLF_ASSEMBLE_JULIANDAY = 1 << 29, + /* assemble julianDay using year, month, etc. */ + CLF_ASSEMBLE_SECONDS = 1 << 30 + /* assemble localSeconds (and seconds at end) */ +}; -#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */ -#define CLF_POSIXSEC (1 << 1) -#define CLF_LOCALSEC (1 << 2) -#define CLF_JULIANDAY (1 << 3) -#define CLF_TIME (1 << 4) -#define CLF_ZONE (1 << 5) -#define CLF_CENTURY (1 << 6) -#define CLF_DAYOFMONTH (1 << 7) -#define CLF_DAYOFYEAR (1 << 8) -#define CLF_MONTH (1 << 9) -#define CLF_YEAR (1 << 10) -#define CLF_DAYOFWEEK (1 << 11) -#define CLF_ISO8601YEAR (1 << 12) -#define CLF_ISO8601WEAK (1 << 13) -#define CLF_ISO8601CENTURY (1 << 14) - -#define CLF_SIGNED (1 << 15) - -/* extra flags used outside of scan/format-tokens too (int, not a short int) */ -#define CLF_RELCONV (1 << 17) -#define CLF_ORDINALMONTH (1 << 18) - -/* On demand (lazy) assemble flags */ -#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */ -#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */ -#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */ - -#define CLF_HAVEDATE (CLF_DAYOFMONTH|CLF_MONTH|CLF_YEAR) -#define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \ - CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | \ - CLF_DAYOFWEEK | CLF_ISO8601WEAK) - -#define TCL_MIN_SECONDS -0x00F0000000000000LL -#define TCL_MAX_SECONDS 0x00F0000000000000LL -#define TCL_INV_SECONDS (TCL_MIN_SECONDS-1) +#define TCL_MIN_SECONDS -0x00F0000000000000LL +#define TCL_MAX_SECONDS 0x00F0000000000000LL +#define TCL_INV_SECONDS (TCL_MIN_SECONDS - 1) /* * Enumeration of the string literals used in [clock] @@ -148,10 +157,11 @@ typedef enum ClockMsgCtLiteral { * Structure containing the fields used in [clock format] and [clock scan] */ -#define CLF_CTZ (1 << 4) +enum TclDateFieldsFlags { + CLF_CTZ = (1 << 4) +}; typedef struct TclDateFields { - /* Cacheable fields: */ Tcl_WideInt seconds; /* Time expressed in seconds from the Posix @@ -270,15 +280,19 @@ ClockInitDateInfo( * Structure containing the command arguments supplied to [clock format] and [clock scan] */ -#define CLF_VALIDATE_S1 (1 << 0) -#define CLF_VALIDATE_S2 (1 << 1) -#define CLF_VALIDATE (CLF_VALIDATE_S1|CLF_VALIDATE_S2) -#define CLF_EXTENDED (1 << 4) -#define CLF_STRICT (1 << 8) -#define CLF_LOCALE_USED (1 << 15) +enum ClockFmtScnCmdArgsFlags { + CLF_VALIDATE_S1 = (1 << 0), + CLF_VALIDATE_S2 = (1 << 1), + CLF_VALIDATE = (CLF_VALIDATE_S1|CLF_VALIDATE_S2), + CLF_EXTENDED = (1 << 4), + CLF_STRICT = (1 << 8), + CLF_LOCALE_USED = (1 << 15) +}; + +typedef struct ClockClientData ClockClientData; typedef struct ClockFmtScnCmdArgs { - void *clientData; /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr; /* Pointer to literal pool, etc. */ Tcl_Interp *interp; /* Tcl interpreter */ Tcl_Obj *formatObj; /* Format */ Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */ @@ -422,10 +436,12 @@ typedef struct DateFormat { Tcl_Obj *localeEra; } DateFormat; -#define CLFMT_INCR (1 << 3) -#define CLFMT_DECR (1 << 4) -#define CLFMT_CALC (1 << 5) -#define CLFMT_LOCALE_INDX (1 << 8) +enum ClockFormatTokenMapFlags { + CLFMT_INCR = (1 << 3), + CLFMT_DECR = (1 << 4), + CLFMT_CALC = (1 << 5), + CLFMT_LOCALE_INDX = (1 << 8) +}; typedef struct ClockFormatToken ClockFormatToken; @@ -513,7 +529,7 @@ MODULE_SCOPE void GetJulianDayFromEraYearMonthDay( TclDateFields *fields, int changeover); MODULE_SCOPE void GetJulianDayFromEraYearDay( TclDateFields *fields, int changeover); -MODULE_SCOPE int ConvertUTCToLocal(void *clientData, Tcl_Interp *, +MODULE_SCOPE int ConvertUTCToLocal(ClockClientData *dataPtr, Tcl_Interp *, TclDateFields *, Tcl_Obj *timezoneObj, int); MODULE_SCOPE Tcl_Obj * LookupLastTransition(Tcl_Interp *, Tcl_WideInt, Tcl_Size, Tcl_Obj *const *, Tcl_WideInt *rangesVal); @@ -521,7 +537,7 @@ MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info); /* tclClock.c module declarations */ -MODULE_SCOPE Tcl_Obj * ClockSetupTimeZone(void *clientData, +MODULE_SCOPE Tcl_Obj * ClockSetupTimeZone(ClockClientData *dataPtr, Tcl_Interp *interp, Tcl_Obj *timezoneObj); MODULE_SCOPE Tcl_Obj * ClockMCDict(ClockFmtScnCmdArgs *opts); MODULE_SCOPE Tcl_Obj * ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey); diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index a1c83a9..533f73d 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -462,7 +462,7 @@ TclStrIdxTreePrint( Tcl_Obj *obj[2]; const char *s; - TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", -1)); + TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", TCL_AUTO_LENGTH)); while (tree != NULL) { s = TclGetString(tree->key) + offs; TclInitObjRef(obj[1], Tcl_ObjPrintf("%*s%.*s\t:%d", -- cgit v0.12 From 4a35726086cdd4ae0a50a852e208b3d5fa1fe025 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Apr 2024 14:02:17 +0000 Subject: Fixed misleading comment --- generic/tclClock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 722aba7..b1aefa8 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -4619,7 +4619,8 @@ ClockSafeCatchCmd( * environment variable has changed. * * Results: - * None. + * An epoch counter to allow efficient checking if the timezone has + * changed. * * Side effects: * Calls tzset. -- cgit v0.12 From c04d61ad4b5c3d2fcdbe941830926e10d0bb470d Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Apr 2024 14:10:36 +0000 Subject: Clock not weak; clock strong! --- generic/tclClock.c | 2 +- generic/tclClockFmt.c | 18 +++++++++--------- generic/tclDate.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 0376a2d..6bb85f4 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -3705,7 +3705,7 @@ ClockScanCommit( { /* If needed assemble julianDay using year, month, etc. */ if (info->flags & CLF_ASSEMBLE_JULIANDAY) { - if ((info->flags & CLF_ISO8601WEAK)) { + if (info->flags & CLF_ISO8601WEEK) { GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE); } else if (!(info->flags & CLF_DAYOFYEAR) /* no day of year */ || (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */ diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index acb1502..40c6c92 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -2008,7 +2008,7 @@ static const ClockScanTokenMap ScnSTokenMap[] = { {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601CENTURY, 0, 4, 4, offsetof(DateInfo, date.iso8601Year), NULL, NULL}, /* %V */ - {CTOKT_INT, CLF_ISO8601WEAK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week), + {CTOKT_INT, CLF_ISO8601WEEK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week), NULL, NULL}, /* %a %A %u %w */ {CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0, @@ -2580,7 +2580,7 @@ ClockScan( case CLF_DAYOFYEAR: /* ddd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } break; case CLF_MONTH | CLF_DAYOFYEAR | CLF_DAYOFMONTH: @@ -2589,7 +2589,7 @@ ClockScan( case CLF_DAYOFMONTH: /* mmdd / dd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } break; /* neither mmdd nor ddd available */ @@ -2597,22 +2597,22 @@ ClockScan( /* but we have day of the week, which can be used */ if (flags & CLF_DAYOFWEEK) { /* prefer week based calculation of julianday */ - flags |= CLF_ISO8601WEAK; + flags |= CLF_ISO8601WEEK; } } /* YearWeekDay below YearMonthDay */ - if ((flags & CLF_ISO8601WEAK) + if ((flags & CLF_ISO8601WEEK) && ((flags & (CLF_YEAR | CLF_DAYOFYEAR)) == (CLF_YEAR | CLF_DAYOFYEAR) || (flags & (CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH)) == ( CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH))) { /* yy precedence below yyyy */ if (!(flags & CLF_ISO8601CENTURY) && (flags & CLF_CENTURY)) { /* normally precedence of ISO is higher, but no century - so put it down */ - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } else if (!(flags & CLF_ISO8601YEAR)) { /* yymmdd or yyddd over naked weekday */ - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } } @@ -2628,7 +2628,7 @@ ClockScan( } } } - if (flags & (CLF_ISO8601WEAK | CLF_ISO8601YEAR)) { + if (flags & (CLF_ISO8601WEEK | CLF_ISO8601YEAR)) { if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_YEAR) { /* for calculations expected iso year */ info->date.iso8601Year = yyYear; @@ -2643,7 +2643,7 @@ ClockScan( } } if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_ISO8601YEAR) { - /* for calculations expected year (e. g. CLF_ISO8601WEAK not set) */ + /* for calculations expected year (e. g. CLF_ISO8601WEEK not set) */ yyYear = info->date.iso8601Year; } } diff --git a/generic/tclDate.h b/generic/tclDate.h index 60e07ab..1657528 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -45,7 +45,7 @@ enum DateInfoFlags { CLF_YEAR = 1 << 10, CLF_DAYOFWEEK = 1 << 11, CLF_ISO8601YEAR = 1 << 12, - CLF_ISO8601WEAK = 1 << 13, + CLF_ISO8601WEEK = 1 << 13, CLF_ISO8601CENTURY = 1 << 14, CLF_SIGNED = 1 << 15, @@ -55,7 +55,7 @@ enum DateInfoFlags { CLF_HAVEDATE = (CLF_DAYOFMONTH | CLF_MONTH | CLF_YEAR), CLF_DATE = (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR - | CLF_DAYOFWEEK | CLF_ISO8601WEAK), + | CLF_DAYOFWEEK | CLF_ISO8601WEEK), /* * Extra flags used outside of scan/format-tokens too (int, not a short). -- cgit v0.12 From f1d98185ed272bf66273010cf052cc5cbfeab625 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 12 Apr 2024 15:25:48 +0000 Subject: (cherry-pick): Clock not weak; clock strong! --- generic/tclClock.c | 2 +- generic/tclClockFmt.c | 18 +++++++++--------- generic/tclDate.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index b1aefa8..5876114 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -3705,7 +3705,7 @@ ClockScanCommit( { /* If needed assemble julianDay using year, month, etc. */ if (info->flags & CLF_ASSEMBLE_JULIANDAY) { - if ((info->flags & CLF_ISO8601WEAK)) { + if (info->flags & CLF_ISO8601WEEK) { GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE); } else if (!(info->flags & CLF_DAYOFYEAR) /* no day of year */ || (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */ diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index cbb935d..7517b72 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -2007,7 +2007,7 @@ static const ClockScanTokenMap ScnSTokenMap[] = { {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601CENTURY, 0, 4, 4, offsetof(DateInfo, date.iso8601Year), NULL, NULL}, /* %V */ - {CTOKT_INT, CLF_ISO8601WEAK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week), + {CTOKT_INT, CLF_ISO8601WEEK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week), NULL, NULL}, /* %a %A %u %w */ {CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0, @@ -2579,7 +2579,7 @@ ClockScan( case CLF_DAYOFYEAR: /* ddd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } break; case CLF_MONTH | CLF_DAYOFYEAR | CLF_DAYOFMONTH: @@ -2588,7 +2588,7 @@ ClockScan( case CLF_DAYOFMONTH: /* mmdd / dd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } break; /* neither mmdd nor ddd available */ @@ -2596,22 +2596,22 @@ ClockScan( /* but we have day of the week, which can be used */ if (flags & CLF_DAYOFWEEK) { /* prefer week based calculation of julianday */ - flags |= CLF_ISO8601WEAK; + flags |= CLF_ISO8601WEEK; } } /* YearWeekDay below YearMonthDay */ - if ((flags & CLF_ISO8601WEAK) + if ((flags & CLF_ISO8601WEEK) && ((flags & (CLF_YEAR | CLF_DAYOFYEAR)) == (CLF_YEAR | CLF_DAYOFYEAR) || (flags & (CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH)) == ( CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH))) { /* yy precedence below yyyy */ if (!(flags & CLF_ISO8601CENTURY) && (flags & CLF_CENTURY)) { /* normally precedence of ISO is higher, but no century - so put it down */ - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } else if (!(flags & CLF_ISO8601YEAR)) { /* yymmdd or yyddd over naked weekday */ - flags &= ~CLF_ISO8601WEAK; + flags &= ~CLF_ISO8601WEEK; } } @@ -2627,7 +2627,7 @@ ClockScan( } } } - if (flags & (CLF_ISO8601WEAK | CLF_ISO8601YEAR)) { + if (flags & (CLF_ISO8601WEEK | CLF_ISO8601YEAR)) { if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_YEAR) { /* for calculations expected iso year */ info->date.iso8601Year = yyYear; @@ -2642,7 +2642,7 @@ ClockScan( } } if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_ISO8601YEAR) { - /* for calculations expected year (e. g. CLF_ISO8601WEAK not set) */ + /* for calculations expected year (e. g. CLF_ISO8601WEEK not set) */ yyYear = info->date.iso8601Year; } } diff --git a/generic/tclDate.h b/generic/tclDate.h index 60e07ab..1657528 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -45,7 +45,7 @@ enum DateInfoFlags { CLF_YEAR = 1 << 10, CLF_DAYOFWEEK = 1 << 11, CLF_ISO8601YEAR = 1 << 12, - CLF_ISO8601WEAK = 1 << 13, + CLF_ISO8601WEEK = 1 << 13, CLF_ISO8601CENTURY = 1 << 14, CLF_SIGNED = 1 << 15, @@ -55,7 +55,7 @@ enum DateInfoFlags { CLF_HAVEDATE = (CLF_DAYOFMONTH | CLF_MONTH | CLF_YEAR), CLF_DATE = (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR - | CLF_DAYOFWEEK | CLF_ISO8601WEAK), + | CLF_DAYOFWEEK | CLF_ISO8601WEEK), /* * Extra flags used outside of scan/format-tokens too (int, not a short). -- cgit v0.12 From 8d186d9f5a98a5225ca38935c3cd51d33236f1c6 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Apr 2024 16:09:49 +0000 Subject: Clean up the arith series code, including fixing a memory leak --- generic/tclArithSeries.c | 426 +++++++++++++++++++++++++++-------------------- 1 file changed, 250 insertions(+), 176 deletions(-) diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 2770639..fd1014c 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -46,41 +46,56 @@ * Note that the len can in theory be always computed by start,end,step * but it's faster to cache it inside the internal representation. */ + typedef struct { Tcl_Size len; Tcl_Obj **elements; int isDouble; +} ArithSeries; + +typedef struct { + ArithSeries base; Tcl_WideInt start; Tcl_WideInt end; Tcl_WideInt step; -} ArithSeries; +} ArithSeriesInt; + typedef struct { - Tcl_Size len; - Tcl_Obj **elements; - int isDouble; + ArithSeries base; double start; double end; double step; - int precision; + unsigned precision; /* Number of decimal places to render. */ } ArithSeriesDbl; -/* -------------------------- ArithSeries object ---------------------------- */ - -static int TclArithSeriesObjIndex(TCL_UNUSED(Tcl_Interp *), Tcl_Obj *arithSeriesObj, - Tcl_Size index, Tcl_Obj **elemObj); - -static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesObj); -static int TclArithSeriesObjRange(Tcl_Interp *interp, Tcl_Obj *arithSeriesObj, - Tcl_Size fromIdx, Tcl_Size toIdx, Tcl_Obj **newObjPtr); -static int TclArithSeriesObjReverse(Tcl_Interp *interp, Tcl_Obj *arithSeriesObj, Tcl_Obj **newObjPtr); -static int TclArithSeriesGetElements(Tcl_Interp *interp, - Tcl_Obj *objPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); -static void DupArithSeriesInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); -static void FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr); -static void UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr); -static int SetArithSeriesFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); -static int ArithSeriesInOperation(Tcl_Interp *interp, Tcl_Obj *valueObj, Tcl_Obj *arithSeriesObj, - int *boolResult); +/* Forward declarations. */ + +static int TclArithSeriesObjIndex(TCL_UNUSED(Tcl_Interp *), + Tcl_Obj *arithSeriesObj, Tcl_Size index, + Tcl_Obj **elemObj); +static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesObj); +static int TclArithSeriesObjRange(Tcl_Interp *interp, + Tcl_Obj *arithSeriesObj, Tcl_Size fromIdx, + Tcl_Size toIdx, Tcl_Obj **newObjPtr); +static int TclArithSeriesObjReverse(Tcl_Interp *interp, + Tcl_Obj *arithSeriesObj, Tcl_Obj **newObjPtr); +static int TclArithSeriesGetElements(Tcl_Interp *interp, + Tcl_Obj *objPtr, Tcl_Size *objcPtr, + Tcl_Obj ***objvPtr); +static void DupArithSeriesInternalRep(Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr); +static void FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr); +static void UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr); +static int SetArithSeriesFromAny(Tcl_Interp *interp, + Tcl_Obj *objPtr); +static int ArithSeriesInOperation(Tcl_Interp *interp, + Tcl_Obj *valueObj, Tcl_Obj *arithSeriesObj, + int *boolResult); +static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, + Tcl_Obj **stepObj); + +/* ------------------------ ArithSeries object type -------------------------- */ + static const Tcl_ObjType arithSeriesType = { "arithseries", /* name */ FreeArithSeriesInternalRep, /* freeIntRepProc */ @@ -97,10 +112,11 @@ static const Tcl_ObjType arithSeriesType = { NULL, // Replace ArithSeriesInOperation) // "in" operator }; - + /* * Helper functions * + * - power10 -- Fast version of pow(10, (int) n) for common cases. * - ArithRound -- Round doubles to the number of significant fractional * digits * - ArithSeriesIndexDbl -- base list indexing operation for doubles @@ -111,10 +127,31 @@ static const Tcl_ObjType arithSeriesType = { * - maxPrecision -- Using the values provide, determine the longest percision * in the arithSeries */ + static inline double -ArithRound(double d, unsigned int n) { - double scalefactor = pow(10, n); - return round(d*scalefactor)/scalefactor; +power10( + unsigned n) +{ + static const double powers[] = { + 1, 10, 100, 1000, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, + 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20 + }; + + if (n < sizeof(powers) / sizeof(*powers)) { + return powers[n]; + } else { + // Not an expected case. Doesn't need to be so fast + return pow(10, n); + } +} + +static inline double +ArithRound( + double d, + unsigned n) +{ + double scalefactor = power10(n); + return round(d * scalefactor) / scalefactor; } static inline double @@ -122,13 +159,14 @@ ArithSeriesIndexDbl( ArithSeries *arithSeriesRepPtr, Tcl_WideInt index) { - ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; if (arithSeriesRepPtr->isDouble) { + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; double d = dblRepPtr->start + (index * dblRepPtr->step); - unsigned n = (dblRepPtr->precision > 0 ? dblRepPtr->precision : 0); - return ArithRound(d, n); + + return ArithRound(d, dblRepPtr->precision); } else { - return (double)(arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step)); + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; + return (double)(intRepPtr->start + (index * intRepPtr->step)); } } @@ -137,51 +175,57 @@ ArithSeriesIndexInt( ArithSeries *arithSeriesRepPtr, Tcl_WideInt index) { - ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; if (arithSeriesRepPtr->isDouble) { - return (Tcl_WideInt)(dblRepPtr->start + ((index) * dblRepPtr->step)); + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; + return (Tcl_WideInt) (dblRepPtr->start + (index * dblRepPtr->step)); } else { - return (arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step)); + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; + return intRepPtr->start + (index * intRepPtr->step); } } -static inline ArithSeries* -ArithSeriesGetInternalRep(Tcl_Obj *objPtr) +static inline ArithSeries * +ArithSeriesGetInternalRep( + Tcl_Obj *objPtr) { - const Tcl_ObjInternalRep *irPtr; - irPtr = TclFetchInternalRep((objPtr), &arithSeriesType); - return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL; + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, + &arithSeriesType); + return irPtr ? (ArithSeries *) irPtr->twoPtrValue.ptr1 : NULL; } /* - * Compute number of significant factional digits + * Compute number of significant fractional digits */ -static inline int -Precision(double d) +static inline unsigned +Precision( + double d) { - char tmp[TCL_DOUBLE_SPACE+2], *off; + char tmp[TCL_DOUBLE_SPACE + 2], *off; + tmp[0] = 0; - Tcl_PrintDouble(NULL,d,tmp); + Tcl_PrintDouble(NULL, d, tmp); off = strchr(tmp, '.'); - return (off ? strlen(off+1) : 0); + return (off ? strlen(off + 1) : 0); } /* * Find longest number of digits after the decimal point. */ -static inline int -maxPrecision(double start, double end, double step) +static inline unsigned +maxPrecision( + double start, + double end, + double step) { - int dp = Precision(step); - int i = Precision(start); + unsigned dp = Precision(step); + unsigned i = Precision(start); + dp = i>dp ? i : dp; i = Precision(end); dp = i>dp ? i : dp; return dp; } - -static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, Tcl_Obj **stepObj); - + /* *---------------------------------------------------------------------- * @@ -206,31 +250,38 @@ static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, Tcl_Obj **stepObj); *---------------------------------------------------------------------- */ static Tcl_WideInt -ArithSeriesLenInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step) +ArithSeriesLenInt( + Tcl_WideInt start, + Tcl_WideInt end, + Tcl_WideInt step) { Tcl_WideInt len; if (step == 0) { return 0; } - len = 1 + ((end-start)/step); + len = 1 + ((end - start) / step); return (len < 0) ? -1 : len; } static Tcl_WideInt -ArithSeriesLenDbl(double start, double end, double step, int precision) +ArithSeriesLenDbl( + double start, + double end, + double step, + unsigned precision) { double istart, iend, istep, ilen; + if (step == 0) { return 0; } - istart = start * pow(10,precision); - iend = end * pow(10,precision); - istep = step * pow(10,precision); - ilen = ((iend-istart+istep)/istep); + istart = start * power10(precision); + iend = end * power10(precision); + istep = step * power10(precision); + ilen = (iend - istart + istep) / istep; return floor(ilen); } - /* *---------------------------------------------------------------------- @@ -239,6 +290,7 @@ ArithSeriesLenDbl(double start, double end, double step, int precision) * * Initialize the internal representation of a arithseries Tcl_Obj to a * copy of the internal representation of an existing arithseries object. + * The copy does not share the cache of the elements. * * Results: * None. @@ -246,6 +298,7 @@ ArithSeriesLenDbl(double start, double end, double step, int precision) * Side effects: * We set "copyPtr"s internal rep to a pointer to a * newly allocated ArithSeries structure. + * *---------------------------------------------------------------------- */ @@ -254,26 +307,25 @@ DupArithSeriesInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { - ArithSeries *srcArithSeriesRepPtr = - (ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1; + ArithSeries *srcRepPtr = (ArithSeries *) + srcPtr->internalRep.twoPtrValue.ptr1; - /* - * Allocate a new ArithSeries structure. */ - - if (srcArithSeriesRepPtr->isDouble) { - ArithSeriesDbl *srcArithSeriesDblRepPtr = - (ArithSeriesDbl *)srcArithSeriesRepPtr; - ArithSeriesDbl *copyArithSeriesDblRepPtr = - (ArithSeriesDbl *)Tcl_Alloc(sizeof(ArithSeriesDbl)); - *copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr; - copyArithSeriesDblRepPtr->elements = NULL; - copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr; + if (srcRepPtr->isDouble) { + ArithSeriesDbl *srcDblPtr = (ArithSeriesDbl *) srcRepPtr; + ArithSeriesDbl *copyDblPtr = (ArithSeriesDbl *) + Tcl_Alloc(sizeof(ArithSeriesDbl)); + + *copyDblPtr = *srcDblPtr; + copyDblPtr->base.elements = NULL; + copyPtr->internalRep.twoPtrValue.ptr1 = copyDblPtr; } else { - ArithSeries *copyArithSeriesRepPtr = - (ArithSeries *)Tcl_Alloc(sizeof(ArithSeries)); - *copyArithSeriesRepPtr = *srcArithSeriesRepPtr; - copyArithSeriesRepPtr->elements = NULL; - copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr; + ArithSeriesInt *srcIntPtr = (ArithSeriesInt *) srcRepPtr; + ArithSeriesInt *copyIntPtr = (ArithSeriesInt *) + Tcl_Alloc(sizeof(ArithSeriesInt)); + + *copyIntPtr = *srcIntPtr; + copyIntPtr->base.elements = NULL; + copyPtr->internalRep.twoPtrValue.ptr1 = copyIntPtr; } copyPtr->internalRep.twoPtrValue.ptr2 = NULL; copyPtr->typePtr = &arithSeriesType; @@ -293,24 +345,34 @@ DupArithSeriesInternalRep( * *---------------------------------------------------------------------- */ -static void -FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr) /* Free any allocated memory */ + +static inline void +FreeElements( + ArithSeries *arithSeriesRepPtr) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + if (arithSeriesRepPtr->elements) { + Tcl_WideInt i, len = arithSeriesRepPtr->len; - if (arithSeriesRepPtr) { - if (arithSeriesRepPtr->elements) { - Tcl_WideInt i, len = arithSeriesRepPtr->len; - for (i=0; ielements[i]); - } - Tcl_Free((char*)arithSeriesRepPtr->elements); - arithSeriesRepPtr->elements = NULL; + for (i=0; ielements[i]); } - Tcl_Free((char*)arithSeriesRepPtr); + Tcl_Free((char *) arithSeriesRepPtr->elements); + arithSeriesRepPtr->elements = NULL; } } +static void +FreeArithSeriesInternalRep( + Tcl_Obj *arithSeriesObjPtr) +{ + ArithSeries *arithSeriesRepPtr = (ArithSeries *) + arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + + if (arithSeriesRepPtr) { + FreeElements(arithSeriesRepPtr); + Tcl_Free((char *) arithSeriesRepPtr); + } +} /* *---------------------------------------------------------------------- @@ -326,17 +388,20 @@ FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr) /* Free any allocated me * A NULL pointer of the range is invalid. * * Side Effects: - * * None. + * *---------------------------------------------------------------------- */ -static -Tcl_Obj * -NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_WideInt len) +static Tcl_Obj * +NewArithSeriesInt( + Tcl_WideInt start, + Tcl_WideInt end, + Tcl_WideInt step, + Tcl_WideInt len) { Tcl_WideInt length; Tcl_Obj *arithSeriesObj; - ArithSeries *arithSeriesRepPtr; + ArithSeriesInt *arithSeriesRepPtr; length = len>=0 ? len : -1; if (length < 0) { @@ -349,13 +414,13 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide return arithSeriesObj; } - arithSeriesRepPtr = (ArithSeries*)Tcl_Alloc(sizeof (ArithSeries)); - arithSeriesRepPtr->isDouble = 0; + arithSeriesRepPtr = (ArithSeriesInt *) Tcl_Alloc(sizeof(ArithSeriesInt)); + arithSeriesRepPtr->base.len = length; + arithSeriesRepPtr->base.elements = NULL; + arithSeriesRepPtr->base.isDouble = 0; arithSeriesRepPtr->start = start; arithSeriesRepPtr->end = end; arithSeriesRepPtr->step = step; - arithSeriesRepPtr->len = length; - arithSeriesRepPtr->elements = NULL; arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr; arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL; arithSeriesObj->typePtr = &arithSeriesType; @@ -385,9 +450,12 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide *---------------------------------------------------------------------- */ -static -Tcl_Obj * -NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) +static Tcl_Obj * +NewArithSeriesDbl( + double start, + double end, + double step, + Tcl_WideInt len) { Tcl_WideInt length; Tcl_Obj *arithSeriesObj; @@ -404,14 +472,14 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) return arithSeriesObj; } - arithSeriesRepPtr = (ArithSeriesDbl*)Tcl_Alloc(sizeof (ArithSeriesDbl)); - arithSeriesRepPtr->isDouble = 1; + arithSeriesRepPtr = (ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl)); + arithSeriesRepPtr->base.len = length; + arithSeriesRepPtr->base.elements = NULL; + arithSeriesRepPtr->base.isDouble = 1; arithSeriesRepPtr->start = start; arithSeriesRepPtr->end = end; arithSeriesRepPtr->step = step; - arithSeriesRepPtr->len = length; - arithSeriesRepPtr->elements = NULL; - arithSeriesRepPtr->precision = maxPrecision(start,end,step); + arithSeriesRepPtr->precision = maxPrecision(start, end, step); arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr; arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL; arithSeriesObj->typePtr = &arithSeriesType; @@ -546,7 +614,7 @@ TclNewArithSeriesObj( assert(dstep!=0); if (!lenObj) { if (useDoubles) { - int precision = maxPrecision(dstart,dend,dstep); + unsigned precision = maxPrecision(dstart, dend, dstep); len = ArithSeriesLenDbl(dstart, dend, dstep, precision); } else { len = ArithSeriesLenInt(start, end, step); @@ -557,21 +625,21 @@ TclNewArithSeriesObj( if (!endObj) { if (useDoubles) { // Compute precision based on given command argument values - int precision = maxPrecision(dstart,len,dstep); + unsigned precision = maxPrecision(dstart, len, dstep); + dend = dstart + (dstep * (len-1)); // Make computed end value match argument(s) precision dend = ArithRound(dend, precision); end = dend; } else { - end = start + (step * (len-1)); + end = start + (step * (len - 1)); dend = end; } } if (len > TCL_SIZE_MAX) { - Tcl_SetObjResult( - interp, - Tcl_NewStringObj("max length of a Tcl list exceeded", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "max length of a Tcl list exceeded", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); return TCL_ERROR; } @@ -606,13 +674,12 @@ TclNewArithSeriesObj( * *---------------------------------------------------------------------- */ - int TclArithSeriesObjIndex( - TCL_UNUSED(Tcl_Interp *),/* Used for error reporting if not NULL. */ - Tcl_Obj *arithSeriesObj, /* List obj */ - Tcl_Size index, /* index to element of interest */ - Tcl_Obj **elemObj) /* Return value */ + TCL_UNUSED(Tcl_Interp *), + Tcl_Obj *arithSeriesObj, /* List obj */ + Tcl_Size index, /* index to element of interest */ + Tcl_Obj **elemObj) /* Return value */ { ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj); @@ -651,7 +718,7 @@ Tcl_Size ArithSeriesObjLength( Tcl_Obj *arithSeriesObj) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*) + ArithSeries *arithSeriesRepPtr = (ArithSeries *) arithSeriesObj->internalRep.twoPtrValue.ptr1; return arithSeriesRepPtr->len; } @@ -681,14 +748,15 @@ TclArithSeriesObjStep( Tcl_Obj **stepObj) { ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj); + if (arithSeriesRepPtr->isDouble) { - *stepObj = Tcl_NewDoubleObj(((ArithSeriesDbl*)(arithSeriesRepPtr))->step); + *stepObj = Tcl_NewDoubleObj(((ArithSeriesDbl *) arithSeriesRepPtr)->step); } else { - *stepObj = Tcl_NewWideIntObj(arithSeriesRepPtr->step); + *stepObj = Tcl_NewWideIntObj(((ArithSeriesInt *) arithSeriesRepPtr)->step); } return TCL_OK; } - + /* *---------------------------------------------------------------------- * @@ -773,8 +841,8 @@ TclArithSeriesObjRange( if (toIdx < 0) { toIdx = 0; } - if (toIdx > arithSeriesRepPtr->len-1) { - toIdx = arithSeriesRepPtr->len-1; + if (toIdx > arithSeriesRepPtr->len - 1) { + toIdx = arithSeriesRepPtr->len - 1; } TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx, &startObj); @@ -806,30 +874,31 @@ TclArithSeriesObjRange( TclInvalidateStringRep(arithSeriesObj); if (arithSeriesRepPtr->isDouble) { - ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; double start, end, step; Tcl_GetDoubleFromObj(NULL, startObj, &start); Tcl_GetDoubleFromObj(NULL, endObj, &end); Tcl_GetDoubleFromObj(NULL, stepObj, &step); - arithSeriesDblRepPtr->start = start; - arithSeriesDblRepPtr->end = end; - arithSeriesDblRepPtr->step = step; - arithSeriesDblRepPtr->precision = maxPrecision(start, end, step); - arithSeriesDblRepPtr->len = - ArithSeriesLenDbl(start, end, step, arithSeriesDblRepPtr->precision); - arithSeriesDblRepPtr->elements = NULL; - + dblRepPtr->start = start; + dblRepPtr->end = end; + dblRepPtr->step = step; + dblRepPtr->precision = maxPrecision(start, end, step); + FreeElements(arithSeriesRepPtr); + dblRepPtr->base.len = + ArithSeriesLenDbl(start, end, step, dblRepPtr->precision); } else { + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; Tcl_WideInt start, end, step; + Tcl_GetWideIntFromObj(NULL, startObj, &start); Tcl_GetWideIntFromObj(NULL, endObj, &end); Tcl_GetWideIntFromObj(NULL, stepObj, &step); - arithSeriesRepPtr->start = start; - arithSeriesRepPtr->end = end; - arithSeriesRepPtr->step = step; - arithSeriesRepPtr->len = ArithSeriesLenInt(start, end, step); - arithSeriesRepPtr->elements = NULL; + intRepPtr->start = start; + intRepPtr->end = end; + intRepPtr->step = step; + FreeElements(arithSeriesRepPtr); + intRepPtr->base.len = ArithSeriesLenInt(start, end, step); } Tcl_DecrRefCount(startObj); @@ -880,32 +949,32 @@ TclArithSeriesGetElements( * pointers to the list's objects. */ { if (TclHasInternalRep(objPtr, &arithSeriesType)) { - ArithSeries *arithSeriesRepPtr; + ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr); Tcl_Obj **objv; - int i, objc; - - arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr); + Tcl_Size objc = arithSeriesRepPtr->len; - objc = arithSeriesRepPtr->len; if (objc > 0) { if (arithSeriesRepPtr->elements) { /* If this exists, it has already been populated */ objv = arithSeriesRepPtr->elements; } else { /* Construct the elements array */ - objv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj*) * objc); + objv = (Tcl_Obj **) Tcl_Alloc(sizeof(Tcl_Obj*) * objc); if (objv == NULL) { if (interp) { - Tcl_SetObjResult( - interp, - Tcl_NewStringObj("max length of a Tcl list exceeded", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "max length of a Tcl list exceeded", + TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return TCL_ERROR; } arithSeriesRepPtr->elements = objv; + + Tcl_Size i; for (i = 0; i < objc; i++) { int status = TclArithSeriesObjIndex(interp, objPtr, i, &objv[i]); + if (status) { return TCL_ERROR; } @@ -919,7 +988,8 @@ TclArithSeriesGetElements( *objcPtr = objc; } else { if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("value is not an arithseries", TCL_INDEX_NONE)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "value is not an arithseries", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "UNKNOWN", (void *)NULL); } return TCL_ERROR; @@ -968,7 +1038,7 @@ TclArithSeriesObjReverse( isDouble = arithSeriesRepPtr->isDouble; len = arithSeriesRepPtr->len; - TclArithSeriesObjIndex(NULL, arithSeriesObj, (len-1), &startObj); + TclArithSeriesObjIndex(NULL, arithSeriesObj, len - 1, &startObj); Tcl_IncrRefCount(startObj); TclArithSeriesObjIndex(NULL, arithSeriesObj, 0, &endObj); Tcl_IncrRefCount(endObj); @@ -991,6 +1061,7 @@ TclArithSeriesObjReverse( if (Tcl_IsShared(arithSeriesObj) || (arithSeriesObj->refCount > 1)) { Tcl_Obj *lenObj; + TclNewIntObj(lenObj, len); if (TclNewArithSeriesObj(NULL, &resultObj, isDouble, startObj, endObj, stepObj, lenObj) != TCL_OK) { @@ -998,7 +1069,6 @@ TclArithSeriesObjReverse( } Tcl_DecrRefCount(lenObj); } else { - /* * In-place is possible. */ @@ -1006,25 +1076,18 @@ TclArithSeriesObjReverse( TclInvalidateStringRep(arithSeriesObj); if (isDouble) { - ArithSeriesDbl *arithSeriesDblRepPtr = - (ArithSeriesDbl*)arithSeriesRepPtr; - arithSeriesDblRepPtr->start = dstart; - arithSeriesDblRepPtr->end = dend; - arithSeriesDblRepPtr->step = dstep; + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr; + + dblRepPtr->start = dstart; + dblRepPtr->end = dend; + dblRepPtr->step = dstep; } else { - arithSeriesRepPtr->start = start; - arithSeriesRepPtr->end = end; - arithSeriesRepPtr->step = step; - } - if (arithSeriesRepPtr->elements) { - Tcl_WideInt i; - for (i=0; ielements[i]); - } - Tcl_Free((char*)arithSeriesRepPtr->elements); + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr; + intRepPtr->start = start; + intRepPtr->end = end; + intRepPtr->step = step; } - arithSeriesRepPtr->elements = NULL; - + FreeElements(arithSeriesRepPtr); resultObj = arithSeriesObj; } @@ -1064,11 +1127,12 @@ TclArithSeriesObjReverse( * *---------------------------------------------------------------------- */ - static void -UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) +UpdateStringOfArithSeries( + Tcl_Obj *arithSeriesObjPtr) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + ArithSeries *arithSeriesRepPtr = (ArithSeries *) + arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; char *p; Tcl_Obj *eleObj; Tcl_Size i, bytlen = 0; @@ -1078,14 +1142,16 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) */ if (!arithSeriesRepPtr->isDouble) { for (i = 0; i < arithSeriesRepPtr->len; i++) { - double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i); - size_t slen = d>0 ? log10(d)+1 : d<0 ? log10((0-d))+2 : 1; + double d = ArithSeriesIndexInt(arithSeriesRepPtr, i); + size_t slen = d>0 ? log10(d)+1 : d<0 ? log10(-d)+2 : 1; + bytlen += slen; } } else { for (i = 0; i < arithSeriesRepPtr->len; i++) { double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i); - char tmp[TCL_DOUBLE_SPACE+2]; + char tmp[TCL_DOUBLE_SPACE + 2]; + tmp[0] = 0; Tcl_PrintDouble(NULL,d,tmp); if ((bytlen + strlen(tmp)) > TCL_SIZE_MAX) { @@ -1105,6 +1171,7 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) if (TclArithSeriesObjIndex(NULL, arithSeriesObjPtr, i, &eleObj) == TCL_OK) { Tcl_Size slen; char *str = TclGetStringFromObj(eleObj, &slen); + strcpy(p, str); p[slen] = ' '; p += slen + 1; @@ -1143,12 +1210,13 @@ ArithSeriesInOperation( Tcl_Obj *arithSeriesObjPtr, int *boolResult) { - ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; - ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + ArithSeries *repPtr = (ArithSeries *) + arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; int status; Tcl_Size index, incr, elen, vlen; - if (arithSeriesRepPtr->isDouble) { + if (repPtr->isDouble) { + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) repPtr; double y; int test = 0; @@ -1161,9 +1229,12 @@ ArithSeriesInOperation( index = (y - dblRepPtr->start) / dblRepPtr->step; while (incr<2) { Tcl_Obj *elemObj; + elen = 0; TclArithSeriesObjIndex(interp, arithSeriesObjPtr, (index+incr), &elemObj); + const char *estr = elemObj ? TclGetStringFromObj(elemObj, &elen) : ""; + /* "in" operation defined as a string compare */ test = (elen == vlen) ? (memcmp(estr, vstr, elen) == 0) : 0; Tcl_BounceRefCount(elemObj); @@ -1178,7 +1249,7 @@ ArithSeriesInOperation( *boolResult = test; } } else { - ArithSeries *intRepPtr = arithSeriesRepPtr; + ArithSeriesInt *intRepPtr = (ArithSeriesInt *) repPtr; Tcl_WideInt y; status = Tcl_GetWideIntFromObj(NULL, valueObj, &y); @@ -1188,11 +1259,14 @@ ArithSeriesInOperation( } } else { Tcl_Obj *elemObj; + elen = 0; index = (y - intRepPtr->start) / intRepPtr->step; TclArithSeriesObjIndex(interp, arithSeriesObjPtr, index, &elemObj); + char const *vstr = TclGetStringFromObj(valueObj, &vlen); char const *estr = elemObj ? TclGetStringFromObj(elemObj, &elen) : ""; + if (boolResult) { *boolResult = (elen == vlen) ? (memcmp(estr, vstr, elen) == 0) : 0; } -- cgit v0.12 From 1ce5d3750ae59ed681763f17e204045c835775c2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 12 Apr 2024 16:41:00 +0000 Subject: In Tcl 9, we don't need "-encoding utf-8" here any more --- library/safe.tcl | 4 ++-- unix/Makefile.in | 2 +- win/Makefile.in | 2 +- win/makefile.vc | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/safe.tcl b/library/safe.tcl index 80bb227..cc4a194 100644 --- a/library/safe.tcl +++ b/library/safe.tcl @@ -623,14 +623,14 @@ proc ::safe::InterpInit { # other procedures defined: if {[catch {::interp eval $child { - source -encoding utf-8 [file join $tcl_library init.tcl] + source [file join $tcl_library init.tcl] }} msg opt]} { Log $child "can't source init.tcl ($msg)" return -options $opt "can't source init.tcl into child $child ($msg)" } if {[catch {::interp eval $child { - source -encoding utf-8 [file join $tcl_library tm.tcl] + source [file join $tcl_library tm.tcl] }} msg opt]} { Log $child "can't source tm.tcl ($msg)" return -options $opt "can't source tm.tcl into child $child ($msg)" diff --git a/unix/Makefile.in b/unix/Makefile.in index e06f749..801a3f5 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -2488,7 +2488,7 @@ html-tk: ${NATIVE_TCLSH} @EXTRA_BUILD_HTML@ BUILD_HTML = \ - @${NATIVE_TCLSH} -encoding utf-8 $(TOOL_DIR)/tcltk-man2html.tcl \ + @${NATIVE_TCLSH} $(TOOL_DIR)/tcltk-man2html.tcl \ --useversion=$(MAJOR_VERSION).$(MINOR_VERSION) \ --htmldir="$(HTML_INSTALL_DIR)" \ --srcdir=$(TOP_DIR) $(BUILD_HTML_FLAGS) diff --git a/win/Makefile.in b/win/Makefile.in index 799c584..14e518e 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -1020,7 +1020,7 @@ runtest: tcltest # `make shell SCRIPT=foo.tcl` shell: binaries @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ - $(WINE) ./$(TCLSH) -encoding utf-8 $(SCRIPT) + $(WINE) ./$(TCLSH) $(SCRIPT) # This target can be used to run tclsh inside either gdb or insight gdb: binaries diff --git a/win/makefile.vc b/win/makefile.vc index 261e0a2..152fc1e 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -734,7 +734,7 @@ CHMFILE=$(HTMLDIR)\$(HTMLBASE).chm htmlhelp: chmsetup $(CHMFILE) $(CHMFILE): $(DOCDIR)\* - @$(TCLSH) -encoding utf-8 $(TOOLSDIR)\tcltk-man2html.tcl "--htmldir=$(HTMLDIR)" + @$(TCLSH) $(TOOLSDIR)\tcltk-man2html.tcl "--htmldir=$(HTMLDIR)" @echo Compiling HTML help project -"$(HHC)" <<$(HHPFILE) >NUL [OPTIONS] -- cgit v0.12 From 104ed642d8bffb3165f77e197e1e46b72e4d9c82 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Fri, 12 Apr 2024 17:15:54 +0000 Subject: Add missing documentation for TIP 598 Tcl_WinConvertError --- doc/SetErrno.3 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/SetErrno.3 b/doc/SetErrno.3 index abed74e..877a362 100644 --- a/doc/SetErrno.3 +++ b/doc/SetErrno.3 @@ -8,7 +8,7 @@ .so man.macros .BS .SH NAME -Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg \- manipulate errno to store and retrieve error codes +Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg, Tcl_WinConvertError \- manipulate errno to store and retrieve error codes .SH SYNOPSIS .nf \fB#include \fR @@ -23,11 +23,17 @@ const char * .sp const char * \fBTcl_ErrnoMsg\fR(\fIerrorCode\fR) +.sp +void +\fBTcl_WinConvertError\fR(\fIwinErrorCode\fR) .fi .SH ARGUMENTS .AS int errorCode .AP int errorCode in A POSIX error code such as \fBENOENT\fR. +.AS unsigned int winErrorCode in +.AP DWORD winErrorCode in +A Windows or Winsock error code such as \fBERROR_FILE_NOT_FOUND\fR. .BE .SH DESCRIPTION @@ -60,6 +66,9 @@ that corresponds to the value of its typically the value returned by \fBTcl_GetErrno\fR. The strings returned by these functions are statically allocated and the caller must not free or modify them. +.PP +\fBTcl_WinConvertError\fR (Windows only) maps the passed Windows or Winsock +error code to a POSIX error and stores it in \fBerrno\fR. .SH KEYWORDS errno, error code, global variables -- cgit v0.12 From ad2e0465fe3118c3fd64465388032790663abca3 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 12 Apr 2024 19:24:12 +0000 Subject: One added line that ends the "Conditional jump" errors from valgrind --- generic/tclClockFmt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 40c6c92..8e99f20 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -560,6 +560,7 @@ ClockFmtScnStorageAllocProc( memset(fss, 0, sizeof(*fss)); hPtr = HashEntry4FmtScn(fss); + hPtr->key.oneWordValue = 0; /* See Ticket [167e0635db] */ memcpy(&hPtr->key.string, string, size); hPtr->clientData = 0; /* currently unused */ -- cgit v0.12 From a4f2ba7f4857c10ed2f89c8db768a544b1dc1520 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 12 Apr 2024 19:37:02 +0000 Subject: A crude protection against accessing the storage after it has been freed by a finalization pass. There are probably better fixes, but this silences the valgrind memory errors. --- generic/tclClockFmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 8e99f20..e63b642 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -679,7 +679,7 @@ ClockFmtObj_FreeInternalRep( Tcl_Obj *objPtr) { ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr); - if (fss != NULL) { + if (fss != NULL && initialized) { Tcl_MutexLock(&ClockFmtMutex); /* decrement object reference count of format/scan storage */ if (--fss->objRefCount <= 0) { -- cgit v0.12 From 8b170cfd056cd0ee91a4dac3a181c2ab3ba581a4 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 12 Apr 2024 19:47:04 +0000 Subject: Plug memory leak of the mcLiterals field. --- generic/tclClock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/generic/tclClock.c b/generic/tclClock.c index 6bb85f4..5bfb7c4 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -352,6 +352,7 @@ ClockDeleteCmdProc( for (i = 0; i < MCLIT__END; ++i) { Tcl_DecrRefCount(data->mcLiterals[i]); } + Tcl_Free(data->mcLiterals); data->mcLiterals = NULL; } if (data->mcLitIdxs != NULL) { -- cgit v0.12 From 1443b389750d24693a94978a8665ae6813e8c01d Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 12 Apr 2024 19:51:09 +0000 Subject: Plug mem leak of mcLitIdxs field. --- generic/tclClock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/generic/tclClock.c b/generic/tclClock.c index 5bfb7c4..7fc18a6 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -359,6 +359,7 @@ ClockDeleteCmdProc( for (i = 0; i < MCLIT__END; ++i) { Tcl_DecrRefCount(data->mcLitIdxs[i]); } + Tcl_Free(data->mcLitIdxs); data->mcLitIdxs = NULL; } -- cgit v0.12 From 42dcfe9f62c31bcf0543c3c1b3316fc28543f6e9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 12 Apr 2024 21:40:07 +0000 Subject: Add missing documentation for TIP 598 Tcl_WinConvertError --- doc/SetErrno.3 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/SetErrno.3 b/doc/SetErrno.3 index c202e2e..84d7553 100644 --- a/doc/SetErrno.3 +++ b/doc/SetErrno.3 @@ -8,7 +8,7 @@ .so man.macros .BS .SH NAME -Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg \- manipulate errno to store and retrieve error codes +Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg, Tcl_WinConvertError \- manipulate errno to store and retrieve error codes .SH SYNOPSIS .nf \fB#include \fR @@ -25,10 +25,16 @@ const char * const char * \fBTcl_ErrnoMsg\fR(\fIerrorCode\fR) .sp +void +\fBTcl_WinConvertError\fR(\fIwinErrorCode\fR) +.fi .SH ARGUMENTS .AS int errorCode .AP int errorCode in A POSIX error code such as \fBENOENT\fR. +.AS unsigned int winErrorCode in +.AP DWORD winErrorCode in +A Windows or Winsock error code such as \fBERROR_FILE_NOT_FOUND\fR. .BE .SH DESCRIPTION @@ -61,6 +67,9 @@ that corresponds to the value of its typically the value returned by \fBTcl_GetErrno\fR. The strings returned by these functions are statically allocated and the caller must not free or modify them. +.PP +\fBTcl_WinConvertError\fR (Windows only) maps the passed Windows or Winsock +error code to a POSIX error and stores it in \fBerrno\fR. .SH KEYWORDS errno, error code, global variables -- cgit v0.12 From b2b727664fc2a795f46b585a2a54412321115e81 Mon Sep 17 00:00:00 2001 From: sebres Date: Sun, 14 Apr 2024 13:32:04 +0000 Subject: revert [0e273ad998f16100], because of bug-fix in tclHash --- generic/tclClockFmt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index e63b642..1a506a9 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -560,7 +560,6 @@ ClockFmtScnStorageAllocProc( memset(fss, 0, sizeof(*fss)); hPtr = HashEntry4FmtScn(fss); - hPtr->key.oneWordValue = 0; /* See Ticket [167e0635db] */ memcpy(&hPtr->key.string, string, size); hPtr->clientData = 0; /* currently unused */ -- cgit v0.12 From 290472a0a3a1f31ff589eac3d5c9242f7d68bb80 Mon Sep 17 00:00:00 2001 From: sebres Date: Sun, 14 Apr 2024 13:46:23 +0000 Subject: amend to [40f13c108666fdda]: although it is no one free to see after ClockFrmScnFinalize, it is better protected in that way (and also avoid delete hash entry during table deletion). --- generic/tclClockFmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 1a506a9..156e4d2 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -3553,8 +3553,8 @@ ClockFrmScnFinalize( ClockFmtScnStorage_GC.count = 0; #endif if (initialized) { - Tcl_DeleteHashTable(&FmtScnHashTable); initialized = 0; + Tcl_DeleteHashTable(&FmtScnHashTable); } Tcl_MutexUnlock(&ClockFmtMutex); Tcl_MutexFinalize(&ClockFmtMutex); -- cgit v0.12 From 1f20b318d467ba5648dba9462d98d727219e374e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 14 Apr 2024 14:31:55 +0000 Subject: Some int -> Tcl_Size changes --- generic/tclClock.c | 16 ++++++++-------- generic/tclClockFmt.c | 22 +++++++++++----------- generic/tclStrIdxTree.c | 8 ++++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 5876114..64bf57f 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -193,9 +193,9 @@ TclClockInit( * Create the client data, which is a refcounted literal pool. */ - data = (ClockClientData *) ckalloc(sizeof(ClockClientData)); + data = (ClockClientData *)ckalloc(sizeof(ClockClientData)); data->refCount = 0; - data->literals = (Tcl_Obj **) ckalloc(LIT__END * sizeof(Tcl_Obj*)); + data->literals = (Tcl_Obj **)ckalloc(LIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < LIT__END; ++i) { TclInitObjRef(data->literals[i], Tcl_NewStringObj( Literals[i], TCL_AUTO_LENGTH)); @@ -722,7 +722,7 @@ ClockMCDict( /* check or obtain mcDictObj (be sure it's modifiable) */ if (opts->mcDictObj == NULL || opts->mcDictObj->refCount > 1) { - int ref = 1; + Tcl_Size ref = 1; /* first try to find locale catalog dict */ if (dataPtr->mcDicts == NULL) { @@ -888,7 +888,7 @@ ClockMCSetIdx( if (dataPtr->mcLitIdxs == NULL) { int i; - dataPtr->mcLitIdxs = (Tcl_Obj **) ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); + dataPtr->mcLitIdxs = (Tcl_Obj **)ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { TclInitObjRef(dataPtr->mcLitIdxs[i], Tcl_NewStringObj(MsgCtLitIdxs[i], TCL_AUTO_LENGTH)); @@ -967,7 +967,7 @@ ClockConfigureObjCmd( CLOCK_INIT_COMPLETE }; int optionIndex; /* Index of an option. */ - int i; + Tcl_Size i; for (i = 1; i < objc; i++) { if (Tcl_GetIndexFromObj(interp, objv[i++], options, @@ -3277,7 +3277,7 @@ ClockParseFmtScnArgs( ClockFmtScnCmdArgs *opts, /* Result vector: format, locale, timezone... */ TclDateFields *date, /* Extracted date-time corresponding base * (by scan or add) resp. clockval (by format) */ - int objc, /* Parameter count */ + Tcl_Size objc, /* Parameter count */ Tcl_Obj *const objv[], /* Parameter vector */ ClockOperation operation, /* What operation are we doing: format, scan, add */ const char *syntax) /* Syntax of the current command */ @@ -3294,7 +3294,7 @@ ClockParseFmtScnArgs( }; int optionIndex; /* Index of an option. */ int saw = 0; /* Flag == 1 if option was seen already. */ - int i, baseIdx; + Tcl_Size i, baseIdx; Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */ if (operation == CLC_OP_SCN) { @@ -4370,7 +4370,7 @@ ClockAddObjCmd( CLC_ADD_HOURS, CLC_ADD_MINUTES, CLC_ADD_SECONDS }; int unitIndex; /* Index of an option. */ - int i; + Tcl_Size i; Tcl_WideInt offs; /* even number of arguments */ diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 7517b72..ac5bb84 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -554,7 +554,7 @@ ClockFmtScnStorageAllocProc( allocsize -= sizeof(hPtr->key); } - fss = (ClockFmtScnStorage *) ckalloc(allocsize); + fss = (ClockFmtScnStorage *)ckalloc(allocsize); /* initialize */ memset(fss, 0, sizeof(*fss)); @@ -666,7 +666,7 @@ ClockFmtObj_DupInternalRep( /* if no format representation, dup string representation */ if (fss == NULL) { - copyPtr->bytes = (char *) ckalloc(srcPtr->length + 1); + copyPtr->bytes = (char *)ckalloc(srcPtr->length + 1); memcpy(copyPtr->bytes, srcPtr->bytes, srcPtr->length + 1); copyPtr->length = srcPtr->length; } @@ -733,7 +733,7 @@ ClockFmtObj_UpdateString( } len = strlen(name); objPtr->length = len++, - objPtr->bytes = (char *) attemptckalloc(len); + objPtr->bytes = (char *)attemptckalloc(len); if (objPtr->bytes) { memcpy(objPtr->bytes, name, len); } @@ -2123,7 +2123,7 @@ EstimateTokenCount( #define AllocTokenInChain(tok, chain, tokCnt, type) \ if (++(tok) >= (chain) + (tokCnt)) { \ - chain = (type) attemptckrealloc((char *)(chain), \ + chain = (type)attemptckrealloc((char *)(chain), \ (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \ if ((chain) == NULL) { \ goto done; \ @@ -2169,7 +2169,7 @@ ClockGetOrParseScanFormat( fss->scnSpaceCount = 0; - scnTok = tok = (ClockScanToken *) ckalloc(sizeof(*tok) * fss->scnTokC); + scnTok = tok = (ClockScanToken *)ckalloc(sizeof(*tok) * fss->scnTokC); memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { @@ -2712,13 +2712,13 @@ FrmResultAllocate( char *newRes; /* differentiate between stack and memory */ if (!FrmResultIsAllocated(dateFmt)) { - newRes = (char *) attemptckalloc(newsize); + newRes = (char *)attemptckalloc(newsize); if (newRes == NULL) { return TCL_ERROR; } memcpy(newRes, dateFmt->resMem, dateFmt->output - dateFmt->resMem); } else { - newRes = (char *) attemptckrealloc(dateFmt->resMem, newsize); + newRes = (char *)attemptckrealloc(dateFmt->resMem, newsize); if (newRes == NULL) { return TCL_ERROR; } @@ -3244,7 +3244,7 @@ ClockGetOrParseFmtFormat( /* estimate token count by % char and format length */ fss->fmtTokC = EstimateTokenCount(p, e); - fmtTok = tok = (ClockFormatToken *) ckalloc(sizeof(*tok) * fss->fmtTokC); + fmtTok = tok = (ClockFormatToken *)ckalloc(sizeof(*tok) * fss->fmtTokC); memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { @@ -3380,7 +3380,7 @@ ClockFormat( dateFmt->resMem = resMem; dateFmt->resEnd = dateFmt->resMem + sizeof(resMem); if (fss->fmtMinAlloc > sizeof(resMem)) { - dateFmt->resMem = (char *) attemptckalloc(fss->fmtMinAlloc); + dateFmt->resMem = (char *)attemptckalloc(fss->fmtMinAlloc); if (dateFmt->resMem == NULL) { return TCL_ERROR; } @@ -3505,13 +3505,13 @@ ClockFormat( result->length = dateFmt->output - dateFmt->resMem; size = result->length + 1; if (dateFmt->resMem == resMem) { - result->bytes = (char *) attemptckalloc(size); + result->bytes = (char *)attemptckalloc(size); if (result->bytes == NULL) { return TCL_ERROR; } memcpy(result->bytes, dateFmt->resMem, size); } else if ((dateFmt->resEnd - dateFmt->resMem) / size > MAX_FMT_RESULT_THRESHOLD) { - result->bytes = (char *) attemptckrealloc(dateFmt->resMem, size); + result->bytes = (char *)attemptckrealloc(dateFmt->resMem, size); if (result->bytes == NULL) { result->bytes = dateFmt->resMem; } diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index 533f73d..1c4cff3 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -252,7 +252,7 @@ TclStrIdxTreeBuildFromList( /* create lowercase reflection of the list keys */ - lwrv = (Tcl_Obj **) attemptckalloc(sizeof(Tcl_Obj*) * lstc); + lwrv = (Tcl_Obj **)attemptckalloc(sizeof(Tcl_Obj*) * lstc); if (lwrv == NULL) { return TCL_ERROR; } @@ -304,7 +304,7 @@ TclStrIdxTreeBuildFromList( * but don't split by fulfilled child of found item ( ii->iii->iiii ) */ if (foundItem->length != (f - s)) { /* first split found item (insert one between parent and found + new one) */ - item = (TclStrIdx *) attemptckalloc(sizeof(TclStrIdx)); + item = (TclStrIdx *)attemptckalloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -322,7 +322,7 @@ TclStrIdxTreeBuildFromList( } } /* append item at end of found parent */ - item = (TclStrIdx *) attemptckalloc(sizeof(TclStrIdx)); + item = (TclStrIdx *)attemptckalloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -517,7 +517,7 @@ TclStrIdxTreeTestObjCmd( case O_INDEX: case O_PUTS_INDEX: { Tcl_Obj **lstv; - int i, lstc; + Tcl_Size i, lstc; TclStrIdxTree idxTree = {NULL, NULL}; i = 1; -- cgit v0.12 From c4829502e7b25f121f85f3caaaea837c820ef6d8 Mon Sep 17 00:00:00 2001 From: sebres Date: Sun, 14 Apr 2024 14:41:35 +0000 Subject: free tz.was (in exit handler) --- generic/tclClock.c | 44 +++++++++++++++++++++++++++++++++----------- generic/tclClockFmt.c | 10 +++++----- generic/tclDate.h | 1 + 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 7fc18a6..14565ea 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -115,6 +115,7 @@ static struct tm * ThreadSafeLocalTime(const time_t *); static size_t TzsetIfNecessary(void); static void ClockDeleteCmdProc(void *); static Tcl_ObjCmdProc ClockSafeCatchCmd; +static void ClockFinalize(void *); /* * Structure containing description of "native" clock commands to create. */ @@ -180,6 +181,15 @@ TclClockInit( ClockClientData *data; int i; + static int initialized = 0; /* global clock engine initialized (in process) */ + /* + * Register handler to finalize clock on exit. + */ + if (!initialized) { + Tcl_CreateExitHandler(ClockFinalize, NULL); + initialized = 1; + } + /* * Safe interps get [::clock] as alias to a parent, so do not need their * own copies of the support routines. @@ -4640,20 +4650,21 @@ ClockSafeCatchCmd( #endif #define TZ_INIT_MARKER ((WCHAR *) INT2PTR(-1)) +typedef struct ClockTzStatic { + WCHAR *was; /* Previous value of TZ. */ + long long lastRefresh; /* Used for latency before next refresh. */ + size_t epoch; /* Epoch, signals that TZ changed. */ + size_t envEpoch; /* Last env epoch, for faster signaling, + * that TZ changed via TCL */ +} ClockTzStatic; +static ClockTzStatic tz = { /* Global timezone info; protected by + * clockMutex.*/ + TZ_INIT_MARKER, 0, 0, 0 +}; + static size_t TzsetIfNecessary(void) { - typedef struct ClockTzStatic { - WCHAR *was; /* Previous value of TZ. */ - long long lastRefresh; /* Used for latency before next refresh. */ - size_t epoch; /* Epoch, signals that TZ changed. */ - size_t envEpoch; /* Last env epoch, for faster signaling, - * that TZ changed via TCL */ - } ClockTzStatic; - static ClockTzStatic tz = { /* Global timezone info; protected by - * clockMutex.*/ - TZ_INIT_MARKER, 0, 0, 0 - }; const WCHAR *tzNow; /* Current value of TZ. */ Tcl_Time now; /* Current time. */ size_t epoch; /* The tz.epoch that the TZ was read at. */ @@ -4702,6 +4713,17 @@ TzsetIfNecessary(void) return epoch; } +static void +ClockFinalize( + TCL_UNUSED(void *)) +{ + ClockFrmScnFinalize(); + + if (tz.was && tz.was != TZ_INIT_MARKER) { + Tcl_Free(tz.was); + } +} + /* * Local Variables: * mode: c diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 156e4d2..cd4d39c 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -26,7 +26,6 @@ static void ClockFmtObj_UpdateString(Tcl_Obj *objPtr); TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */ static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss); -static void ClockFrmScnFinalize(void *); /* * Derivation of tclStringHashKeyType with another allocEntryProc @@ -832,7 +831,6 @@ FindOrCreateFmtScnStorage( &ClockFmtScnStorageHashKeyType); initialized = 1; - Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL); } /* get or create entry (and alocate storage) */ @@ -3541,10 +3539,12 @@ ClockFrmScnClearCaches(void) Tcl_MutexUnlock(&ClockFmtMutex); } -static void -ClockFrmScnFinalize( - TCL_UNUSED(void *)) +void +ClockFrmScnFinalize() { + if (!initialized) { + return; + } Tcl_MutexLock(&ClockFmtMutex); #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 /* clear GC */ diff --git a/generic/tclDate.h b/generic/tclDate.h index 1657528..fea7cbd 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -560,5 +560,6 @@ MODULE_SCOPE int ClockScan(DateInfo *info, Tcl_Obj *strObj, MODULE_SCOPE int ClockFormat(DateFormat *dateFmt, ClockFmtScnCmdArgs *opts); MODULE_SCOPE void ClockFrmScnClearCaches(void); +MODULE_SCOPE void ClockFrmScnFinalize(); #endif /* _TCLCLOCK_H */ -- cgit v0.12 From 3a4af2c98cbdaef1b77ca3e02362b11f6732633a Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 15 Apr 2024 13:21:54 +0000 Subject: clean clock mutex --- generic/tclClock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generic/tclClock.c b/generic/tclClock.c index 14565ea..817d917 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -4722,6 +4722,8 @@ ClockFinalize( if (tz.was && tz.was != TZ_INIT_MARKER) { Tcl_Free(tz.was); } + + Tcl_MutexFinalize(&clockMutex); } /* -- cgit v0.12 From 06e6507f37c70d92a9bbb7d3c24f33598f0bc846 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 17 Apr 2024 09:03:43 +0000 Subject: (cherry-pick): dup test names --- tests/clock.test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/clock.test b/tests/clock.test index 3a43017..a0b2a6a 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -18708,25 +18708,25 @@ test clock-6.10 {input of seconds - overflow} { } {1 {integer value too large to represent} {CLOCK dateTooLarge}} foreach sign {{} -} { - test clock-6.10a {input of seconds - overflow, bug [1f40aa83c5]} { + test clock-6.10a$sign {input of seconds - overflow, bug [1f40aa83c5]} { list [catch {clock scan ${sign}27670116110564327423 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""] } {1 {integer value too large to represent} {CLOCK dateTooLarge}} - test clock-6.10b {input of seconds - overflow, bug [1f40aa83c5]} { + test clock-6.10b$sign {input of seconds - overflow, bug [1f40aa83c5]} { list [catch {clock scan ${sign}27670116110564327424 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""] } {1 {integer value too large to represent} {CLOCK dateTooLarge}} - test clock-6.10c {input of seconds - no overflow, bug [1f40aa83c5]} { + test clock-6.10c$sign {input of seconds - no overflow, bug [1f40aa83c5]} { list [catch {clock scan ${sign}[string repeat 9 18] -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""] } [list 0 ${sign}[string repeat 9 18] {}] - test clock-6.10d {input of seconds - overflow, bug [1f40aa83c5]} { + test clock-6.10d$sign {input of seconds - overflow, bug [1f40aa83c5]} { list [catch {clock scan ${sign}[string repeat 9 19] -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""] } {1 {integer value too large to represent} {CLOCK dateTooLarge}} # both fololowing freescan test don't generate overflow error, # since it is a free scan, thus the token is simply not recognized further in yacc lexer, # therefore we get parse error (can be surely changed latter): - test clock-6.10e {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body { + test clock-6.10e$sign {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body { list [catch {clock scan ${sign}27670116110564327423 -gmt true} result opt] $result [dict getd $opt -errorcode ""] } -match glob -result {1 {unable to convert date-time string "*": syntax error *} {TCL VALUE DATE PARSE}} - test clock-6.10f {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body { + test clock-6.10f$sign {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body { list [catch {clock scan ${sign}27670116110564327424 -gmt true} result opt] $result [dict getd $opt -errorcode ""] } -match glob -result {1 {unable to convert date-time string "*": syntax error *} {TCL VALUE DATE PARSE}} }; unset sign @@ -18844,7 +18844,7 @@ test clock-6.21.0.1 {Stardate 0.1 - 1.9 (test negative clock value -> positive S test clock-6.21.0.2 {Stardate 10000.1 - 10002.9 (test negative clock value -> positive Stardate)} { _testStarDates [clock scan "Stardate 10000.1" -f %Q -g 1] 3 0.1 } {} -test clock-6.21.0.2 {Stardate 80000.1 - 80002.9 (test positive clock value)} { +test clock-6.21.0.3 {Stardate 80000.1 - 80002.9 (test positive clock value)} { _testStarDates [clock scan "Stardate 80001.1" -f %Q -g 1] 3 0.1 } {} test clock-6.21.1 {Stardate} { @@ -18911,7 +18911,7 @@ test clock-6.22.16 {Greedy match} { test clock-6.22.17 {Greedy match} { clock format [clock scan "111213120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1 } {Tue Dec 13 01:02:00 GMT 2011} -test clock-6.22.17 {Greedy match (space wins as date-time separator)} { +test clock-6.22.17.1 {Greedy match (space wins as date-time separator)} { clock format [clock scan "1112 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1 } {Sun Jan 02 13:12:00 GMT 2011} test clock-6.22.18 {Greedy match (second space wins as date-time separator)} { -- cgit v0.12 From f0b2e78030b03fe6c4b79b5f617c76c16f65e3b5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 17 Apr 2024 12:59:06 +0000 Subject: TIP 693: Restart the changes files. (changes.md still TODO) --- changes | 9551 ------------------------------------------------------------ changes.md | 1 + 2 files changed, 1 insertion(+), 9551 deletions(-) delete mode 100644 changes create mode 100644 changes.md diff --git a/changes b/changes deleted file mode 100644 index d9f4a44..0000000 --- a/changes +++ /dev/null @@ -1,9551 +0,0 @@ -Recent user-visible changes to Tcl: - -1. No more [command1] [command2] construct for grouping multiple -commands on a single command line. - -2. Semi-colon now available for grouping commands on a line. - -3. For a command to span multiple lines, must now use backslash-return -at the end of each line but the last. - -4. "Var" command has been changed to "set". - -5. Double-quotes now available as an argument grouping character. - -6. "Return" may be used at top-level. - -7. More backslash sequences available now. In particular, backslash-newline -may be used to join lines in command files. - -8. New or modified built-in commands: case, return, for, glob, info, -print, return, set, source, string, uplevel. - -9. After an error, the variable "errorInfo" is filled with a stack -trace showing what was being executed when the error occurred. - -10. Command abbreviations are accepted when parsing commands, but -are not recommended except for purely-interactive commands. - -11. $, set, and expr all complain now if a non-existent variable is -referenced. - -12. History facilities exist now. See Tcl.man and Tcl_RecordAndEval.man. - -13. Changed to distinguish between empty variables and those that don't -exist at all. Interfaces to Tcl_GetVar and Tcl_ParseVar have changed -(NULL return value is now possible). *** POTENTIAL INCOMPATIBILITY *** - -14. Changed meaning of "level" argument to "uplevel" command (1 now means -"go up one level", not "go to level 1"; "#1" means "go to level 1"). -*** POTENTIAL INCOMPATIBILITY *** - -15. 3/19/90 Added "info exists" option to see if variable exists. - -16. 3/19/90 Added "noAbbrev" variable to prohibit command abbreviations. - -17. 3/19/90 Added extra errorInfo option to "error" command. - -18. 3/21/90 Double-quotes now only affect space: command, variable, -and backslash substitutions still occur inside double-quotes. -*** POTENTIAL INCOMPATIBILITY *** - -19. 3/21/90 Added support for \r. - -20. 3/21/90 List, concat, eval, and glob commands all expect at least -one argument now. *** POTENTIAL INCOMPATIBILITY *** - -21. 3/22/90 Added "?:" operators to expressions. - -22. 3/25/90 Fixed bug in Tcl_Result that caused memory to get trashed. - -------------------- Released version 3.1 --------------------- - -23. 3/29/90 Fixed bug that caused "file a.b/c ext" to return ".b/c". - -24. 3/29/90 Semi-colon is not treated specially when enclosed in -double-quotes. - -------------------- Released version 3.2 --------------------- - -25. 4/16/90 Rewrote "exec" not to use select or signals anymore. -Should be more Sys-V compatible, and no slower in the normal case. - -26. 4/18/90 Rewrote "glob" to eliminate GNU code (there's no GNU code -left in Tcl, now), and added Tcl_TildeSubst procedure. Added automatic -tilde-substitution in many commands, including "glob". - -------------------- Released version 3.3 --------------------- - -27. 7/11/90 Added "Tcl_AppendResult" procedure. - -28. 7/20/90 "History" with no options now defaults to "history info" -rather than to "history redo". Although this is a backward incompatibility, -it should only be used interactively and thus shouldn't present any -compatibility problems with scripts. - -29. 7/20/90 Added "Tcl_GetInteger", "Tcl_GetDouble", and "Tcl_GetBoolean" -procedures. - -30. 7/22/90 Removed "Tcl_WatchInterp" procedure: doesn't seem to be -necessary, since the same effect can be achieved with the deletion -callbacks on individual commands. *** POTENTIAL INCOMPATIBILITY *** - -31. 7/23/90 Added variable tracing: Tcl_TraceVar, Tcl_UnTraceVar, -and Tcl_VarTraceInfo procedures, "trace" command. - -32. 8/9/90 Mailed out list of all bug fixes since 3.3 release. - -33. 8/29/90 Fixed bugs in Tcl_Merge relating to backslashes and -semi-colons. Mailed out patch. - -34. 9/3/90 Fixed bug in tclBasic.c: quotes weren't quoting ]'s. -Mailed out patch. - -35. 9/19/90 Rewrote exec to always use files both for input and -output to the process. The old pipe-based version didn't work if -the exec'ed process forked a child and then exited: Tcl waited -around for stdout to get closed, which didn't happen until the -grandchild exited. - -36. 11/5/90 ERR_IN_PROGRESS flag wasn't being cleared soon enough -in Tcl_Eval, allowing error messages from different commands to -pile up in $errorInfo. Fixed by re-arranging code in Tcl_Eval that -re-initializes result and ERR_IN_PROGRESS flag. Didn't mail out -patch: changes too complicated to describe. - -37. 12/19/90 Added Tcl_VarEval procedure as a convenience for -assembling and executing Tcl commands. - -38. 1/29/91 Fixed core leak in Tcl_AddErrorInfo. Also changed procedure -and Tcl_Eval so that first call to Tcl_AddErrorInfo need not come from -Tcl_Eval. - ------------------ Released version 5.0 with Tk ------------------ - -39. 4/3/91 Removed change bars from manual entries, leaving only those -that came after version 3.3 was released. - -40. 5/17/91 Changed tests to conform to Mary Ann May-Pumphrey's approach. - -41. 5/23/91 Massive revision to Tcl parser to simplify the implementation -of string and floating-point support in expressions. Newlines inside -[] are now treated as command separators rather than word separators -(this makes newline treatment consistent throughout Tcl). -*** POTENTIAL INCOMPATIBILITY *** - -42. 5/23/91 Massive rewrite of expression code to support floating-point -values and simple string comparisons. The C interfaces to expression -routines have changed (Tcl_Expr is replaced by Tcl_ExprLong, Tcl_ExprDouble, -etc.), but all old Tcl expression strings should be accepted by the new -expression code. -*** POTENTIAL INCOMPATIBILITY *** - -43. 5/23/91 Modified tclHistory.c to check for negative "keep" value. - -44. 5/23/91 Modified Tcl_Backslash to handle backslash-newline. It now -returns 0 to indicate that a backslash sequence should be replaced by -no character at all. -*** POTENTIAL INCOMPATIBILITY *** - -45. 5/29/91 Modified to use ANSI C function prototypes. Must set -"USE_ANSI" switch when compiling to get prototypes. - -46. 5/29/91 Completed test suite by providing tests for all of the -built-in Tcl commands. - -47. 5/29/91 Changed Tcl_Concat to eliminate leading and trailing -white-space in each of the things it concatenates and to ignore -elements that are empty or have only white space in them. This -produces cleaner output from the "concat" command. -*** POTENTIAL INCOMPATIBILITY *** - -48. 5/31/91 Changed "set" command and Tcl_SetVar procedure to return -new value of variable. - -49. 6/1/91 Added "while" and "cd" commands. - -50. 6/1/91 Changed "exec" to delete the last character of program -output if it is a newline. In most cases this makes it easier to -process program-generated output. -*** POTENTIAL INCOMPATIBILITY *** - -51. 6/1/91 Made sure that pointers are never used after freeing them. - -52. 6/1/91 Fixed bug in TclWordEnd where it wasn't dealing with -[] inside quotes correctly. - -53. 6/8/91 Fixed exec.test to accept return values of either 1 or -255 from "false" command. - -54. 7/6/91 Massive overhaul of variable management. Associative -arrays now available, along with "unset" command (and Tcl_UnsetVar -procedure). Variable traces have been completely reworked: -interfaces different both from Tcl and C, and multiple traces may -exist on same variable. Can no longer redefine existing local -variable to be global. Calling sequences have changed slightly -for Tcl_GetVar and Tcl_SetVar ("global" is now "flags"). Tcl_SetVar -can fail and return a NULL result. New forms of variable-manipulation -procedures: Tcl_GetVar2, Tcl_SetVar2, etc. Syntax of variable -$-notation changed to support array indexing. -*** POTENTIAL INCOMPATIBILITY *** - -55. 7/6/91 Added new list-manipulation procedures: Tcl_ScanElement, -Tcl_ConvertElement, Tcl_AppendElement. - -56. 7/12/91 Created new procedure Tcl_EvalFile, which does most of the -work of the "source" command. - -57. 7/20/91 Major reworking of "exec" command to allow pipelines, -more redirection, background. Added new procedures Tcl_Fork, -Tcl_WaitPids, Tcl_DetachPids, and Tcl_CreatePipeline. The old -"< input" notation has been replaced by "<< input" ("<" is for -redirection from a file). Also handles error returns and abnormal -terminations (e.g. signals) differently. -*** POTENTIAL INCOMPATIBILITY *** - -58. 7/21/91 Added "append" and "lappend" commands. - -59. 7/22/91 Reworked error messages and manual entries to use -?x? as the notation for an optional argument x, instead of [x]. The -bracket notation was often confused with the use of brackets for -command substitution. Also modified error messages to be more -consistent. - -60. 7/23/91 Tcl_DeleteCommand now returns an indication of whether -or not the command actually existed, and the "rename" command uses -this information to return an error if an attempt is made to delete -a non-existent command. -*** POTENTIAL INCOMPATIBILITY *** - -61. 7/25/91 Added new "errorCode" mechanism, along with procedures -Tcl_SetErrorCode, Tcl_UnixError, and Tcl_ResetResult. Renamed -Tcl_Return to Tcl_SetResult, but left a #define for Tcl_Return to -avoid compatibility problems. - -62. 7/26/91 Extended "case" command with alternate syntax where all -patterns and commands are together in a single list argument: makes -it easier to write multi-line case statements. - -63. 7/27/91 Changed "print" command to perform tilde-substitution on -the file name. - -64. 7/27/91 Added "tolower", "toupper", "trim", "trimleft", and "trimright" -options to "string" command. - -65. 7/29/91 Added "atime", "mtime", "size", and "stat" options to "file" -command. - -66. 8/1/91 Added "split" and "join" commands. - -67. 8/11/91 Added commands for file I/O, including "open", "close", -"read", "gets", "puts", "flush", "eof", "seek", and "tell". - -68. 8/14/91 Switched to use a hash table for command lookups. Command -abbreviations no longer have direct support in the Tcl interpreter, but -it should be possible to simulate them with the auto-load features -described below. The "noAbbrev" variable is no longer used by Tcl. -*** POTENTIAL INCOMPATIBILITY *** - -68.5 8/15/91 Added support for "unknown" command, which can be used to -complete abbreviations, auto-load library files, auto-exec shell -commands, etc. - -69. 8/15/91 Added -nocomplain switch to "glob" command. - -70. 8/20/91 Added "info library" option and TCL_LIBRARY #define. Also -added "info script" option. - -71. 8/20/91 Changed "file" command to take "option" argument as first -argument (before file name), for consistency with other Tcl commands. -*** POTENTIAL INCOMPATIBILITY *** - -72. 8/20/91 Changed format of information in $errorInfo variable: -comments such as - ("while" body line 1) -are now on separate lines from commands being executed. -*** POTENTIAL INCOMPATIBILITY *** - -73. 8/20/91 Changed Tcl_AppendResult so that it (eventually) frees -large buffers that it allocates. - -74. 8/21/91 Added "linsert", "lreplace", "lsearch", and "lsort" -commands. - -75. 8/28/91 Added "incr" and "exit" commands. - -76. 8/30/91 Added "regexp" and "regsub" commands. - -77. 9/4/91 Changed "dynamic" field in interpreters to "freeProc" (procedure -address). This allows for alternative storage managers. -*** POTENTIAL INCOMPATIBILITY *** - -78. 9/6/91 Added "index", "length", and "range" options to "string" -command. Added "lindex", "llength", and "lrange" commands. - -79. 9/8/91 Removed "index", "length", "print" and "range" commands. -"Print" is redundant with "puts", but less general, and the other -commands are replaced with the new commands described in change 78 -above. -*** POTENTIAL INCOMPATIBILITY *** - -80. 9/8/91 Changed history revision to occur even when history command -is nested; needed in order to allow "history" to be invoked from -"unknown" procedure. - -81. 9/13/91 Changed "panic" not to use vfprintf (it's uglier and less -general now, but makes it easier to run Tcl on systems that don't -have vfprintf). Also changed "strerror" not to redeclare sys_errlist. - -82. 9/19/91 Lots of changes to improve portability to different UNIX -systems, including addition of "config" script to adapt Tcl to the -configuration of the system it's being compiled on. - -83. 9/22/91 Added "pwd" command. - -84. 9/22/91 Renamed manual pages so that their filenames are no more -than 14 characters in length, moved to "doc" subdirectory. - -85. 9/24/91 Redid manual entries so they contain the supplemental -macros that they need; can just print with "troff -man" or "man" -now. - -86. 9/26/91 Created initial version of script library, including -a version of "unknown" that does auto-loading, auto-execution, and -abbreviation expansion. This library is used by tclTest -automatically. See the "library" manual entry for details. - ------------------ Released version 6.0, 9/26/91 ------------------ - -87. 9/30/91 Made "string tolower" and "string toupper" check case -before converting: on some systems, "tolower" and "toupper" assume -that character already has particular case. - -88. 9/30/91 Fixed bug in Tcl_SetResult: wasn't always setting freeProc -correctly when called with NULL value. This tended to cause memory -allocation errors later. - -89. 10/3/91 Added "upvar" command. - -90. 10/4/91 Changed "format" so that internally it converts %D to %ld, -%U to %lu, %O to %lo, and %F to %f. This eliminates some compatibility -problems on some machines without affecting behavior. - -91. 10/10/91 Fixed bug in "regsub" that caused core dumps with the -all -option when the last match wasn't at the end of the string. - -92. 10/17/91 Fixed problems with backslash sequences: \r support was -incomplete and \f and \v weren't supported at all. - -93. 10/24/91 Added Tcl_InitHistory procedure. - -94. 10/24/91 Changed "regexp" to store "-1 -1" in subMatchVars that -don't match, rather than returning an error. - -95. 10/27/91 Modified "regexp" to return actual strings in matchVar -and subMatchVars instead of indices. Added "-indices" switch to cause -indices to be returned. -*** POTENTIAL INCOMPATIBILITY *** - -96. 10/27/91 Fixed bug in "scan" where it used hardwired constants for -sizes of floats and doubles instead of using "sizeof". - -97. 10/31/91 Fixed bug in tclParse.c where parse-related error messages -weren't being storage-managed correctly, causing spurious free's. - -98. 10/31/91 Form feed and vertical tab characters are now considered -to be space characters by the parser. - -99. 10/31/91 Added TCL_LEAVE_ERR_MSG flag to procedures like Tcl_SetVar. - -100. 11/7/91 Fixed bug in "case" where "in" argument couldn't be omitted -if all case branches were embedded in a single list. - -101. 11/7/91 Switched to use "pid_t" and "uid_t" and other official -POSIC types and function prototypes. - ------------------ Released version 6.1, 11/7/91 ------------------ - -102. 12/2/91 Modified Tcl_ScanElement and Tcl_ConvertElement in several -ways. First, allowed caller to request that only backslashes be used -(no braces). Second, made Tcl_ConvertElement more aggressive in using -backslashes for braces and quotes. - -103. 12/5/91 Added "type", "lstat", and "readlink" options to "file" -command, plus added new "type" element to output of "stat" and "lstat" -options. - -104. 12/10/91 Manual entries had first lines that caused "man" program -to try weird preprocessor. Added blank comment lines to fix problem. - -105. 12/16/91 Fixed a few bugs in auto_mkindex proc: wasn't handling -errors properly, and hadn't been upgraded for new "regexp" syntax. - -106. 1/2/92 Fixed bug in "file" command where it didn't properly handle -a file names containing tildes where the indicated user doesn't exist. - -107. 1/2/92 Fixed lots of cases in tclUnixStr.c where two different -errno symbols (e.g. EWOULDBLOCK and EAGAIN) have the same number; Tcl -will only use one of them. - -108. 1/2/92 Lots of changes to configuration script to handle many more -systems more gracefully. E.g. should now detect the bogus strtoul that -comes with AIX and substitute Tcl's own version instead. - ------------------ Released version 6.2, 1/10/92 ------------------ - -109. 1/20/92 Config didn't have code to actually use "uid_t" variable -to set TCL_UIT_T #define. - -110. 2/10/92 Tcl_Eval didn't properly reset "numLevels" variable when -too-deep recursion occurred. - -111. 2/29/92 Added "on" and "off" to keywords accepted by Tcl_GetBoolean. - -112. 3/19/92 Config wasn't installing default version of strtod.c for -systems that don't have one in libc.a. - -113. 3/23/92 Fixed bug in tclExpr.c where numbers with leading "."s, -like 0.75, couldn't be properly substituted into expressions with -variable or command substitution. - -114. 3/25/92 Fixed bug in tclUnixAZ.c where "gets" command wasn't -checking to make sure that it was able to write the variable OK. - -115. 4/16/92 Fixed bug in tclUnixAZ.c where "read" command didn't -compute file size right for device files. - -116. 4/23/92 Fixed but in tclCmdMZ.c where "trace vinfo" was overwriting -the trace command. - ------------------ Released version 6.3, 5/1/92 ------------------ - -117. 5/1/92 Added Tcl_GlobalEval. - -118. 6/1/92 Changed auto-load facility to source files at global level. - -119. 6/8/92 Tcl_ParseVar wasn't always setting termPtr after errors, which -sometimes caused core dumps. - -120. 6/21/92 Fixed bug in initialization of regexp pattern cache. This -bug caused segmentation violations in regexp commands under some conditions. - -121. 6/22/92 Changed implementation of "glob" command to eliminate -trailing slashes on directory names: they confuse some systems. There -shouldn't be any user-visible changes in functionality except for names -in error messages not having trailing slashes. - -122. 7/2/92 Fixed bug that caused 'string match ** ""' to return 0. - -123. 7/2/92 Fixed bug in Tcl_CreateCmdBuf where it wasn't initializing -the buffer to an empty string. - -124. 7/6/92 Fixed bug in "case" command where it used NULL pattern string -after errors in the "default" clause. - -125. 7/25/92 Speeded up auto_load procedure: don't reread all the index -files unless the path has changed. - -126. 8/3/92 Changed tclUnix.h to define MAXPATHLEN from PATH_MAX, not -_POSIX_PATH_MAX. - ------------------ Released version 6.4, 8/7/92 ------------------ - -127. 8/10/92 Changed tclBasic.c so that comment lines can be continued by -putting a backslash before the newline. - -128. 8/21/92 Modified "unknown" to allow the source-ing of a file for -an auto-load to trigger other nested auto-loads, as long as there isn't -any recursion on the same command name. - -129. 8/25/92 Modified "format" command to allow " " and "+" flags, and -allow flags in any order. - -130. 9/14/92 Modified Tcl_ParseVar so that it doesn't actually attempt -to look up the variable if "noEval" mode is in effect in the interpreter -(it just parses the name). This avoids the errors that used to occur -in statements like "expr {[info exists foo] && $foo}". - -131. 9/14/92 Fixed bug in "uplevel" command where it didn't output the -correct error message if a level was specified but no command. - -132. 9/14/92 Renamed manual entries to have extensions like .3 and .n, -and added "install" target to Makefile. - -133. 9/18/92 Modified "unknown" command to emulate !!, !, and -^^ csh history substitutions. - -134. 9/21/92 Made the config script cleverer about figuring out which -switches to pass to "nm". - -135. 9/23/92 Fixed tclVar.c to be sure to copy flags when growing variables. -Used to forget about traces in progress and make extra recursive calls -on trace procs. - -136. 9/28/92 Fixed bug in auto_reset where it was unsetting variables -that might not exist. - -137. 10/7/92 Changed "parray" library procedure to print any array -accessible to caller, local or global. - -138. 10/15/92 Fixed bug where propagation of new environment variable -values among interpreters took N! time if there exist N interpreters. - -139. 10/16/92 Changed auto_reset procedure so that it also deletes any -existing procedures that are in the auto_load index (the assumption is -that they should be re-loaded to get the latest versions). - -140. 10/21/92 Fixed bug that caused lists to be incorrectly generated -for elements that contained backslash-newline sequences. - -141. 12/9/92 Added support for TCL_LIBRARY environment variable: use -it as library location if it's present. - -142. 12/9/92 Added "info complete" command, Tcl_CommandComplete procedure. - -143. 12/16/92 Changed the Makefile to check to make sure "config" has been -run (can't run config directly from the Makefile because it modifies the -Makefile; thus make has to be run again after running config). - ------------------ Released version 6.5, 12/17/92 ------------------ - -144. 12/21/92 Changed config to look in several places for libc file. - -145. 12/23/92 Added "elseif" support to if. Also, "then", "else", and -"elseif" may no longer be abbreviated. -*** POTENTIAL INCOMPATIBILITY *** - -146. 12/28/92 Changed "puts" and "read" to support initial "-nonewline" -switch instead of additional "nonewline" argument. The old form is -still supported, but it is discouraged and is no longer documented. -Also changed "puts" to make the file argument default to stdout: e.g. -"puts foo" will print foo on standard output. - -147. 1/6/93 Fixed bug whereby backslash-newline wasn't working when -typed interactively, or in "info complete". - -148. 1/22/93 Fixed bugs in "lreplace" and "linsert" where close -quotes were being lost from last element before replacement or -insertion. - -149. 1/29/93 Fixed bug in Tcl_AssembleCmd where it wasn't requiring -a newline at the end of a line before considering a command to be -complete. The bug caused some very long lines in script files to -be processed as multiple separate commands. - -150. 1/29/93 Various changes in Makefile to add more configuration -options, simplify installation, fix bugs (e.g. don't use -f switch -for cp), etc. - -151. 1/29/93 Changed "name1" and "name2" identifiers to "part1" and -"part2" to avoid name conflicts with stupid C++ implementations that -use "name1" and "name2" in a reserved way. - -152. 2/1/93 Added "putenv" procedure to replace the standard system -version so that it will work correctly with Tcl's environment handling. - ------------------ Released version 6.6, 2/5/93 ------------------ - -153. 2/10/93 Fixed bugs in config script: missing "endif" in libc loop, -and tried to use strncasecmp.c instead of strcasecmp.c. - -154. 2/10/93 Makefile improvements: added RANLIB variable for easier -Sys-V configuration, added SHELL variable for SGI systems. - ------------------ Released version 6.7, 2/11/93 ------------------ - -153. 2/6/93 Changes in backslash processing: - - \Cx, \Mx, \CMx, \e sequences no longer special - - \ also eats up any space after the newline, replacing - the whole sequence with a single space character - - Hex sequences like \x24 are now supported, along with ANSI C's \a. - - "format" no longer does backslash processing on its format string - - there is no longer any special meaning to a 0 return value from - Tcl_Backslash - - unknown backslash sequences, like (e.g. \*), are replaced with - the following character (e.g. *), instead of just treating the - backslash as an ordinary character. -*** POTENTIAL INCOMPATIBILITY *** - -154. 2/6/93 Updated all copyright notices. The meaning hasn't changed -at all but the wording does a better job of protecting U.C. from -liability (according to U.C. lawyers, anyway). - -155. 2/6/93 Changed "regsub" so that it overwrites the result variable -in all cases, even if there is no match. -*** POTENTIAL INCOMPATIBILITY *** - -156. 2/8/93 Added support for XPG3 %n$ conversion specifiers to "format" -command. - -157. 2/17/93 Fixed bug in Tcl_Eval where errors due to infinite -recursion could result in core dumps. - -158. 2/17/93 Improved the auto-load mechanism to deal gracefully (i.e. -return an error) with a situation where a library file that supposedly -defines a procedure doesn't actually define it. - -159. 2/17/93 Renamed Tcl_UnixError procedure to Tcl_PosixError, and -changed errorCode variable usage to use POSIX as keyword instead of -UNIX. -*** POTENTIAL INCOMPATIBILITY *** - -160. 2/19/93 Changes to exec and process control: - - Added support for >>, >&, >>&, |&, <@, >@, and >&@ forms of redirection. - - When exec puts processes into background, it returns a list of - their pids as result. - - Added support for file, etc. (i.e. no space between - ">" and file name. - - Added -keepnewline option. - - Deleted Tcl_Fork and Tcl_WaitPids procedures (just use fork and - waitpid instead). - - Added waitpid compatibility procedure for systems that don't have - it. - - Added Tcl_ReapDetachedProcs procedure. - - Changed "exec" to return an error if there is stderr output, even - if the command returns a 0 exit status (it's always been documented - this way, but the implementation wasn't correct). - - If a process returns a non-zero exit status but doesn't generate - any diagnostic output, then Tcl generates an error message for it. -*** POTENTIAL INCOMPATIBILITY *** - -161. 2/25/93 Fixed two memory-management problems having to do with -managing the old result during variable trace callbacks. - -162. 3/1/93 Added dynamic string library: Tcl_DStringInit, Tcl_DStringAppend, -Tcl_DStringFree, Tcl_DStringResult, etc. - -163. 3/1/93 Modified glob command to only return the names of files that -exist, and to only return names ending in "/" if the file is a directory. -*** POTENTIAL INCOMPATIBILITY *** - -164. 3/19/93 Modified not to use system calls like "read" directly, -but instead to use special Tcl procedures that retry automatically -if interrupted by signals. - -165. 4/3/93 Eliminated "noSep" argument to Tcl_AppendElement, plus -TCL_NO_SPACE flag for Tcl_SetVar and Tcl_SetVar2. -*** POTENTIAL INCOMPATIBILITY *** - -166. 4/3/93 Eliminated "flags" and "termPtr" arguments to Tcl_Eval. -*** POTENTIAL INCOMPATIBILITY *** - -167. 4/3/93 Changes to expressions: - - The "expr" command now accepts multiple arguments, which are - concatenated together with space separators. - - Integers aren't automatically promoted to floating-point if they - overflow the word size: errors are generated instead. - - Tcl can now handle "NaN" and other special values if the underlying - library procedures handle them. - - When printing floating-point numbers, Tcl ensures that there is a "." - or "e" in the number, so it can't be treated as an integer accidentally. - The procedure Tcl_PrintDouble is available to provide this function - in other contexts. Also, the variable "tcl_precision" can be used - to set the precision for printing (must be a decimal number giving - digits of precision). - - Expressions now support transcendental and other functions, e.g. sin, - acos, hypot, ceil, and round. Can add new math functions with - Tcl_CreateMathFunc(). - - Boolean expressions can now have any of the string values accepted - by Tcl_GetBoolean, such as "yes" or "no". -*** POTENTIAL INCOMPATIBILITY *** - -168. 4/5/93 Changed Tcl_UnsetVar and Tcl_UnsetVar2 to return TCL_OK -or TCL_ERROR instead of 0 or -1. -*** POTENTIAL INCOMPATIBILITY *** - -169. 4/5/93 Eliminated Tcl_CmdBuf structure and associated procedures; -can use Tcl_DStrings instead. -*** POTENTIAL INCOMPATIBILITY *** - -170. 4/8/93 Changed interface to Tcl_TildeSubst to use a dynamic -string for buffer space. This makes the procedure re-entrant and -thread-safe, whereas it wasn't before. -*** POTENTIAL INCOMPATIBILITY *** - -171. 4/14/93 Eliminated tclHash.h, and moved everything from it to -tcl.h -*** POTENTIAL INCOMPATIBILITY *** - -172. 4/15/93 Eliminated Tcl_InitHistory, made "history" command always -be part of interpreter. -*** POTENTIAL INCOMPATIBILITY *** - -173. 4/16/93 Modified "file" command so that "readable" option always -exists, even on machines that don't support symbolic links (always returns -same error as if the file wasn't a symbolic link). - -174. 4/26/93 Fixed bugs in "regsub" where ^ patterns didn't get handled -right (pretended not to match when it really did, and looped infinitely -if -all was specified). - -175. 4/29/93 Various improvements in the handling of variables: - - Can create variables and array elements during a read trace. - - Can delete variables during traces (note: unset traces will be - invoked when this happens). - - Can upvar to array elements. - - Can retarget an upvar to another variable by re-issuing the - upvar command with a different "other" variable. - -176. 5/3/93 Added Tcl_GetCommandInfo, which returns info about a Tcl -command such as whether it exists and its ClientData. Also added -Tcl_SetCommandInfo, which allows any of this information to be modified -and also allows a command's delete procedure to have a different -ClientData value than its command procedure. - -177. 5/5/93 Added Tcl_RegExpMatch procedure. - -178. 5/6/93 Fixed bug in "scan" where it didn't properly handle -%% conversion specifiers. Also changed "scan" to use Tcl_PrintDouble -for printing real values. - -179. 5/7/93 Added "-exact", "-glob", and "-regexp" options to "lsearch" -command to allow different kinds of pattern matching. - -180. 5/7/93 Added many new switches to "lsort" to control the sorting -process: "-ascii", "-integer", "-real", "-command", "-increasing", -and "-decreasing". - -181. 5/10/93 Changes to file I/O: - - Modified "open" command to support a list of POSIX access flags - like {WRONLY CREAT TRUNC} in addition to current fopen-style - access modes. Also added "permissions" argument to set permissions - of newly-created files. - - Fixed Scott Bolte's bug (can close stdin etc. in application and - then re-open them with Tcl commands). - - Exported access to Tcl's file table with new procedures Tcl_EnterFile - and Tcl_GetOpenFile. - -182. 5/15/93 Added new "pid" command, which can be used to retrieve -either the current process id or a list of the process ids in a -pipeline opened with "open |..." - -183. 6/3/93 Changed to use GNU autoconfig for configuration instead of -the home-brew "config" script. Also made many other configuration-related -changes, such as using instead of explicitly declaring system -calls in tclUnix.h. - -184. 6/4/93 Fixed bug where core-dumps could occur if a procedure -redefined itself (the memory for the procedure's body could get -reallocated in the middle of evaluating the body); implemented -simple reference count mechanism. - -185. 6/5/93 Changed tclIndex file format in two ways: (a) it's now -eval-ed instead of parsed, which makes it 3-4x faster; (b) the entries -in auto_index are now commands to evaluate, which allows commands to -be loaded in different ways such as dynamic-loading of C code. The -old tclIndex file format is still supported. - -186. 6/7/93 Eliminated tclTest program, added new "tclsh" program -that is more like wish (allows script files to be invoked automatically -using "#!/usr/local/bin/tclsh", makes arguments available to script, -etc.). Added support for Tcl_AppInit plus default version; this -allows new Tcl applications to be created without modifying the -main program for tclsh. - -187. 6/7/93 Fixed bug in TclWordEnd that kept backslash-newline from -working correctly in some cases during interactive input. - -188. 6/9/93 Added Tcl_LinkVar and related procedures, which automatically -keep a Tcl variable in sync with a C variable. - -189. 6/16/93 Increased maximum nesting depth from 100 to 1000. - -190. 6/16/93 Modified "trace var" command so that error messages from -within traces are returned properly as the result of the variable -access, instead of the generic "access disallowed by trace command" -message. - -191. 6/16/93 Added Tcl_CallWhenDeleted to provide callbacks when an -interpreter is deleted (same functionality as Tcl_WatchInterp, which -used to exist in versions before 6.0). - -193. 6/16/93 Added "-code" argument to "return" command; it's there -primarily for completeness, so that procedures implementing control -constructs can reflect exceptional conditions back to their callers. - -194. 6/16/93 Split up Tcl.n to make separate manual entries for each -Tcl command. Tcl.n now contains a summary of the language syntax. - -195. 6/17/93 Added new "switch" command to replace "case": allows -alternate forms of pattern matching (exact, glob, regexp), replaces -pattern lists with single patterns (but you can use "-" bodies to -share one body among several patterns), eliminates "in" noise word. -"Case" command is now obsolete. - -196. 6/17/93 Changed the "exec", "glob", "regexp", and "regsub" commands -to include a "--" switch. All initial arguments starting with "-" are now -treated as switches unless a "--" switch is present to end the list. -*** POTENTIAL INCOMPATIBILITY *** - -197. 6/17/93 Changed auto-exec so that the subprocess gets stdin, stdout, -and stderr from the parent. This allows truly interactive sub-processes -(e.g. vi) to be auto-exec'ed from a tcl shell command line. - -198. 6/18/93 Added patchlevel.h, for use in coordinating future patch -releases, and also added "info patchlevel" command to make the patch -level available to Tcl scripts. - -199. 6/19/93 Modified "glob" command so that a leading "//" in a name -gets left as is (this is needed for systems like Apollos where "//" is -the super-root; Tcl used to collapse the two slashes into a single -slash). - -200. 7/7/93 Added Tcl_SetRecursionLimit procedure so that the maximum -allowable nesting depth can be controlled for an interpreter from C. - ------------------ Released version 7.0 Beta 1, 7/9/93 ------------------ - -201. 7/12/93 Modified Tcl_GetInt and tclExpr.c so that full-precision -unsigned integers can be specified without overflow errors. - -202. 7/12/93 Configuration changes: eliminate leading blank line in -configure script; provide separate targets in Makefile for installing -binary and non-binary information; check for size_t and a few other -potentially missing typedefs; don't put tclAppInit.o into libtcl.a; -better checks for matherr support. - -203. 7/14/93 Changed tclExpr.c to check the termination pointer before -errno after strtod calls, to avoid problems with some versions of -strtod that set errno in unexpected ways. - -204. 7/16/93 Changed "scan" command to be more ANSI-conformant: -eliminated %F, %D, etc., added code to ignore "l", "h", and "L" -modifiers but always convert %e, %f, and %g with implicit "l"; -also added support for %u and %i. Also changed "format" command -to eliminate %D, %U, %O, and add %i. -*** POTENTIAL INCOMPATIBILITY *** - -205. 7/17/93 Changed "uplevel" and "upvar" so that they can be used -from global level to global level: this used to generate an error. - -206. 7/19/93 Renamed "setenv", "putenv", and "unsetenv" procedures -to avoid conflicts with system procedures with the same names. If -you want Tcl's procedures to override the system procedures, do it -in the Makefile (instructions are in the Makefile). -*** POTENTIAL INCOMPATIBILITY *** - ------------------ Released version 7.0 Beta 2, 7/21/93 ------------------ - -207. 7/21/93 Fixed bug in tclVar.c where freed memory was accidentally -used if a procedure returned an element of a local array. - -208. 7/22/93 Fixed bug in "unknown" where it didn't properly handle -errors occurring in the "auto_load" procedure, leaving its state -inconsistent. - -209. 7/23/93 Changed exec's ">2" redirection operator to "2>" for -consistency with sh. This is incompatible with earlier beta releases -of 7.0 but not with pre-7.0 releases, which didn't support either -operator. - -210. 7/28/93 Changed backslash-newline handling so that the resulting -space character *is* treated as a word separator unless the backslash -sequence is in quotes or braces. This is incompatible with 7.0b1 -and 7.0b2 but is more compatible with pre-7.0 versions that the b1 -and b2 releases were. - -211. 7/28/93 Eliminated Tcl_LinkedVarWritable, added TCL_LINK_READ_ONLY to -Tcl_LinkVar to accomplish same purpose. This change is incompatible -with earlier beta releases, but not with releases before Tcl 7.0. - -212. 7/29/93 Renamed regexp C functions so they won't clash with POSIX -regexp functions that use the same name. - -213. 8/3/93 Added "-errorinfo" and "-errorcode" options to "return" -command: these allow for much better handling of the errorInfo -and errorCode variables in some cases. - -214. 8/12/93 Changed "expr" so that % always returns a remainder with -the same sign as the divisor and absolute value smaller than the -divisor. - -215. 8/14/93 Turned off auto-exec in "unknown" unless the command -was typed interactively. This means you must use "exec" when -invoking subprocesses, unless it's a command that's typed interactively. -*** POTENTIAL INCOMPATIBILITY *** - -216. 8/14/93 Added support for tcl_prompt1 and tcl_prompt2 variables -to tclMain.c: makes prompts user-settable. - -217. 8/14/93 Added asynchronous handlers (Tcl_AsyncCreate etc.) so -that signals can be taken cleanly by Tcl applications. - -218. 8/16/93 Moved information about open files from the interpreter -structure to global variables so that a file can be opened in one -interpreter and read or written in another. - -219. 8/16/93 Removed ENV_FLAGS from Makefile, so that there's no -official support for overriding setenv, unsetenv, and putenv. - -220. 8/20/93 Various configuration improvements: coerce chars -to unsigned chars before using macros like isspace; source ~/.tclshrc -file during initialization if it exists and program is running -interactively; allow there to be directories in auto_path that don't -exist or don't have tclIndex files (ignore them); added Tcl_Init -procedure and changed Tcl_AppInit to call it. - -221. 8/21/93 Fixed bug in expr where "+", "-", and " " were all -getting treated as integers with value 0. - -222. 8/26/93 Added "tcl_interactive" variable to tclsh. - -223. 8/27/93 Added procedure Tcl_FilePermissions to return whether a -given file can be read or written or both. Modified Tcl_EnterFile -to take a permissions mask rather than separate read and write arguments. - -224. 8/28/93 Fixed performance bug in "glob" command (unnecessary call -to "access" for each file caused a 5-10x slow-down for big directories). - ------------------ Released version 7.0 Beta 3, 8/28/93 ------------------ - -225. 9/9/93 Renamed regexp.h to tclRegexp.h to avoid conflicts with system -include file by same name. - -226. 9/9/93 Added Tcl_DontCallWhenDeleted. - -227. 9/16/93 Changed not to call exit C procedure directly; instead -always invoke "exit" Tcl command so that application can redefine the -command to do additional cleanup. - -228. 9/17/93 Changed auto-exec to handle names that contain slashes -(i.e. don't use PATH for them). - -229. 9/23/93 Fixed bug in "read" and "gets" commands where they didn't -clear EOF conditions. - ------------------ Released version 7.0, 9/29/93 ------------------ - -230. 10/7/93 "Scan" command wasn't properly aligning things in memory, -so segmentation faults could arise under some circumstances. - -231. 10/7/93 Fixed bug in Tcl_ConvertElement where it forgot to -backslash leading curly brace when creating lists. - -232. 10/7/93 Eliminated dependency of tclMain.c on tclInt.h and -tclUnix.h, so that people can copy the file out of the Tcl source -directory to make modified private versions. - -233. 10/8/93 Fixed bug in auto-loader that reversed the priority order -of entries in auto_path for new-style index files. Now things are -back to the way they were before 3.0: first in auto_path is always -highest priority. - -234. 10/13/93 Fixed bug where Tcl_CommandComplete didn't recognize -comments and treat them as such. Thus if you typed the line - # { -interactively, Tcl would think that the command wasn't complete and -wait for more input before evaluating the script. - -235. 10/14/93 Fixed bug where "regsub" didn't set the output variable -if the input string was empty. - -236. 10/23/93 Fixed bug where Tcl_CreatePipeline didn't close off enough -file descriptors in child processes, causing children not to exit -properly in some cases. - -237. 10/28/93 Changed "list" and "concat" commands not to generate -errors if given zero arguments, but instead to just return an empty -string. - ------------------ Released version 7.1, 11/4/93 ------------------ - -Note: there is no 7.2 release. It was flawed and was thus withdrawn -shortly after it was released. - -238. 11/10/93 TclMain.c didn't compile on some systems because of -R_OK in call to "access". Changed to eliminate call to "access". - ------------------ Released version 7.3, 11/26/93 ------------------ - -239. 11/6/93 Modified "lindex", "linsert", "lrange", and "lreplace" -so that "end" can be specified as an index. - -240. 11/6/93 Modified "append" and "lappend" to allow only two -words total (i.e., nothing to append) without generating an error. - -241. 12/2/93 Changed to use EAGAIN as the errno for non-blocking -I/O instead of EWOULDBLOCK: this should fix problem where non-blocking -I/O didn't work correctly on System-V systems. - -242. 12/22/93 Fixed bug in expressions where cancelled evaluation -wasn't always working correctly (e.g. "set one 1; eval {1 || 1/$one}" -failed with a divide by zero error). - -243. 1/6/94 Changed TCL_VOLATILE definition from -1 to the address of -a dummy procedure Tcl_Volatile, since -1 causes portability problems on -some machines (e.g., Crays). - -244. 2/4/94 Added support for unary plus. - -245. 2/17/94 Changed Tcl_RecordAndEval and "history" command to -call Tcl_GlobalEval instead of Tcl_Eval. Otherwise, invocation of -these facilities in nested procedures can cause unwanted results. - -246. 2/17/94 Fixed bug in tclExpr.c where an expression such as -"expr {"12398712938788234-1298379" != ""}" triggers an integer -overflow error for the number in quotes, even though it isn't really -a proper integer anyway. - -247. 2/19/94 Added new procedure Tcl_DStringGetResult to move result -from interpreter to a dynamic string. - -248. 2/19/94 Fixed bug in Tcl_DStringResult that caused it to overwrite -the contents of a static result in some situations. This can cause -bizarre errors such as variables suddenly having empty values. - -249. 2/21/94 Fixed bug in Tcl_AppendElement, Tcl_DStringAppendElement, -and the "lappend" command that caused improper omission of a separator -space in some cases. For example, the script - set x "abc{"; lappend x "def" -used to return the result "abc{def" instead of "abc{ def". - -250. 3/3/94 Tcl_ConvertElement was outputting empty elements as \0 if -TCL_DONT_USE_BRACES was set. This depends on old pre-7.0 meaning of -\0, which is no longer in effect, so it didn't really work. Changed -to output empty elements as {} always. - -251. 3/3/94 Renamed Tcl_DStringTrunc to Tcl_DStringSetLength and extended -it so that it can be used to lengthen a string as well as shorten it. -Tcl_DStringTrunc is defined as a macro for backward compatibility, but -it is deprecated. - -252. 3/3/94 Added Tcl_AllowExceptions procedure. - -253. 3/13/94 Fixed bug in Tcl_FormatCmd that could cause "format" -to mis-behave on 64-bit Big-Endian machines. - -254. 3/13/94 Changed to use vfork instead of fork on systems where -vfork exists. - -255. 3/23/94 Fixed bug in expressions where ?: didn't associate -right-to-left as they should. - -256. 4/3/94 Fixed "exec" to flush any files used in >@ or >&@ -redirection in exec, so that data buffered for them is written -before any new data added by the subprocess. - -257. 4/3/94 Added "subst" command. - -258. 5/20/94 The tclsh main program is now called Tcl_Main; tclAppInit.c -has a "main" procedure that calls Tcl_Main. This makes it easier to use -Tcl with C++ programs, which need their own main programs, and it also -allows an application to prefilter the argument list before calling -Tcl_Main. -*** POTENTIAL INCOMPATIBILITY *** - -259. 6/6/94 Fixed bug in procedure returns where the errorInfo variable -could get truncated if an unset trace was invoked as part of returning -from the procedure. - -260. 6/13/94 Added "wordstart" and "wordend" options to "string" command. - -261. 6/27/94 Fixed bug in expressions where they didn't properly cancel -the evaluation of math functions in &&, ||, and ?:. - -262. 7/11/94 Incorrect boolean values, like "ogle", weren't being -handled properly. - -263. 7/15/94 Added Tcl_RegExpCompile, Tcl_RegExpExec, and Tcl_RegExpRange, -which provide lower-level access to regular expression pattern matching. - -264. 7/22/94 Fixed bug in "glob" command where "glob -nocomplain ~bad_user" -would complain about a missing user. Now it doesn't complain anymore. - -265. 8/4/94 Fixed bug with linked variables where they didn't behave -correctly when accessed via upvars. - -266. 8/17/94 Fixed bug in Tcl_EvalFile where it didn't clear interp->result. - -267. 8/31/94 Modified "open" command so that errors in exec-ing -subprocesses are returned by the open immediately, rather than -being delayed until the "close" is executed. - -268. 9/9/94 Modified "expr" command to generate errors for integer -overflow (includes addition, subtraction, negation, multiplication, -division). - -269. 9/23/94 Modified "regsub" to return a count of the number of -matches and replacements, rather than 0/1. - -279. 10/4/94 Added new features to "array" command: - - added "get" and "set" commands for easy conversion between arrays - and lists. - - added "exists" command to see if a variable is an array, changed - "names" and "size" commands to treat a non-existent array (or scalar - variable) just like an empty one. - - added pattern option to "names" command. - -280. 10/6/94 Modified Tcl_SetVar2 so that read traces on variables get -called during append operations. - -281. 10/20/94 Fixed bug in "read" command where reading from stdin -required two control-D's to stop the reading. - -282. 11/3/94 Changed "expr" command to use longs for division just like -all other expr operators; it previously used ints for division. - -283. 11/4/94 Fixed bugs in "unknown" procedure: it wasn't properly -handling exception returns from commands that were executed after -being auto-loaded. - ------------------ Released version 7.4b1, 12/23/94 ------------------ - -284. 12/26/94 Fixed "install" target in Makefile (couldn't always -find install program). - -285. 12/26/94 Added strcncasecmp procedure to compat directory. - -286. 1/3/95 Fixed all procedure calls to explicitly cast arguments: -implicit conversions from prototypes (especially integer->double) -don't work when compiling under non-ANSI compilers. Tcl is now clean -under gcc -Wconversion. - -287. 1/4/95 Fixed problem in Tcl_ArrayCmd where same name was used for -both a label and a variable; caused problems on several older compilers, -making array command misbehave and causing many errors in Tcl test suite. - ------------------ Released version 7.4b2, 1/12/95 ------------------ - -288. 2/9/95 Modified Tcl_CreateCommand to return a token, and added -Tcl_GetCommandName procedure. Together, these procedures make it possible -to track renames of a command. - -289. 2/13/95 Fixed bug in expr where "089" was interpreted as a -floating-point number rather than a bogus octal number. -*** POTENTIAL INCOMPATIBILITY *** - -290. 2/14/95 Added code to Tcl_GetInt and Tcl_GetDouble to check for -overflows when reading in numbers. - -291. 2/18/95 Changed "array set" to stop after first error, rather than -continuing after error. - -292. 2/20/95 Upgraded to use autoconf version 2.2. - -293. 2/20/95 Fixed core dump that could occur in "scan" command if a -close bracket was omitted. - -294. 2/27/95 Changed Makefile to always use install-sh for installations: -there's just too much variation among "install" system programs, which -makes installation flakey. - ------------------ Released version 7.4b3, 3/24/95 ------------------ - -3/25/95 (bug fix) Changed "install" to "./install" in Makefile so that -"make install" will work even when "." isn't in the search path. - -3/29/95 (bug fix) Fixed bug where the auto-loading mechanism wasn't -protecting the values of the errorCode and errorInfo variables. - -3/29/95 (new feature) Added optional pattern argument to "parray" procedure. - -3/29/95 (bug fix) Made the full functionality of - "return -code ... -errorcode ..." -work not just inside procedures, but also in sourced files and at -top level. - -4/6/95 (new feature) Added "pattern" option to "array names" command. - -4/18/95 (bug fix) Fixed bug in parser where it didn't allow backslash-newline -immediately after an argument in braces or quotes. - -4/19/95 (new feature) Added tcl_library variable, which application can -set to override default library directory. - -4/30/95 (bug fix) During trace callbacks for array elements, the variable -name used in the original reference would be temporarily modified to -separate the array name and element name; if the trace callback used -the same name string, it would get the wrong name (the array name without -element). Fixed to restore the variable name before making trace -callbacks. - -4/30/95 (new feature) Added -nobackslashes, -nocommands, and -novariables -switches to "subst" command. - -5/4/95 (new feature) Added TCL_EVAL_GLOBAL flag to Tcl_RecordAndEval. - -5/5/95 (bug fix) Format command would overrun memory when printing -integers with very large precision, as in "format %.1000d 0". - -5/5/95 (portability improvement) Changed to use BSDgettimeofday on -IRIX machines, to avoid compilation problems with the gettimeofday -declaration. - -5/6/95 (bug fix) Changed manual entries to use the standard .TH -macro instead of a custom .HS macro; the .HS macro confuses index -generators like makewhatis. - -5/9/95 (bug fix) Modified configure script to check for Solaris bug -that makes vfork unreliable (core dumps result if vforked child -changes a signal handler); will use fork instead of vfork if the -bug is present. - -6/5/95 (bug fix) Modified "lsort" command to disallow recursive calls -to lsort from a comparison function. This is needed because qsort -is not reentrant. - -6/5/95 (bug fix) Undid change 243 above: changed TCL_VOLATILE and -TCL_DYNAMIC back to integer constants rather than procedure addresses. -This was needed because procedure addresses can have multiple values -under some dynamic loading systems (e.g. SunOS 4.1 and Windows). - -6/8/95 (feature change) Modified interface to Tcl_Main to pass in the -address of the application-specific initialization procedure. -Tcl_AppInit is no longer hardwired into Tcl_Main. This is needed -in order to make Tcl a shared library. - -6/8/95 (feature change) Modified Makefile so that the installed versions -of tclsh and libtcl.a have version number in them (e.g. tclsh7.4 and -libtcl7.4.a) and the library directory name also has an embedded version -number (e.g., /usr/local/lib/tcl7.4). This should make it easier for -Tcl 7.4 to coexist with earlier versions. - ------------------ Released version 7.4b4, 6/16/95 ------------------ - -6/19/95 (bug fix) Fixed bugs in tclCkalloc.c that caused core dumps -if TCL_MEM_DEBUG was enabled on word-addressed machines such as Crays. - -6/21/95 (feature removal) Removed overflow checks for integer arithmetic: -they just cause too much trouble (e.g. for random number generators). - -6/28/95 (new features) Added tcl_patchLevel and tcl_version variables, -for consistency with Tk. - -6/29/95 (bug fix) Fixed problem in Tcl_Eval where it didn't record -the right termination character if a script ended with a comment. This -caused erroneous output for the following command, among others: -puts "[ -expr 1+1 -# duh! -]" - -6/29/95 (message change) Changed the error message for ECHILD slightly -to provide a hint about why the problem is occurring. - ------------------ Released version 7.4, 7/1/95 ------------------ - -7/18/95 (bug fix) Changed "lreplace" so that nothing is deleted if -the last index is less than the first index or if the last index -is < 0. - -7/18/95 (bug fix) Fixed bugs with backslashes in comments: -Tcl_CommandComplete (and "info complete") didn't properly handle -strings ending in backslash-newline, and neither Tcl_CommandComplete -nor the Tcl parser handled other backslash sequences right, such -as two backslashes before a newline. - -7/19/95 (bug fix) Modified Tcl_DeleteCommand to delete the hash table -entry for the command before invoking its callback. This is needed in -order to deal with reentrancy. - -7/22/95 (bug fix) "exec" wasn't reaping processes correctly after -certain errors (e.g. if the name of the executable was bogus, as -in "exec foobar"). - -7/27/95 (bug fix) Makefile.in wasn't using the LIBS variable provided -by the "configure" script. This caused problems on some SCO systems. - -7/27/95 (bug fix) The version of strtod in fixstrtod.c didn't properly -handle the case where endPtr == NULL. - ------------------ Released patch 7.4p1, 7/29/95 ----------------------- - -8/4/95 (bug fix) C-level trace callbacks for variables were sometimes -receiving the PART1_NOT_PARSED flag, which could cause errors in -subsequent Tcl library calls using the flags. (JO) - -8/4/95 (bug fix) Calls to toupper and tolower weren't using the -UCHAR macros, which caused trouble in non-U.S. locales. (JO) - -8/10/95 (new feature) Added the "load" command for dynamic loading of -binary packages, and the Tcl_PackageInitProc prototype for package -initialization procedures. (JO) - -8/23/95 (new features) Added "info sharedlibextension" and -"info nameofexecutable" commands, plus Tcl_FindExtension procedure. (JO) - -8/25/95 (bug fix) If the target of an "upvar" was non-existent but -had traces set, the traces were silently lost. Change to generate -an error instead. (JO) - -8/25/95 (bug fix) Undid change from 7/19, so that commands can stay -around while their deletion callbacks execute. Added lots of code to -handle all of the reentrancy problems that this opens up. (JO) - -8/25/95 (bug fix) Fixed core dump that could occur in TclDeleteVars -if there was an upvar from one entry in the table to the next entry -in the same table. (JO) - -8/28/95 (bug fix) Exec wasn't handling bad user names properly, as -in "exec ~bogus_user/foo". (JO) - -8/29/95 (bug fixes) Changed backslash-newline handling to correct two -problems: - - Only spaces and tabs following the backslash-newline are now - absorbed as part of the backslash-newline. Newlinew are no - longer absorbed (add another backslash if you want to absorb - another newline). - - TclWordEnd returns the character just before the backslash in - the sequence as the end of the sequence; it used to not consider - the backslash-newline as a word separator. (JO) - -8/31/95 (new feature) Changed man page installation (with "mkLinks" -script) to create additional links for manual pages corresponding to -each of the procedure and command names described in the pages. (JO) - -9/10/95 Reorganized Tcl sources for Windows and Mac ports. All sources -are now in subdirectories: "generic" contains sources that work on all -platforms, "windows", "mac", and "unix" directories contain platform- -specific sources. Some UNIX sources are also used on other platforms. (SS) - -9/10/95 (feature change) Eliminated exported global variables (they -don't work with Windows DLLs). Replaced tcl_AsyncReady and -tcl_FileCloseProc with procedures Tcl_AsyncReady() and -Tcl_SetFileCloseProc(). Replaced C variable tcl_RcFileName with -a Tcl variable tcl_rcFileName. (SS) -*** POTENTIAL INCOMPATIBILITY *** - -9/11/95 (new feature) Added procedure Tcl_SetPanicProc to override -the default implementation of "panic". (SS) - -9/11/95 (new feature) Added "interp" command to allow creation of -new interpreters and execution of untrusted scripts. Added many new -procedures, such as Tcl_CreateSlave, Tcl_CreateAlias,and Tcl_MakeSafe, -to provide C-level access to the interpreter facility. This mechanism -now provides almost all of the generic functions of Borenstein's and -Rose's Safe-Tcl (but not any Tk or email-related stuff). (JL) - -9/11/95 (feature change) Changed file management so that files are -no longer shared between interpreters: a file cannot normally be -referenced in one interpreter if it was opened in another. This -feature is needed to support safe interpreters. Added Tcl_ShareHandle() -procedure for allowing files to be shared, and added "interp" argument -to Tcl_FilePermissions procedure. (JL) -*** POTENTIAL INCOMPATIBILITY *** - -9/11/95 (new feature) Added "AssocData" mechanism, whereby extensions -can associate their own data with an interpreter and get called back -when the interpreter is deleted. This is visible at C level via the -procedures Tcl_SetAssocData and Tcl_GetAssocData. (JL) - -9/11/95 (new feature) Added Tcl_ErrnoMsg to translate an errno value -into a human-readable string. This is now used instead of calling -strerror because strerror mesages vary dramatically from platform -to platform, which messes up Tcl tests. Tcl_ErrnoMsg uses the standard -POSIX messages for all the common signals, and calls strerror for -signals it doesn't understand. - ------------------ Released patch 7.4p2, 9/15/95 ----------------------- - ------------------ Released 7.5a1, 9/15/95 ----------------------- - -9/22/95 (bug fix) Changed auto_mkindex to create tclIndex files that -handle directories whose paths might contain spaces. (RJ) - -9/27/95 (bug fix) The "format" command didn't check for huge or negative -width specifiers, which could cause core dumps. (JO) - -9/27/95 (bug fix) Core dumps could occur if an interactive command typed -to tclsh returned a very long result for tclsh to print out. The bug is -actually in printf (in Solaris 2.3 and 2.4, at least); switched to use -puts instead. (JO) - -9/28/95 (bug fix) Changed makefile.bc to eliminate a false dependency -for tcl1675.dll on the Borland run time library. (SS) - -9/28/95 (bug fix) Fixed tcl75.dll so it looks for tcl1675.dll instead -of tcl16.dll. (SS) - -9/28/95 (bug fix) Tcl was not correctly detecting the difference -between Win32s and Windows '95. (SS) - -9/28/95 (bug fix) "exec" was not passing environment changes to child -processes under Windows. (SS) - -9/28/95 (bug fix) Changed Tcl to ensure that open files are not passed -to child processes under Windows. (SS) - -9/28/95 (bug fix) Fixed Windows '95 and NT versions of exec so it can -handle both console and windows apps. (SS) - -9/28/95 (bug fix) Fixed Windows version of exec so it no longer leaves -temp files lying around. Also changed it so the temp files are -created in the appropriate system dependent temp directory. (SS) - -9/28/95 (bug fix) Eliminated source dependency on the Win32s Universal -Thunk header file, since it is not bundled with VC++. (SS) - -9/28/95 (bug fix) Under Windows, Tcl now constructs the HOME -environment variable from HOMEPATH and HOMEDRIVE when HOME is not -already set. (SS) - -9/28/95 (bug fix) Added support for "info nameofexecutable" and "info -sharedlibextension" to the Windows version. (SS) - -9/28/95 (bug fix) Changed tclsh to correctly parse command line -arguments so that backslashes are preserved under Windows. (SS) - -9/29/95 (bug fix) Tcl 7.5a1 treated either return or newline as end -of line in "gets", which caused lines ending in CRLF to be treated as -two separate lines. Changed to allow only character as end-of-line: -carriage return on Macs, newline elsewhere. (JO) - -9/29/95 (new feature) Changed to install "configInfo" file in same -directory as library scripts. It didn't used to get installed. (JO) - -9/29/95 (bug fix) Tcl was not converting Win32 errors into POSIX -errors under some circumstances. (SS) - -10/2/95 (bug fix) Safe interpreters no longer get initialized with -a call to Tcl_Init(). (JL) - -10/1/95 (new feature) Added "tcl_platform" global variable to provide -environment information such as the instruction set and operating -system. (JO) - -10/1/95 (bug fix) "exec" command wasn't always generating the -"child process exited abnormally" message when it should have. (JO) - -10/2/95 (bug fix) Changed "mkLinks.tcl" so that the scripts it generates -won't create links that overwrite original manual entries (there was -a problem where pack-old.n was overwriting pack.n). (JO) - -10/2/95 (feature change) Changed to use -ldl for dynamic loading under -Linux if it is available, but fall back to -ldld if it isn't. (JO) - -10/2/95 (bug fix) File sharing was causing refcounts to reach 0 -prematurely for stdin, stdout and stderr, under some circumstances. (JL) - -10/2/95 (platform support) Added support for Visual C++ compiler on -Windows, Windows '95 and Windows NT, code donated by Gordon Chaffee. (JL) - -10/3/95 (bug fix) Tcl now frees any libraries that it loads before it -exits. (SS) - -10/03/95 (bug fix) Fixed bug in Macintosh ls command where the -l -and -C options would fail in anything but the HOME directory. (RJ) - ------------------ Released 7.5a2, 10/6/95 ----------------------- - -10/10/95 (bug fix) "file dirnam /." was returning ":" on UNIX instead -of "/". (JO) - -10/13/95 (bug fix) Eliminated dependency on MKS toolkit for generating -the tcl.def file from Borland object files. (SS) - -10/17/95 (new features) Moved the event loop from Tcl to Tk, made major -revisions along the way: - - New Tcl commands: after, update, vwait (replaces "tkwait variable"). - - "tkerror" is now replaced with "bgerror". - - The following procedures are similar to their old Tk counterparts: - Tcl_DoOneEvent, Tcl_Sleep, Tcl_DoWhenIdle, Tcl_CancelIdleCall, - Tcl_CreateFileHandler, Tcl_DeleteFileHandler, Tcl_CreateTimerHandler, - Tcl_DeleteTimerHandler, Tcl_BackgroundError. - - Revised notifier, add new concept of "event source" with the following - procedures: Tcl_CreateEventSource, Tcl_DeleteEventSource, - Tcl_WatchFile, Tcl_SetMaxBlockTime, Tcl_FileReady, Tcl_QueueEvent, - Tcl_WaitForEvent. (JO) - -10/31/95 (new features) Implemented cross platform file name support to make -it easier to write cross platform scripts. Tcl now understands 4 file naming -conventions: Windows (both DOS and UNC), Mac, Unix, and Network. The network -convention is a new naming mechanism that can be used to paths in a platform -independent fashion. See the "file" command manual page for more details. -The primary interfaces changes are: - - All Tcl commands that expect a file name now accept both network and - native form. - - Two new "file" subcommands, "nativename" and "networkname", provide a - way to convert between network and native form. - - Renamed Tcl_TildeSubst to Tcl_TranslateFileName, and changed it so that - it always returns a filename in native form. Tcl_TildeSubst is defined - as a macro for backward compatibility, but it is deprecated. (SS) - -11/5/95 (new feature) Made "tkerror" and "bgerror" synonyms, so that -either name can be used to manipulate the command (provides temporary -backward compatibility for existing scripts that use tkerror). (JO) - -11/5/95 (new feature) Added exit handlers and new C procedures -Tcl_CreateExitHandler, Tcl_DeleteExitHandler, and Tcl_Exit. (JO) - -11/6/95 (new feature) Added pid command for Macintosh version of -Tcl (it didn't previously exist on the Mac). (RJ) - -11/7/95 (new feature) New generic IO facility and support for IO to -files, pipes and sockets based on a common buffering scheme. Support -for asynchronous (non-blocking) IO and for event driver IO. Support -for automatic (background) asynchronous flushing and asynchronous -closing of channels. (JL) - -11/7/95 (new feature) Added new commands "fconfigure" and "fblocked" -to support new I/O features such as nonblocking I/O. Added "socket" -command for creating TCP client and server sockets. (JL). - -11/7/95 (new feature) Complete set of C APIs to the new generic IO -facility: - - Opening channels: Tcl_OpenFileChannel, Tcl_OpenCommandChannel, - Tcl_OpenTcpClient, Tcl_OpenTcpServer. - - I/O procedures on channels, which roughly mirror the ANSI C stdio - library: Tcl_Read, Tcl_Gets, Tcl_Write, Tcl_Flush, Tcl_Seek, - Tcl_Tell, Tcl_Close, Tcl_Eof, Tcl_InputBlocked, Tcl_GetChannelOption, - Tcl_SetChannelOption. - - Extension mechanism for creating new kinds of channels: - Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, - Tcl_GetChannelName, Tcl_GetChannelFile, Tcl_RegisterChannel, - Tcl_UnregisterChannel, Tcl_GetChannel. - - Event-driven I/O on channels: Tcl_CreateChannelHandler, - Tcl_DeleteChannelHandler. (JL) - -11/7/95 (new feature) Channel driver interface specification to allow -new types of channels to be added easily to Tcl. Currently being used -in three drivers - for files, pipes and TCP-based sockets. (JL). - -11/7/95 (new feature) interp delete now takes any number of path -names of interpreters to delete, including zero. (JL). - -11/8/95 (new feature) implemented 'info hostname' and Tcl_GetHostName -command to get host name of machine on which the Tcl process is running. (JL) - -11/9/95 (new feature) Implemented file APIs for access to low level files -on each system. The APIs are: Tcl_CloseFile, Tcl_OpenFile, Tcl_ReadFile, -Tcl_WriteFile and Tcl_SeekFile. Also implemented Tcl_WaitPid which waits -in a system dependent manner for a child process. (JL) - -11/9/95 (new feature) Added Tcl_UpdateLinkedVar procedure to force a -Tcl variable to be updated after its C variable changes. (JO) - -11/9/95 (bug fix) The glob command has been totally reimplemented so -that it can support different file name conventions. It now handles -Windows file names (both UNC and drive-relative) properly. It also -supports nested braces correctly now. (SS) - -11/13/95 (bug fix) Fixed Makefile.in so that configure can be run -from a clean directory separate from the Tcl source tree, and compilations -can be performed there. (JO) - -11/14/95 (bug fix) Fixed file sharing between interpreters and file -transferring between interpreters to correctly manage the refcount so that -files are closed when the last reference to them is discarded. (JL) - -11/14/95 (bug fix) Fixed gettimeofday implementation for the -Macintosh. This fixes several timing related bugs. (RJ) - -11/17/95 (new feature) Added missing support for info nameofexecutable -on the Macintosh. (RJ) - -11/17/95 (bug fix) The Tcl variables argc argv and argv0 now return -something reasonable on the Mac. (RJ) - -11/22/95 (new feature) Implemented "auto-detect" mode for end of line -translations. On input, standalone "\r" mean MAC mode, standalone "\n" -mean Unix mode and "\r\n" means Windows mode. On output, the mode is -modified to whatever the platform specific mode for that platform is. (JL) - -11/24/95 (feature change) Replaced "configInfo" file with tclConfig.sh, -which is more complete and uses slightly different names. Also -arranged for tclConfig.sh to be installed in the platform-specific -library directory instead of Tcl's script library directory. (JO) -*** POTENTIAL INCOMPATIBILITY with Tcl 7.5a2, but not with Tcl 7.4 *** - ------------------ Released patch 7.4p3, 11/28/95 ----------------------- - -12/5/95 (new feature) Added Tcl_File facility to support platform- -independent file handles. Changed all interfaces that used Unix- -style integer fd's to use Tcl_File's instead. (SS) -*** POTENTIAL INCOMPATIBILITY *** - -12/5/95 (new feature) Added a new "clock" command to Tcl. The command -allows you to get the current "clicks" or seconds & allows you to -format or scan human readable time/date strings. (RJ) - -12/18/95 (new feature) Moved Tk_Preserve, Tk_Release, and Tk_EventuallyFree -to Tcl, renamed to Tcl_Preserve, Tcl_Release, and Tcl_EventuallyFree. (JO) - -12/18/95 (new feature) Added new "package" command and associated -procedures Tcl_PkgRequire and Tcl_PkgProvide. Also wrote -pkg_mkIndex library procedure to create index files from binaries -and scripts. (JO) - -12/20/95 (new feature) Added Tcl_WaitForFile procedure. (JO) - -12/21/95 (new features) Made package name argument to "load" optional -(Tcl will now attempt to guess the package name if necessary). Also -added Tcl_StaticPackage and support in "load" for statically linked -packages. (JO) - -12/22/95 (new feature) Upgraded the foreach command to accept multiple -loop variables and multiple value lists. This lets you iterate over -multiple lists in parallel, and/or assign multiple loop variables from -one value list during each iteration. The only potential compatibility -problem is with scripts that used loop variables with a name that could be -construed to be a list of variable names (i.e. contained spaces). (BW) - -1/5/96 (new feature) Changed tclsh so it builds as a console mode -application under Windows. Now tclsh can be used from the command -line with pipes or interactively. Note that this only works under -Windows 95 or NT. (SS) - -1/17/96 (new feature) Modified Makefile and configure script to allow -Tcl to be compiled as a shared library: use the --enable-shared option -when configuing. (JO) - -1/17/96 (removed obsolete features) Removed the procedures Tcl_EnterFile -and Tcl_GetOpenFile: these no longer make sense with the new I/O system. (JL) -*** POTENTIAL INCOMPATIBILITY *** - -1/19/96 (bug fixes) Prevented formation of circular aliases, through the -Tcl 'interp alias' command and through the 'rename' command, as well as -through the C API Tcl_CreateAlias. (JL) - -1/19/96 (bug fixes) Fixed several bugs in direct deletion of interpreters -with Tcl_DeleteInterp when the interpreter is a slave; fixes based on a -patch received from Viktor Dukhovni of ESM. (JL) - -1/19/96 (new feature) Implemented on-close handlers for channels; added -the C APIs Tcl_CreateCloseHandler and Tcl_DeleteCloseHandler. (JL) - -1/19/96 (new feature) Implemented portable error reporting mechanism; added -the C APIs Tcl_SetErrno and Tcl_GetErrno. (JL) - -1/24/96 (bug fix) Unknown command processing properly invokes external -commands under Windows NT and Windows '95 now. (SS) - -1/23/96 (bug fix) Eliminated extremely long startup times under Windows '95. -The problem was a result of the option database initialization code that -concatenated $HOME with /.Xdefaults, resulting in a // in the middle of the -file name. Under Windows '95, this is incorrectly interpreted as a UNC -path. They delays came from the network timeouts needed to determine that -the file name was invalid. Tcl_TranslateFileName now suppresses duplicate -slashes that aren't at the beginning of the file name. (SS) - -1/25/96 (bug fix) Changed exec and open to create children so they are -attached to the application's console if it exists. (SS) - -1/31/96 (bug fix) Fixed command line parsing to handle embedded -spaces under Windows. (SS) - ------------------ Released 7.5b1, 2/1/96 ----------------------- - -2/7/96 (bug fix) Fixed off by one error in argument parsing code under -Windows. (SS) - -2/7/96 (bug fix) Fixed bugs in VC++ makefile that improperly -initialized the tcl75.dll. Fixed bugs in Borland makefile that caused -build failures under Windows NT. (SS) - -2/9/96 (bug fix) Fixed deadlock problem in AUTO end of line translation -mode which would cause a socket server with several concurrent clients -writing in CRLF mode to hang. (JL) - -2/9/96 (API change) Replaced -linemode option to fconfigure with a -new -buffering option, added "none" setting to enable immediate write. (JL) -*** INCOMPATIBILITY with b1 *** - -2/9/96 (new feature) Added C API Tcl_InputBuffered which returns the count -of bytes currently buffered in the input buffer of a channel, and o for -output only channels. (JL) - -2/9/96 (new feature) Implemented asynchronous connect for sockets. (JL) - -2/9/96 (new feature) Added C API Tcl_SetDefaultTranslation to set (per -channel) the default end of line translation mode. This is the mode that -will be installed if an output operation is done on the channel while it is -still in AUTO mode. (JL) - -2/9/96 (bug fix) Changed Tcl_OpenCommandChannel interface to properly -handle all of the combinations of stdio inheritance in background -pipelines. See the Tcl_OpenFileChannel(3) man page for more -info. This change fixes the bug where exec of a background pipeline -was not getting passed the stdio handles properly. (SS) - -2/9/96 (bug fix) Removed the new Tcl_CreatePipeline interface, and -restored the old version for Unix platforms only. All new code should -use Tcl_CreateCommandChannel instead. (SS) - -2/9/96 (bug fix) Changed Makefile.in to use -L and -ltcl7.5 for Tcl -library so that shared libraries are more likely to be found correctly -on more platforms. (JO) - -2/13/96 (new feature) Added C API Tcl_SetNotifierData and -Tcl_GetNotifierData to allow notifier and channel driver writers to -associate data with a Tcl_File. The result of this change is that -Tcl_GetFileInfo now always returns an OS file handle, and Tcl_GetFile -can be used to construct a Tcl_File for an externally constructed OS -handle. (SS) - -2/13/96 (bug fix) Changed Windows socket implementation so it doesn't -set SO_REUSEADDR on server sockets. Now attempts to create a server -socket on a port that is already in use will be properly identified -and an error will be generated. (SS) - -2/13/96 (bug fix) Fixed problems with DLL initialization under Visual -C++ that left the C run time library uninitialized. (SS) - -2/13/96 (bug fix) Fixed Windows socket initialization so it loads -winsock the first time it is used, rather than at the time tcl75.dll -is loaded. This should fix the bug where the modem immediately starts -trying to connect to a service provider when wish or tclsh are -started. (SS) - -2/13/96 (new feature) Added C APIs Tcl_MakeFileChannel and -Tcl_MakeTcpClientChannel to wrap up existing fds and sockets into -channels. Provided implementations on Unix and Windows. (JL) - -2/13/96 (bug fix) Fixed bug with seek leaving EOF and BLOCKING set. (JL) - -2/14/96 (bug fix) Fixed reentrancy problem in fileevent handling -and made it more robust in the face of errors. (JL) - -2/14/96 (feature change) Made generic IO level emulate blocking mode if the -channel driver is unable to provide it, e.g. if the low level device is -always nonblocking. Thus, now blocking behavior is an advisory setting for -channel drivers and can be ignored safely if the channel driver is unable -to provide it. (JL) - -2/15/96 (new feature) Added "binary" end of line translation mode, which is -a synonym of "lf" mode. (JL) - -2/15/96 (bug fix) Fixed reentrancy problem in fileevent handling vs -deletion of channel event handlers. (JL) - -2/15/96 (bug fix) Fixed bug in event handling which would cause a -nonblocking channel to not see further readable events after the first -readable event that had insufficient input. (JL) - -2/17/96 (bug fix) "info complete" didn't properly handle comments -in nested commands. (JO) - -2/21/96 (bug fix) "exec" under Windows NT/95 did not properly handle -very long command lines (>200 chars). (SS) - -2/21/96 (bug fix) Sockets could get into an infinite loop if a read -event arrived after all of the available data had been read. (SS) - -2/22/96 (bug fix) Added cast of st_size elements to (long) before -sprintf-ing in "file size" command. This is needed to handle systems -like NetBSD with 64-bit file offsets. (JO) - ------------------ Released 7.5b2, 2/23/96 ----------------------- - -2/23/96 (bug fix) TCL_VARARGS macro in tcl.h wasn't defined properly -when compiling with C++. (JO) - -2/24/96 (bug fix) Removed dependencies on Makefile in the UNIX Makefile: -this caused problems on some platforms (like Linux?). (JO) - -2/24/96 (bug fix) Fixed configuration bug that made Tcl not compile -correctly on Linux machines with neither -ldl or -ldld. (JO) - -2/24/96 (new feature) Added a block of comments and definitions to -Makefile.in to make it easier to have Tcl's TclSetEnv etc. replace -the library procedures setenv etc, so that calls to setenv etc. in -the application automatically update the Tcl "env" variable. (JO) - -2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL) -to C API Tcl_Close and simplified closing of command channels. (JL) -*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** - -2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL) -to C type definition Tcl_DriverCloseProc; modified all channel drivers to -implement close procedures that accept the additional argument. (JL) -*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** - -2/28/96 (bug fix) Fixed memory leak that could occur if an upvar -referred to an element of an array in the same stack frame as the -upvar. (JO) - -2/29/96 (feature change) Modified both Tcl_DoOneEvent and Tcl_WaitForEvent -so that they return immediately in cases where they would otherwise -block forever (e.g. if there are no event handlers of any sort). (JO) - -2/29/96 (new feature) Added C APIs Tcl_GetChannelBufferSize and -Tcl_SetChannelBufferSize to set and retrieve the size, in bytes, for -buffers allocated to store input or output in a channel. (JL) - -2/29/96 (new feature) Added option -buffersize to Tcl fconfigure command -to allow Tcl scripts to query and set the size of channel buffers. (JL) - -2/29/96 (feature removed) Removed channel driver function to specify -the buffer size to use when allocating a buffer. Removed the C typedef -for Tcl_DriverBufferSizeProc. Channels are now created with a default -buffer size of 4K. (JL) -*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** - -2/29/96 (feature change) The channel driver function for setting blocking -mode on the device may now be NULL. If the generic code detects that the -function is NULL, operations that set the blocking mode on the channel -simply succeed. (JL) - -3/2/96 (bug fix) Fixed core dump that could occur if a syntax error -(such as missing close paren) occurred in an array reference with a -very long array name. (JO) - -3/4/96 (bug fix) Removed code in the "auto_load" procedure that deletes -all existing auto-load information whenever the "auto_path" variable -is changed. Instead, new information adds to what was already there. -Otherwise, changing the "auto_path" variable causes all package- -related information to be lost. If you really want to get rid of -existing auto-load information, use auto_reset before setting auto_path. (JO) - -3/5/96 (new feature) Added version suffix to shared library names so that -Tcl will compile under NetBSD and FreeBSD (I hope). (JO) - -3/6/96 (bug fix) Cleaned up error messages in new I/O system to correspond -more closely to old I/O system. (JO) - -3/6/96 (new feature) Added -myaddr and -myport options to the socket -command, removed -tcp and -- options. This lets clients and servers -choose a particular interface. Also changed the default server address -from the hostname to INADDR_ANY. The server accept callback now gets -passed the client's port as well as IP address. The C interfaces for -Tcl_OpenTcpClient and Tcl_OpenTcpServer have changed to support the -above changes. (BW) -*** POTENTIAL INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** - -3/6/96 (changed feature) The library function auto_mkindex will now -default to using the pattern "*.tcl" if no pattern is given. (RJ) - -3/6/96 (bug fix) The socket channel code for the Macintosh has been -rewritten to use native MacTcp. (RJ) - -3/7/96 (new feature) Added Tcl_SetStdChannel and Tcl_GetStdChannel -interfaces to allow applications to explicitly set and get the global -standard channels. (SS) - -3/7/96 (bug fix) Tcl did close not the file descriptors associated -with "stdout", etc. when the corresponding channels were closed. (SS) - -3/7/96 (bug fix) Reworked shared library and dynamic loading stuff to -try to get it working under AIX. Added new @SHLIB_LD_LIBS@ autoconf -symbol as part of this. AIX probably doesn't work yet, but it should -be a lot closer. (JO) - -3/7/96 (feature change) Added Tcl_ChannelProc typedef and changed the -signature of Tcl_CreateChannelHandler and Tcl_DeleteChannelHandler to take -Tcl_ChannelProc arguments instead of Tcl_FileProc arguments. This change -should not affect any code outside Tcl because the signatures of -Tcl_ChannelProc and Tcl_FileProc are compatible. (JL) - -3/7/96 (API change) Modified signature of Tcl_GetChannelOption to return -an int instead of char *, and to take a Tcl_DString * argument. Modified -the implementation so that the option name can be NULL, to mean that the -call should retrieve a list of alternating option names and values. (JL) -*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** - -3/7/96 (API change) Added Tcl_DriverSetOptionProc, Tcl_DriverGetOptionProc -typedefs, added two slots setOptionProc and getOptionProc to the channel -type structure. These may be NULL to indicate that the channel type does -not support any options. (JL) -*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** - -3/7/96 (feature change) stdin, stdout and stderr can now be put into -nonblocking mode. (JL) - -3/8/96 (feature change) Eliminated dependence on the registry for -finding the Tcl library files. (SS) - ------------------ Released 7.5b3, 3/8/96 ----------------------- - -3/12/96 (feature improvement) Modified startup script to look in several -different places for the Tcl library directory. This should allow Tcl -to find the libraries under all but the weirdest conditions, even without -the TCL_LIBRARY environment variable being set. (JO) - -3/13/96 (bug fix) Eliminated use of the "linger" option from the Windows -socket implementation. (JL) - -3/13/96 (new feature) Added -peername and -sockname options for fconfigure -for socket channels. Code contributed by John Haxby of HP. (JL) - -3/13/96 (bug fix) Fixed panic and core dump that would occur if the accept -callback script on a server socket encountered an error. (JL) - -3/13/96 (feature change) Added -async option to the Tcl socket command. -If the command is creating a client socket and the flag is present, the -client is connected asynchronously. If the option is absent (the default), -the client socket is connected synchronously, and the command returns only -when the connection has been completed or failed. This change was suggested -by Mark Diekhans. (JL) - -3/13/96 (feature change) Modified the signature of Tcl_OpenTcpClient to -take an additional int argument, async. If nonzero, the client is connected -to the server asynchronously. If the value is zero, the connection is made -synchronously, and the call to Tcl_OpenTcpClient returns only when the -connection fails or succeeds. This change was suggested by Mark Diekhans. (JL) -*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** - -3/14/96 (bug fix) "tclsh bogus_file_name" didn't print an error message. (JO) - -3/14/96 (bug fix) Added new procedures to tclCkalloc.c so that libraries -and applications can be compiled with TCL_MEM_DEBUG even if Tcl isn't -(however, the converse is still not true). Patches provided by Jan -Nijtmans. (JO) - -3/15/96 (bug fix) Marked standard IO handles of a process as close-on-exec -to fix bug in Ultrix where exec was not sharing standard IO handles with -subprocesses. Fix suggested by Mark Diekhans. (JL) - -3/15/96 (bug fix) Fixed asynchronous close mechanism so that it closes the -channel instead of leaking system resources. The manifestation was that Tcl -would eventually run out of file descriptors if it was handling a large -number of nonblocking sockets or pipes with high congestion. (JL) - -3/15/96 (bug fix) Fixed tests so that they no longer leak file descriptors. -The manifestation was that Tcl would eventually run out of file descriptors -if the tests were rerun many times (> a hundred times on Solaris). (JL) - -3/15/96 (bug fix) Fixed channel creation code so that it never creates -unnamed channels. This would cause a panic and core dump when the channel -was closed. (JL) - -3/16/96 (bug fixes) Made lots of changes in configuration stuff to get -Tcl working under AIX (finally). Tcl should now support the "load" -command under AIX and should work either with or without shared -libraries for Tcl and Tk. (JO) - -3/21/96 (configuration improvement) Changed configure script so it -doesn't use version numbers (as in -ltcl7.5 and libtcl7.5.so) under -SunOS 4.1, where they don't work anyway. (JO) - -3/22/96 (new feature) Added C API Tcl_InterpDeleted that allows extension -writers to discover when an interpreter is being deleted. (JL) - -3/22/96 (bug fix) The standard IO channels are now added to each -trusted interpreter as soon as the interpreter is created. This ensures -against the bug where a child would do IO before the master had done any, -and then the child is destroyed - the standard IO channels would be then -closed and the master would be unable to do any IO. (JL) - -3/22/96 (bug fix) Made Tcl more robust against interpreter deletion, by -using Tcl_Preserve, Tcl_Release and Tcl_EventuallyFree to split the process -of interpreter deletion into two distinct phases. Also went through all of -Tcl and added calls to Tcl_Preserve and Tcl_Delete where needed. (JL) - -3/22/96 (bug fix) Fixed several places where C code was reading and writing -into freed memory, especially during interpreter deletion. (JL) - -3/22/96 (bug fix) Fixed very deep bug in Tcl_Release that caused memory to -be freed twice if the release callback did Tcl_Preserve and Tcl_Release on -the same memory as the chunk currently being freed. (JL) - -3/22/96 (bug fix) Removed several memory leaks that would cause memory -buildup on half-K chunks in the generic IO level. (JL) - -3/22/96 (bug fix) Fixed several core dumps which occurred when new -AssocData was being created during the cleanups in interpreter deletion. -The solution implemented now is to loop repeatedly over the AssocData until -none is left to clean up. (JL) - -3/22/96 (bug fix) Fixed a bug in event handling which caused an infinite -loop if there were no files being watched and no timer. Fix suggested by -Jan Nijtmans. (JL) - -3/22/96 (bug fix) Fixed Tcl_CreateCommand, Tcl_DeleteCommand to be more -robust if the interpreter is being deleted. Also fixed several order -dependency bugs in Tcl_DeleteCommand which kicked in when an interpreter -was being deleted. (JL) - -3/26/96 (bug fix) Upon a "short read", the generic code no longer calls -the driver for more input. Doing this caused blocking on some platforms -even on nonblocking channels. Bug and fix courtesy Mark Roseman. (JL) - -3/26/96 (new feature) Added 'package Tcltest' which is present only in -test versions of Tcl; this allows the testing commands to be loaded into -new interpreters besides the main one. (JL) - -3/26/96 (restored feature) Recreated the Tcl_GetOpenFile C API. You can -now get a FILE * from a registered channel; Unix only. (JL) - -3/27/96 (bug fix) The regular expression code did not support more -than 9 subexpressions. It now supports up to 20. (SS) - -4/1/96 (bug fixes) The CHANNEL_BLOCKED bit was being left on on a short -read, so that fileevents wouldn't fire correctly. Bug reported by Mark -Roseman.(JL, RJ) - -4/1/96 (bug fix) Moved Tcl_Release to match Tcl_Preserve exactly, in -tclInterp.c; previously interpreters were being freed only conditionally -and sometimes not at all. (JL) - -4/1/96 (bug fix) Fixed error reporting in slave interpreters when the -error message was being generated directly by C code. Fix suggested by -Viktor Dukhovni of ESM. (JL) - -4/2/96 (bug fixes) Fixed a series of bugs in Windows sockets that caused -events to variously get lost, to get sent multiple times, or to be ignored -by the driver. The manifestation was blocking if the channel is blocking, -and either getting EAGAIN or infinite loops if the channel is nonblocking. -This series of bugs was found by Ian Wallis of Cisco. Now all tests (also -those that were previously commented out) in socket.test pass. (JL, SS) - -4/2/96 (feature change/bug fix) Eliminated network name support in -favor of better native name support. Added "file split", "file join", -and "file pathtype" commands. See the "file" man page for more -details. (SS) -*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** - -4/2/96 (bug fix) Changed implementation of auto_mkindex so tclIndex -files will properly handle path names in a cross platform context. (SS) - -4/5/96 (bug fix) Fixed Tcl_ReadCmd to use the channel buffer size as the -chunk size it reads, instead of a fixed 4K size. Thus, on large reads, the -user can set the channel buffer size to a large size and the read will -occur orders of magnitude faster. For example, on a 2MB file, reading in 4K -chunks took 34 seconds, while reading in 1MB chunks took 1.5 seconds (on a -SS-20). Problem identified and fix suggested by John Haxby of HP. (JL) - -4/5/96 (bug fix) Fixed socket creation code to invoke gethostbyname only if -inet_addr failed (very unlikely). Before this change the order was reversed -and this made things much slower than they needed to be (gethostbyname -generally requires an RPC, which is slow). Problem identified and fix -suggested by John Loverso of OSF. (JL) - -4/9/96 (feature change) Modified "auto" translation mode so that it -recognizes any of "\n", "\r" and "\r\n" in input as end of line, so -that a file can have mixed end-of-line sequences. It now outputs -the platform specific end of line sequence on each platform for files and -pipes, and for sockets it produces crlf in output on all platforms. (JL) -*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** - -4/11/96 (new feature) Added -eofchar option to Tcl_SetChannelOption to allow -setting of an end of file character for input and output. If an input eof -char is set, it is recognized as EOF and further input from the channel is -not presented to the caller. If an output eof char is set, on output, that -byte is appended to the channel when it is closed. On Unix and Macintosh, -all channels start with no eof char set for input or output. On Windows, -files and pipes start with input and output eof chars set to Crlt-Z (ascii -26), and sockets start with no input or output eof char. (JL) -*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** - -4/17/96 (bug fix) Fixed series of bugs with handling of crlf sequence split -across buffer boundaries in input, in AUTO mode. (JL, BW) - -4/17/96 (test suite improvement) Fixed test suite so that tests that -depend on the availability of Unix commands such as echo, cat and others -are not run if these commands are not present. (JL) - -4/17/96 (test suite improvement) The socket test now automatically starts, -on platformst that support exec, a separate process for remote testsing. (JL) - ------------------ Released 7.5, 4/21/96 ----------------------- - -5/1/96 (bug fix) "file tail ~" did not correctly return the tail -portion of the user's home directory. (SS) - -5/1/96 (bug fix) Fixed bug in TclGetEnv where it didn't lookup environment -variables correctly: could confuse "H" and "HOME", for example. (JO) - -5/1/96 (bug fix) Changed to install tclConfig.sh under "make install-binaries", -not "make install-libraries". (JO) - -5/2/96 (bug fix) Changed pkg_mkIndex not to attempt to "load" a file unless -it has the standard shared library extension. On SunOS, attempts to load -Tcl scripts cause the whole application to be aborted (there's no way to -get the error back into Tcl). (JO) - -5/7/96 (bug fix) Moved initScript in tclUnixInit.c to writable memory to -avoid potential core dumps. (JO) - -5/7/96 (bug fix) Auto_reset procedure was removing procedure from init.tcl, -such as pkg_mkIndex. (JO) - -5/7/96 (bug fix) Fixed cast on socket address resolution code that -would cause a failure to connect on Dec Alphas. (JL) - -5/7/96 (bug fix) Added "time", "subst" and "fileevent" commands to set of -commands available in a safe interpreter. (JL) - -5/13/96 (bug fix) Preventing OS level handles for stdin, stdout and stderr -from being implicitly closed when the last reference to the standard -channel containing that handle is discarded when an interpreter is deleted. -Explicitly closing standard channels by using "close" still works. (JL) - -5/21/96 (bug fix) Do not create channels for stdin, stdout and stderr on -Unix if the devices are closed. This prevents a duplicate channel name -panic later on when the fd is used to open a channel and the channel is -registered in an interpreter. (JL) - -5/23/96 (bug fix) Fixed bug that prevented the use of standard channels in -interpreters created after the last interpreter was destroyed. In the sequence - - interp = Tcl_CreateInterp(); - Tcl_DeleteInterp(interp); - interp = Tcl_CreateInterp(); - -channels for stdio would not be available in the second interpreter. (JL) - -5/23/96 (bug fix) Fixed bug that allowed Tcl_MakeFileChannel to create new -channels with Tcl_Files in them that are already used by another channel. -This would cause core dumps when the Tcl_Files were being freed twice. (JL) - -5/23/96 (bug fix) Fixed a logical timing bug that caused a standard channel -to be removed from the standard channel table too early when the channel -was being closed. If the channel was being flushed asynchronously, it could -get recreated before being actually destroyed, and the recreated channel -would contain the same Tcl_File as the one being closed, leading to -dangling pointers and core dumps. (JL) - -5/27/96 (bug fix) Fixed a bug in Tcl_GetChannelOption which caused it to -always return a list of one element, a list of the settings, for --translation and -eofchar options. Now correctly returns the value -described by the documentation (Mark Diekhans found this, thanks!). (JL) - -5/30/96 (bug fix) Fixed a couple of syntax errors in io.test. (JL) - -5/30/96 (bug fix) If a fileevent scripts gets an error, delete it before -causing a background error. This is to allow the error handler to reinstall -the fileevent and to prevent infinite loops if the event loop is reentered -in the error handler. (JL) - -5/31/96 (bug fix) Channels now will get properly flushed on exit. (JL) - -6/5/96 (bug fix) Changed Tcl_Ckalloc, Tcl_Ckfree, and Tcl_Ckrealloc to -Tcl_Alloc, Tcl_Free, and Tcl_Realloc. Added documentation for these -routines now that they are officially supported. Extension writers -should use these routines instead of free() and malloc(). (SS) - -6/10/96 (bug fix) Changes the Tcl close command so that it no longer -waits on nonblocking pipes for the piped processes to exit; instead it -reaps them in the background. (JL) - -6/11/96 (bug fix) Increased the length of the listen queue for server -sockets on Unix from 5 to 100. Some OSes will disregard this and reset it -to 5, but we should try to get as long a queue as we can, for performance -reasons. (JL) - -6/11/96 (bug fix) Fixed windows sockets bug that caused a cascade of events -if the fileevent script read less than was available. Now reading less than -is available does not cause a flood of Tcl events. (JL, SS) - -6/11/96 (bug fix) Fixed bug in background flushing on closed channels that -would prevent the last buffer from getting flushed. (JL) - -6/13/96 (bug fix) Fixed bug in Windows sockets that caused a core dump if -a DLL linked with tcl.dll and referred to e.g. ntohs() without opening a -Tcl socket. The problem was that the indirection table was not being -initialized. (JL) - -6/13/96 (bug fix) Fixed OS level resource leak that would occur when a -Tcl channel was still registered in some interpreter when the process -exits. Previously the channel was not being closed and the OS level handles -were not being released; the output was being flushed but the device was -not being closed. Now the device is properly closed. This was only a -problem on Win3.1 and MacOS. (JL, SS) - -6/28/96 (bug fix) Fixed bug where transient errors were leaving an error -code around, so that it would erroneously get reported later. This bug was -exercised intermittently by closing a channel to a file on a very loaded -NFS server, or to a socket whose other end blocked. (JL, BW) - -7/3/96 (bug fix) Fileevents declared in an interpreter are now deleted -when the channel is closed in that interpreter. Before this fix, the -fileevent would hang around until the channel is completely closed, and -would cause errors if events happened before the channel was closed. This -could happen in two cases: first if the channel is shared between several -interpreters, and second if an async flush is in progress that prevents the -channel from being closed until the flush finishes. (JL) - -7/10/96 (bug fix) Fixed bugs in both "lrange" and "lreplace" commands -where too much white space was being removed. For example, the command - lreplace {\}\ hello} end end -was returning "\}\", losing the significant space in the first list -element and corrupting the list. (JO) - -7/20/96 (bug fix) The procedure pkg_mkIndex didn't work properly for -extensions that depend on Tk, because it didn't load Tk into the child -interpreter before loading the extension. Now it loads Tk if Tk is -present in the parent. (JO) - -7/23/96 (bug fix) Added compat version of strftime to fix crashes -resulting from bad implementations under Windows. (SS) - -7/23/96 (bug fix) Standard implementations of gmtime() and localtime() -under Windows did not handle dates before 1970, so they were replaced -with a revised implementation. (SS) - -7/23/96 (bug fix) Tcl would crash on exit under Borland 5.0 because -the global environ pointer was left pointing to freed memory. (SS) - -7/29/96 (bug fix) Fixed memory leak in Tcl_LoadCmd that could occur if -a package's AppInit procedure called Tcl_StaticPackage to register -static packages. (JO) - -8/1/96 (bug fix) Fixed a series of bugs in Windows sockets so that async -writebehind in the presence of read event handlers now works, and so that -async writebehind also works on sockets for which a read event handler was -declared and whose channels were then closed before the async write -finished. The bug was reported by John Loverso and Steven Wahl, -independently, test case supplied by John Loverso. (JL) - ------------------ Released patch 7.5p1, 8/2/96 ----------------------- - -5/8/96 (new feature) Added Tcl_GetChannelMode C API for retrieving whether -a channel is open for reading and writing. (JL) - -5/8/96 (API changes) Revised C APIs for channel drivers: - - Removed all Tcl_Files from channel driver interface; you can now have - channels that are not based on Tcl_Files. - - Added channelReadyProc and watchChannelProc procedures to interface; - these are used to implement event notification for channels. - - Added getFileProc to channel driver, to allow the generic IO code - to retrieve a Tcl_File from a channel (presumably if the channel - uses Tcl_Files they will be stored inside its instanceData). (JL) -*** INCOMPATIBILITY with Tcl 7.5 *** - -5/8/96 (API change) The Tcl_CreateChannel C API was modified to not take -Tcl_File arguments, and instead to take a mask specifying whether the -channel is readable and/or writable. (JL) -*** INCOMPATIBILITY with Tcl 7.5 *** - -6/3/96 (bug fix) Made Tcl_SetVar2 robust against the case where the value -of the variable is a NULL pointer instead of "". (JL) - -6/17/96 (bug fix) Fixed "reading uninitialized memory" error reported by -Purify, in Tcl_Preserve/Tcl_Release. (JL) - -8/9/96 (bug fix) Fixed bug in init.tcl that caused incorrect error message -if the act of autoloading a procedure caused the procedure to be invoked -again. (JO) - -8/9/96 (bug fix) Configure script produced bad library names and extensions -under SunOS and a few other platforms if the --disable-load switch was used. -(JO) - -8/9/96 (bug fix) Tcl_UpdateLinkedVar generated an error if the variable -being updated was read-only. (JO) - -8/14/96 (bug fix) The macintosh now supports synchronous socket -connections. Other minor bugs were also fixed. (RJ) - -8/15/96 (configuration improvement) Changed the file patchlevel.h -to be tclPatch.h. This avoids conflict with the Tk file and is now -in 8.3 format on the Windows platform. (RJ) - -8/20/96 (bug fix) Fixed core dump in interp alias command for interpreters -created with Tcl_CreateInterp (as opposed to with Tcl_CreateSlave). (JL) - -8/20/96 (bug fix) No longer masking ECONNRESET on Windows sockets so -that the higher level of the IO mechanism sees the error instead of -entering an infinite loop. (JL) - -8/20/96 (bug fix) Destroying the last interpreter no longer closes the -standard channels. (JL) - -8/20/96 (bug fix) Closing one of the stdin, stdout or stderr channels and -then opening a new channel now correctly assigns the new channel as the -standard channel that was closed. (JL) - -8/20/96 (bug fix) Added code to unix/tclUnixChan.c for using ioctl with -FIONBIO instead of fcntl with O_NONBLOCK, for those versions of Unix where -either O_NONBLOCK is not supported or implemented incorrectly. (JL) - -8/21/96 (bug fix) Fixed "file extension" so it correctly returns the -extension on files like "foo..c" as "..c" instead of ".c". (SS) - -8/22/96 (bug fix) If environ[] contains static strings, Tcl would core -dump in TclSetupEnv because it was trying to write NULLs into the actual -data in environ[]. Now we instead copy as appropriate. (JL) - -8/22/96 (added impl) Added missing implementation of Tcl_MakeTcpClientChannel -for Windows platform. Code contributed by Mark Diekhans. (JL) - -8/22/96 (new feature) Added a new memory allocator for the Macintosh -version of Tcl. It's quite a bit faster than MetroWerk's version. (RJ) - -8/26/96 (documentation update) Removed old change bars (for all changes -in Tcl 7.5 and earlier releases) from manual entries. (JO) - -8/27/96 (enhancement) The exec and open commands behave better and work in -more situations under Windows NT and Windows 95. Documentation describes -what is still lacking. (CS) - -8/27/96 (enhancement) The Windows makefiles will now compile even if the -compiler is not in the path and/or the compiler's environment variables -have not been set up. (CS) - -8/27/96 (configuration improvement) The Windows resource files are -automatically updated when the version/patch level changes. The header file -now has a comment that reminds the user which other files must be manually -updated when the version/patch level changes. (CS) - -8/28/96 (new feature) Added file manipulation features (copy, rename, delete, -mkdir) that are supported on all platforms. They are implemented as -subcommands to the "file" command. See the documentation for the "file" -command for more information. (JH) - ------------------ Released 7.6b1, 8/30/96 ----------------------- - -9/3/96 (bug fix) Simplified code so that standard channels are created -lazily, they are added to an interpreter lazily, and they are never added -to a safe interpreter. (JL) - -9/3/96 (bug fix) Closing a channel after closing a standard channel, e.g. -stdout, would cause the implicit recreation of that standard channel. (JL) - -9/3/96 (new feature) Now calling Tcl_RegisterChannel with a NULL -interpreter increments the refcount so that code outside any interpreter -can use channels that are also registered in interpreters, without worrying -that the channel may turn into a dangling pointer at any time. Calling -Tcl_UnregisterChannel with a NULL interpreter only decrements the recount -so that code outside any interpreter can safely declare it is no longer -interested in a channel. (JL) - -9/4/96 (new features) Two changes to dynamic loading: - - If the file name is empty in the "load" command and there is no - statically loaded version of the package, a dynamically loaded - version will be used if there is one. - - Tcl_StaticPackage ignores redundant calls for the same package. (JO) - -9/6/96 (bug fix) Platform specific procedures for manipulating files are -no longer macros and have been prefixed with "Tclp", such as TclpRenameFile. -Unix file code now handles symbolic links and other special files correctly. -The semantics of file copy and file rename has been changed so that if -a target directory exists, the source files will NOT be merged with the -existing files. (JH) - -9/6/96 (bug fix) If standard channel is NULL, because Tcl cannot connect -to the standard channel, do not increment the refcount. The channel can -be NULL if there is for example no standard input. (JL) - -9/6/96 (portability improvement) Changed parsing of backslash sequences -like \n to translate directly to absolute values like 0xA instead of -letting the compiler do the translation. This guarantees that the -translation is done the same everywhere. (JO) - -9/9/96 (bug fix) If channel is opened and not associated with any -interpreter, but Tcl decides to use it as one of the standard channels, it -became impossible to close the channel with Tcl_Close -- instead you had -to call Tcl_UnregisterChannel. Fixed now so that it's safe to call -Tcl_Close even when Tcl is using the channel as one of the standard ones. (JL) - -9/11/96 (feature change) The Tcl library is now placed in the Tcl -shared libraries resource. You no longer need to place the Tcl files -in your applications explicitly. (RJ) - -9/11/96 (feature change) Extensions no longer automatically have the -resource fork of the extension opened for it. Instead you need to -use the tclMacLibrary.c file in your extension. (RJ) -*** POTENTIAL INCOMPATIBILITY *** - -9/12/96 (bug fix) The extension loading mechanism on the Macintosh now -looks at the 'cfrg' resource to determine where to load the code -fragment from. This means FAT fragments should now work. (RJ) - -9/18/96 (enhancement) The exec and open commands behave better and work in -more situations under Windows 3.X. Documentation describes what is still -lacking. (CS) - -9/19/96 (bug fix) Fixed a panic which would occur if you delete a -non-existent alias before any aliases are created. Now instead correctly -returns an error that the alias is not found. (JL) - -9/19/96 (bug fix) Slave interpreters could rename aliases and they would -not get deleted when the alias was being redefined. This led to dangling -pointers etc. (JL) - -9/19/96 (bug fix) Fixed a panic where a hash table entry was being deleted -twice during alias management operations. (JL) - -9/19/96 (bug fix) Fixed bug in event loop that could cause the input focus -in Tk to get confused during menu traversal, among other problems. The -problem was related to handling of the "marker" when its event was -deleted. (JO) - -9/26/96 (bug fix) Windows was losing EOF on a socket if the FD_CLOSE event -happened to precede any left over FD_READ events. Now correctly remembers -seeing FD_CLOSE, so that trailing FD_READ events are not discarded if they -do not contain any data. This allows Tcl to correctly get a zero read and -notice EOF. (JL) - -9/26/96 (bug fix) Was not resetting READABLE state properly on sockets -under Windows if the driver discarded an FD_READ event because no data was -present. Now correctly resets the state. (JL) - -9/30/96 (bug fix) Made EOF sticky on Windows sockets, so that fileevent -readable will fire repeatedly until the socket is closed. Previously the -fileevent fired only once. This could lead to never-closed connections if -the Tcl script in the fileevent wasn't closing the socket immediately. (JL) - -10/2/96 (new feature) Improved the package loader: - - Added new variable tcl_pkgPath, which holds the default - directories under which packages are normally installed (each - package goes in a separate subdirectory of a directory in - $tcl_pkgPath). These directories are included in auto_path by - default. - - Changed the package auto-loader to look for pkgIndex.tcl files - not only in the auto_path directories but also in their immediate - children. This should make it easier to install and uninstall - packages (don't have to change auto_path or merge pkgIndex.tcl - files). (JO) - -10/3/96 (bug fix) Changed tclsh to look for tclshrc.tcl instead of -tclsh.rc on startup under Windows. This is more consistent with wish and -uses the right extension. (SS) -*** POTENTIAL INCOMPATIBILITY *** - -10/8/96 (bug fix) Convertclock does not parse 24-hour times of the -form "hhmm" correctly when hour = 00. In the parse code, hour must be ->= 100 for minutes to be non-zero. Thanks to Lint LaCour for this -bug fix. (RJ) - -10/11/96 (bug fix) Under Windows, the pid command returned the process -handle instead of the process id. (SS) - ------------------ Released 7.6, 10/16/96 ----------------------- - -10/29/96 (bug fix) Under Windows, sockets would consume 100% CPU time after -the first accept(), due to a typo. (JL) - -10/29/96 (bug fix) Incorrect refcount management caused standard channels -not to get deleted at process exit or DLL unload time, causing a memory -leak of upwards of 20K each time. (JL) - -11/7/96 (bug fix) Auto-exec didn't work on file names that contained -spaces. (JO) - -11/8/96 (bug fix) Fixed core dump that would occur if more than one call -to Tcl_DeleteChannelHandler was made to delete a given channel handler. (JL) - -11/8/96 (bug fix) Fixed test for return value in Tcl_Seek and Tcl_SeekCmd -to only treat -1 as error, instead of all negative numbers. (JL) - -11/12/96 (bug fix) Do not blocking waiting for processes at the end of a -pipe during exit cleanup. (JL) - -11/12/96 (bug fix) If we are in exit cleanup, do not close the system level -file descriptors 0, 1 and 2. Previously they were being closed which is -incorrect, in the embedded case. This led to weird behavior for programs -that want to interpose on I/O through the standard file descriptors (e.g. -Netscape Navigator). (JL) - -11/15/96 (bug fix) Fixed core dump on Windows sockets due to dependency on -deletion order at exit. Now all socket functions check to see if sockets -are (still) initialized, before calling through function pointers. Before, -they would call and might end up calling unloaded object code. (JL) - -11/15/96 (bug fix) Fixed core dump in Windows socket initialization routine -if sockets were not installed on the system. Before, it was not properly -checking the result of attempting to load the socket DLL, so it would call -through uninitialized function pointers. (JL) - -11/15/96 (bug fix) Fixed memory leak in Windows sockets which left socket -DLL handle open and could hold the socket DLL in memory uneccessarily, -until a reboot. (JL) - -12/4/96 (bug fix) Fixed bug in Macintosh socket code that could result -in lost data if a client was closed too soon after sending data. (RJ) - -12/17/96 (bug fix) Fixed deadlock bug in Windows sockets due to losing an -event. This was happening because of an interaction between buffering and -nonblocking mode on sockets. Now switched to sockets being blocking by -default, so we are also no longer emulating blocking through a private -event loop. (JL) - -1/21/97 (performance bug fix) Client TCP connections were slow to create -because getservbyname was always called on the port. Now this is only -done if Tcl_GetInt fails. (BW) - -1/21/97 (configuration fix) Made it possible to override TCL_PACKAGE_PATH -during make. Previously it was only set during autoconf process. - -1/29/97 (bug fix) Fixed some problems with the clock command that -impacted how dates were scaned after the year 2000. (RJ) - ------------------ Released 7.6p2, 1/31/97 ----------------------- - -2/5/97 (bug fix) Fixed a bug where in CR-LF translation mode, \r bytes -in the input stream were not being handled correctly. (JL) - -2/24/97 (bug fix) Fix bug with exec under Win32s not being able to create -stderr file which caused all execs to fail. Fixed temp file leak under -Win32s. Fixed optional parameter bug with SearchPath that only happened -under Win32s 1.25. (CCS) - ----------------------------------------------------------- -Changes for Tcl 7.6 go above this line. -Changes for Tcl 7.7 go below this line. ----------------------------------------------------------- - -5/8/96 (new feature) Added Tcl_Ungets C API for putting a sequence of bytes -into a channel's input buffer. This can be used for "push" model channels -where the input is obtained via callbacks instead of by request of the -generic IO code. No Tcl procedure yet. (JL) - -11/15/96 (new feature) Implemented hidden commands. New C APIs: - Tcl_HideCommand -- hides an existing exposed command. - Tcl_ExposeCommand -- exposes an existing hidden command. -New tcl APIs: - interp invokehidden -- invokes a hidden command in a slave. - interp hide -- hides an existing exposed command. - interp expose -- exposes an existing hidden command. - interp hidden -- returns a list of hidden commands. -The implementation of Safe Tcl now uses the new hidden commands facility -to implement the safe base, instead of deleting the commands from a safe -interpreter. (JL) - -11/15/96 (new feature) Implemented the safe base, a mechanism for -installing and requesting security policies, purely in Tcl code. Overloads -the package command to also allow an interpreter to "require" a policy. The -following new library commands are provided: - tcl_safeCreateInterp -- creates a slave and initializes the - policy mechanism. - tcl_safeInitInterp -- initializes an existing slave with the - policy mechanism. - tcl_safeDeleteInterp -- deletes a slave and deinitializes the - policy mechanism. -Added a new file to the library, safeinit.tcl, to hold implementation. (JL) -On 7/9/97, removed the policy loading mechanism from the Safe Base. Left -only the Safe Base aliases dealing with auto-loading and source. (JL) - -12/6/96 (new feature) Implemented Tcl_Finalize, an API that should be -called by a process when it is done using Tcl. This API runs all the exit -handlers to allow them to clean up resources etc. (JL) - -12/17/96 (new feature) Add an http Tcl script package to the Tcl library. -This package implements the client side of HTTP/1.0; the GET, HEAD, -and POST requests. (BW) - -1/21/97 (new feature) Added a "marktrusted" subcommand to the "interp" and -to the interpreter object command. It removes the "safe" mark on an -interpreter and disables hard-wired checks for safety in the C sources. (JL) - -1/21/97 (removed feature) Removed "vwait" from set of commands available in -a safe interpreter. (JL) - -2/11/97 (new feature, bug fix) http package. Added -accept to http_config -so you can set the Accept header. Added -handler option to http_get so -you can supply your own data handler. Also fixed POST operation to -set the correct MIME type on the request. (BW) - ----------------------------------------------------------- -Changes for Tcl 7.7 go above this line. -Changes for Tcl 8.0 go below this line. ----------------------------------------------------------- - -9/17/96 (bug fix) Using "upvar" it was possible to turn an array element -into an array itself. Changed to disallow this; it was quirky and didn't -really work correctly anyway. (JO) - -10/21/96 (new feature) The core of the Tcl interpreter has been replaced -with an on-the-fly compiler that translates Tcl scripts to bytecoded -instructions; a new interpreter then executes the bytecodes. The compiler -introduces only a few minor changes at the level of Tcl scripts. The biggest -changes are to expressions and lists. - - A second level of substitutions is no longer done for expressions. - This substantially improves their execution time. This means that - the expression "$x*4" produces a different result than in the past - if x is "$y+2". Fortunately, not much code depends on the old - two-level semantics. Some expressions that do, such as - "expr [join $list +]" can be recoded to work in Tcl8.0 by adding - an eval: e.g., "eval expr [join $list +]". - - Lists are now completely parsed on the first list operation to - create a faster internal representation. In the past, if you had a - misformed list but the erroneous part was after the point you - inserted or extracted an element, then you never saw an error. - In Tcl8.0 an error will be reported. This should only effect - incorrect programs that took advantage of behavior of the old - implementation that was not documented in the man pages. -Other changes to Tcl scripts are discussed in the web page at -http://www.scriptics.com/doc/compiler.html. (BL) -*** POTENTIAL INCOMPATIBILITY *** - -10/21/96 (new feature) In earlier versions of Tcl, strings were used as a -universal representation; in Tcl 8.0 strings are replaced with Tcl_Obj -structures ("objects") that can hold both a string value and an internal -form such as a binary integer or compiled bytecodes. The new objects make it -possible to store information in efficient internal forms and avoid the -constant translations to and from strings that occurred with the old -interpreter. There are new many new C APIs for managing objects. Some of the -new library procedures for objects (such as Tcl_EvalObj) resemble existing -string-based procedures (such as Tcl_Eval) but take advantage of the -internal form stored in Tcl objects for greater speed. Other new procedures -manage objects and allow extension writers to define new kinds of objects. -See the manual entries doc/*Obj*.3 (BL) - -10/24/96 (bug fix) Fixed memory leak on exit caused by some IO related -data structures not being deallocated on exit because their refcount was -artificially boosted. (JL) - -10/24/96 (bug fix) Fixed core dump in Tcl_Close if called with NULL -Tcl_Channel. (JL) - -11/19/96 (new feature) Added library procedures for finding word -breaks in strings in a platform specific manner. See the library.n -manual entry for more information. (SS) - -11/22/96 (feature improvements) Added support for different levels of -tracing during bytecode compilation and execution. This should help in -tracking down suspected problems with the compiler or with converting -existing code to use Tcl8.0. Two global Tcl variables, traceCompile -and traceExec, can be set to generate tracing information in stdout: - - traceCompile: 0 no tracing (default) - 1 trace compilations of top level commands and procs - 2 trace and display instructions for all compilations - - traceExec: 0 no tracing - 1 trace only calls to Tcl procs - 2 trace invocations of all commands including procs - 3 detailed trace showing the result of each instruction -traceExec >= 2 provides a one line summary of each called command and -its arguments. Commands that have been "compiled away" such as set are -not shown. (BL) - -11/30/96 (bug fix) The command "info nameofexecutable" could sometimes -return the name of a directory. (JO) - -11/30/96 (feature improvements) Changed the code in library/init.tcl -that reads in pkgIndex.tcl so that (a) it reads the files from child -directories before those in the parent, so that the parent gets -precedence, and (b) it doesn't quit if there is an error in a -pkgIndex.tcl file; instead, it prints an error message on standard -error and continues. (JO) - -10/5/96 (feature improvements) Partial implementation of binary string -support: the ability for Tcl string values to contain embedded null bytes. -Changed the Tcl object-based APIs to take a byte pointer and length pair -instead of a null-terminated C string. Modified several object type managers -to support binary strings but not, for example, the list type manager. -Existing string-based C APIs are unchanged and will truncate binary -strings. Compiled scripts containing nulls are also truncated. (BL) - -12/12/96 (feature change) Removed the commands "cp", "mkdir", "mv", -"rm", and "rmdir" from the Macintosh version of Tcl. They were never -officially supported and their functionality is now available via -the file command. (RJ) - ------------------ Released 8.0a1, 12/20/96 ----------------------- - -1/7/97 (bug fix) Under Windows, "file stat c:" was returning error instead -of stat for current dir on c: drive. - -1/10/97 (new feature) Added Tcl_GetIndexFromObj procedure for quick -lookups of keyword arguments. (JO) - -1/12/97 (new feature) Serial IO channel drivers for Windows and Unix, -available by using Tcl open command to open pseudo-files like "com1:" or -"/dev/ttya". New option to Tcl fconfigure command for serial files: -"-mode baud,parity,data,stop" to specify baud rate, parity, data bits, and -stop bits. Serial IO is not yet available on Mac. - -1/16/97 (feature change) Restored the Tcl7.x "two level substitution -semantics" for expressions. Expressions not enclosed in braces are -implemented, in general, by calling the expr command procedure -(Tcl_ExprObjCmd) at runtime after the Tcl interpreter has already done a -first round of substitutions. This is slow (about Tcl7.x speed) because new -code for the expression is generally compiled each time. However, if the -expression has only variable substitutions (and not command substitutions), -"optimistic" fast code is generated inline. This inline code will fail if a -second round of substitutions is needed (i.e., if the value of a substituted -variable itself requires more substitutions). The optimistic code will -catch the error and back off to call the slower but guaranteed correct -expr command procedure. (BL) - -1/16/97 (feature improvements) Added Tcl_ExprLongObj and Tcl_ExprDoubleObj -to round out expression-related procedures. (BL) - -1/16/97 (feature change) Under Windows, at startup the environment variables -"path", "comspec", and "windir" in any capitalization are converted -automatically to upper case. The PATH variable could be spelled as path, -Path, PaTh, etc. and it makes programming rather annoying. All other -environment variables are left alone. (CS) - -1/20/97 (new features) Rewrote the "lsort" command: - - The new version is based on reentrant merge sort code provided - by Richard Hipp, so it eliminates the reentrancy and stability - problems with the old qsort-based implementation. - - The new version supports a -dictionary option for sorting, and - it also supports a -index option for sorting lists using one - element for comparison. - - The new version is an object command, so it works well with the - Tcl compiler, especially in conjunction with the new -index - option. When the -index option is used, this version of lsort - is more than 100 times faster than the Tcl 7.6 lsort, which had - to use the -command option to get the same effect. (JO) - -1/20/97 (feature improvements) Added the improved debugging support for Tcl -objects prototyped by Karl Lehenbauer . -If TCL_MEM_DEBUG is defined, the object creation calls use Tcl_DbCkalloc -directly in order to record the caller's source file name and line -number. (BL) - -1/21/97 (removed feature) Desupported the tcl_precision variable: if -set, it is ignored. Tcl now uses the full 17 digits of precision when -converting real numbers to strings (with the new object system real -numbers are rarely converted to strings so there is no efficiency -disadvantage to printing all 17 digits; the new scheme improves -accuracy and simplifies several APIs). (JO) -*** POTENTIAL INCOMPATIBILITY *** - -1/21/97 (feature change) Removed the "interp" argument for the -procedures Tcl_GetStringFromObj, Tcl_StringObjAppend, and -Tcl_StringObjAppendObj. Also removed the "interp" argument for -the updateStringProc procedure in Tcl_ObjType structures. With -the tcl_precision changes above, these are no longer needed. (JO) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a1, but not with Tcl 7.6 *** - -1/22/97 (bug fix) Fixed http.tcl so that http_reset does not result in -an extra call to the command callback. In addition, if the transaction -gets a premature eof, the state(status) is "eof", not "ok". (BW) - ------------------ Released 8.0a2, 1/24/97 ----------------------- - -1/29/97 (feature change) Changed how two digit years are parsed in the -clock command. The old interface just added 1900 which will seem -broken by the year 2000. The new scheme follows the POSIX standard -and treats dates 70-99 as 1970-1999 and dates 00-38 as 2000-2038. All -other two digit dates are undefined. (RJ) -*** POTENTIAL INCOMPATIBILITY *** - -2/4/97 (bug fix) Fixed bug in clock code that dealt with relative -dates. Using the relative month code you could get an invalid date -because it jumped into a non-existant day. (For example, Jan 31 -to Feb 31.) The code now will return the last valid day of the -month in these situations. Thanks to Hume Smith for sending in -this bug fix. (RJ) - -2/10/97 (feature change) Eliminated Tcl_StringObjAppend and -Tcl_StringObjAppendObj procedures, replaced them with Tcl_AppendToObj -and Tcl_AppendStringsToObj procedures. Added new procedure -Tcl_SetObjLength. (JO) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2, but not with Tcl 7.6 *** - -2/10/97 (new feature) Added Tcl_WrongNumArgs procedure for generating -error messages about incorrect number of arguments. (JO) - -2/11/97 (new feature, bug fix) http package. Added -accept to http_config -so you can set the Accept header. Added -handler option to http_get so -you can supply your own data handler. Also fixed POST operation to -set the correct MIME type on the request. (BW) - -2/22/97 (bug fix) Fixed bug that caused $tcl_platform(osVersion) to be -computed incorrectly under AIX. (JO) - -2/25/97 (new feature, feature change) Added support for both int and long -integer objects. Added Tcl_NewLongObj/Tcl_GetLongFromObj/Tcl_SetLongFromObj -procedures and renamed the Tcl_Obj internalRep intValue member to -longValue. Tcl_GetIntFromObj now checks for integer values too large to -represent as non-long integers. Changed Tcl_GetAllObjTypes to -Tcl_AppendAllObjTypes. (BL) - -3/5/97 (new feature) Added new Tcl_SetListObj procedure to round out -collection of procedures that set the type and value of existing Tcl -objects. (BL) - -3/6/97 (new feature) Added -global flag for interp invokehidden. (JL) - -3/6/97 (new feature, feature change) Added isNativeObjectProc field to the -Tcl_CmdInfo structure to indicate (when 1) if the command has an -object-based command procedure. Removed the nameLength arg from -Tcl_CreateObjCommand since command names can't contain null characters. (BL) - -3/6/97 (bug fix) Fixed bug in "unknown" procedure that caused auto- -loading to fail on commands whose names begin with digits. (JO) - -3/7/97 (bug fix) Auto-loading now works in Safe Base. Safe interpreters -only accept the Version 2 and onwards tclIndex files. (JL) - -3/13/97 (bug fix) Fixed core dump due to interaction between aliases and -hidden commands. Bug found by Lindsay Marshall. (JL) - -3/14/97 (bug fix) Fixed mac bugs relating to time. The -gmt option -now adjusts the time in the correct direction. (Thanks to Ed Hume for -reporting a fix to this problem.) Also fixed file "mtime" etc. to -return times from GMT rather than local time zone. (RJ) - -3/18/97 (feature change) Declaration of objv in Tcl_ObjCmdProc function -changed from "Tcl_Obj *objv[]" to "Tcl_Obj *CONST objv[]". All Tcl object -commands changed to use new declaration of objv. Naive translation of -string-based command procs to object-based command procs could very easily -have yielded code where the contents of the objv array were changed. This -is not a problem with string-based command procs, but doing something as -simple as objv[2] = objv[3] would corrupt the runtime stack and cause Tcl to -crash. Introduced CONST in declaration of objv so that attempted assignment -of new pointer values to elements of the objv array will be caught by the -compiler. (CCS) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 *** - -3/19/97 (bug fix) Fixed panic due to object sharing. The root cause was -that old code was using Tcl_ResetResult instead of Tcl_ResetObjResult. (JL) - -3/20/97 (new feature) Added a new subcommand for the file -command. file attributes filename can give a list of platform-specific -options (such as file/creator type on the Mac, permissions on Unix) or -set the values of them. Added a new subcommand for the file -command. file nativename name gives back the platform-specific form -for the file. This is useful when the filename is needed to pass to -the OS, such as exec under Windows 95 or AppleScript on the Mac. For -more info, see file.n. (SRP) - -3/24/97 (removed feature) Removed the tcl_safePolicyPath procedure. Now -the policy path is computed from the auto_path by appending the directory -'policies' to each element. Also fixed several bugs in automatic tracking -of auto_path by computed policy path. (JL) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 *** - -4/8/97 (new feature) If the variable whose name is passed to lappend doesn't -already exist, and there are no value arguments, lappend now creates the -variable with an empty value instead of returning an error. Change suggested -by Tom Tromey. (BL) - -4/9/97 (feature change) Changed the name of the TCL_PART1_NOT_PARSED flag to -TCL_PARSE_PART1. (BL) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 *** - -4/10/97 (bug fixes) Fixed various compilation-related bugs: - - "UpdateStringOfCmdName should never be invoked" panic. - - Bad code generated for expressions not in {}'s inside catch commands. - - Segmentation fault in some command procedures when two argument - object pointers refer to the same object. - - Second level of substitutions were never done for expressions not - in {}'s that consist of a single variable reference: e.g., - "set x 27; set bool {$x}; if $bool {puts foo}" would fail with error. - - Bad code generated when code storage was grown while compiling some - expressions: ones with compilation errors or consisting of only a - variable reference. - - Bugs involving multiple interpreters: wasn't checking that a - procedure's code was compiled for the same interpreter as the one - executing it, and didn't invalidate code on hidden-exposed command - transitions. - - "Bad stack top" panic when executing scripts that require a huge - amount of stack space. - - Incorrect sharing of code for procedure bodies, and procedure code - deallocated before last execution of the procedure finished. - - Fixed compilation of expression words in quotes. For example, - if "0 < 3" {puts foo}. - - Fixed performance bug in array set command with large assignments. - - Tcl_SetObjLength segmentation fault setting length of empty object. - - If Tcl_SetObjectResult was passed the same object as the interpreter's - result object, it freed the object instead of doing nothing. Bug fix - by Michael J. McLennan. - - Tcl_ListObjAppendList inserted elements from the wrong list. Bug fix - by Michael J. McLennan. - - Segmentation fault if empty variable list was specified in a foreach - command. Bug fix by Jan Nijtmans. - - NULL command name was always passed to Tcl_CreateTrace callback - procedure. - - Wrong string representation generated for the value LONG_MIN. - For example, expr 1<<31 printed incorrectly on a 32 bit machine. - - "set {a($x)} 1" stored value in wrong variable. - - Tcl_GetBooleanFromObj was not checking for garbage after a numeric - value. - - Garbled "bad operand type" error message when evaluating expressions - not surrounded by {}'s. (BL) - -4/16/97 (new feature) The expr command now has the "rand()" and -"srand()" functions for getting random numbers in expr. (RJ) - -4/23/97 (bug fix) Fixed core dump in bgerror when the error handler command -deletes the current interpreter. Found by Juergen Schoenwald. (JL) - -4/23/97 (feature change) The notifier interfaces have been redesigned -to make embedding in applications with external event loops possible. -A number of interfaces in the notifier and the channel drivers have -changed. Refer to the Notifier.3 and CrtChannel.3 manual entries for -more details. (SS) -*** POTENTIAL INCOMPATIBILITY *** - -4/23/97 (removed feature) The Tcl_File interfaces have been removed. -The Tcl_CreateFileHandler/Tcl_DeleteFileHandler interfaces now take -Unix fd's and are only supported on the Unix platform. -Tcl_GetChannelFile has been replaced with Tcl_GetChannelHandle. -Tcl_MakeFileChannel now takes a platform specific file handle. (SS) -*** POTENTIAL INCOMPATIBILITY *** - -4/23/97 (removed feature) The modal timeout interface has been -removed (Tcl_CreateModalTimeout/Tcl_DeleteModalTimeout) (SS) -*** POTENTIAL INCOMPATIBILITY *** - -4/23/97 (feature change) Channel drivers are now required to correctly -implement blocking behavior when they are in blocking mode. (SS) -*** POTENTIAL INCOMPATIBILITY *** - -4/23/97 (new feature) Added the "binary" command for manipulating -binary strings. Also, changed the "puts", "gets", and "read" commands -to preserve embedded nulls. (SS) - -4/23/97 (new feature) Added tcl_platform(byteOrder) element to the -tcl_platform array to identify the native byte order for the current -host. (SS) - -4/23/97 (bug fix) Fixed bug in date parsing around year boundaries. (SS) - -4/24/97 (bug fix) In the process of copying a file owned by another user, -Tcl was changing the owner of the copy back to the owner of the original -file, therefore causing further file operations to fail because the current -user didn't own the copy anymore. The owner of the copy is now left as the -current user. (CCS) - -4/24/97 (feature change) Under Windows, don't automatically uppercase the -environment variable "windir" -- it's supposed to be lower case. (CCS) - -4/29/97 (new feature) Added namespace support based on a namespace -implementation by Michael J. McLennan of Lucent Technologies. A namespace -encapsulates a collection of commands and variables to ensure that they -won't interfere the commands and variables of other namespaces. The global -namespace holds all global variables and commands. Additional namespaces are -created with the new namespace command. The new variable command lets you -create Tcl variables inside a namespace. The names of Tcl variables and -commands may now be qualified by the name of the namespace containing them. -The key namespace-related commands are summarized below: - - namespace ?eval? name arg ?arg...? - Used to define the commands and variables in a namespace. - Optionally creates the namespace. - - namespace export ?-clear? ?pattern pattern...? - Specifies which commands are exported from a namespace. These - are the ones that can be imported into another namespace. - - namespace import ?-force? ?pattern pattern...? - Makes the specified commands accessible in the current namespace. - - namespace current - Returns the name of the current namespace. - - variable name ?value? ?name ?value?...? - Creates one or more namespace variables. (BTL) - -5/1/97 (bug fix) Under Windows, file times were reported in GMT. Should be -reported in local time. (CCS) - -5/2/97 (feature change) Changed the name of the two Tcl variables used for -tracing bytecode compilation and execution to tcl_traceCompile and -tcl_traceExec respectively. These variables are now documented in the -tclvars man page. (BL) - -5/5/97 (new feature) Support "end" as the index for "lsort -index". (BW) - -5/5/97 (bug fixes) Cleaned up the way the http package resets connections (BW) - -5/8/97 (feature change) Newly created Tcl objects now have a reference count -of zero instead of one. This simplifies C code that stores newly created -objects in Tcl variables or in data structures such as list objects. That C -code must increment the new object's reference count since the variable or -data structure will contain a long-term reference to the object. Formerly, -when new objects started out with reference count one, it was necessary to -decrement the new object's reference count after the store to make sure it -was left with the correct value; this is no longer necessary. (BL) - -5/9/97 (new feature) Added the Tcl_GetsObj interface that takes an -object reference instead of a dynamic string (as in Tcl_Gets). (SS) - -5/12/97 (new feature) Added Tcl_CreateAliasObj and Tcl_GetAliasObj C APIs -to allow an alias command to be created with a vector of Tcl_Obj structures -and to get the vector back later. (JL) - -5/12/97 (feature change) Changed Tcl_ExposeCommand and Tcl_HideCommand to -leave an object result instead of a string result. (JL) - -5/14/97 (feature change) Improved the handling of the interpreter result. -This is still either an object or a string, but the two values are now kept -consistent unless some C code reads or writes interp->result directly. See -the SetResult man page for details. Removed the Tcl_ResetObjResult -procedure. (BL) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 *** - -5/16/97 (new feature) Added "fcopy" command to move data between -channels. Refer to the manual page for more information. Removed the -"unsupported0" command since it is obsolete now. (SS) - -5/16/97 (new feature) Added Tcl_GetStringResult procedure to allow programs -to get an interpreter's result as a string. If the result was previously set -to an object, this procedure will convert the object to a string. Use of -Tcl_GetStringResult is intended to replace direct access to interp->result, -which is not safe. (BL) - -5/20/97 (new features) Fixed "fcopy" to return the number of bytes -transferred in the blocking case. Updated the http package to use -fcopy instead of unsupported0. Added -timeout and -handler options to -http_get. http_get is now blocking by default. It is only non-blocking -if you supply a -command argument. (BW) - -5/22/97 (bug fix) Fixed several bugs in the "lsort" command having to do -with the -dictionary option and the presence of numbers embedded in the -strings. (JO) - ------------------ Released 8.0b1, 5/27/97 ----------------------- - -6/2/97 (bug fix) Fixed bug in startup code that caused a problem in -finding the library files when they are installed in a directory -containing a space in the name. (SS) - -6/2/97 (bug fix) Fixed bug in Unix notifier where the select mask was -not being cleared under some circumstances. (SS) - -6/4/97 (bug fix) Fixed bug that prevented creation of Tk widgets in -namespaces. Tcl_CreateObjCommand and Tcl_CreateCommand now always create -commands in the global namespace unless the command names are qualified. Tcl -procedures continue to be created in the current namespace by default. (BL) - -6/6/97 (new features) Added new namespace API procedures -Tcl_AppendExportList and Tcl_Export to allow C code to get and set a -namespace's export list. (BL) - -6/11/97 (new feature) Added Tcl_ConcatObj. This object-based routine -parallels the string-based routine Tcl_Concat. (SRP) - -6/11/97 (new feature) Added Tcl_SetObjErrorCode. This object-based -routines parallels the string-based routine Tcl_SetErrorCode. (SRP) - -6/12/97 (bug fix) Fix the "unknown" procedure so that wish under Windows -will exec an external program, instead of always complaining "console1 not -opened for writing". (CCS) - -6/12/97 (bug fix) Fixed core dump experienced by the following simple -script: - interp create x - x alias exec exec - interp delete x -This panic was caused by not installing the new CmdDeleteProc when exec -got redefined by the alias creation step. Reported by Lindsay Marshal (JL) - -6/13/97 (new features) Tcl objects newly created by Tcl_NewObj now have a -string representation that points to a shared heap string of length 1. (They -used to have NULL bytes and typePtr fields. This was treated as a special -case to indicate an empty string, but made type manager implementations -complex and error prone.) The new procedure Tcl_InvalidateStringRep is used -to mark an object's string representation invalid and to free any storage -associated with the old string representation. (BL) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 *** - -6/16/97 (bug fix) Tcl_ScanCountedElement could leave braces unmatched -if the string ended with a backslash. (JO) - -6/17/97 (bug fix) Fixed channel event bug where readable events would be -lost during recursive events loops if the input buffers contained -data. (SS) - -6/17/97 (bug fix) Fixed bug in Windows socket code that didn't -reenable read events in the case where an external entity is also -reading from the socket. (SS) - -6/18/97 (bug fix) Changed initial setting of the notifier service mode -to TCL_SERVICE_NONE to avoid unexpected event handling during -initialization. (SS) - -6/19/97 (bug fix/feature change) The command callback to fcopy is now -called in case of errors during the background copy. This adds a second, -optional argument to the callback that is the error string. The callback -in case of errors is required for proper cleanup by the user of fcopy. (BW) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** - -6/19/97 (bug fix) Fixed a panic due to the following four line script: - interp create x - x alias foo bar - x eval rename foo blotz - x alias foo {} -The problem was that the interp code was not using the actual current name -of the command to be deleted as a result of unaliasing foo. (JL) - -6/19/97 (feature change) Pass interp down to the ChannelOption and -driver specific calls so system errors can be differentiated from syntax -ones. Changed Tcl_DriverGetOptionProc type. Affects Tcl_GetChannelOption, -TcpGetOptionProc, TtyGetOptionProc, etc. (DL) -*** POTENTIAL INCOMPATIBILITY *** - -6/19/97 (new feature) Added Tcl_BadChannelOption for use by by driver -specific option procedures (Set and Get) to return a complete and -meaningful error message. (DL) - -6/19/97 (bug fixes) If a system call error occurs while doing an -fconfigure on tcp or tty/com channel: return the appropriate error -message (instead of the syntax error one or none). (Fixed for Unix and -most of the Win and Mac drivers). (DL) - -6/20/97 (feature change) Eval is no longer assumed as the subcommand name -in namespace commands: you must now write "namespace eval nsName {...}". -Abbreviations of namespace subcommand names are now allowed. (BL) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 *** - -6/20/97 (feature change) Changed the errorInfo traceback message for -compilation errors from "invoked from within" to "while compiling". (BL) - -6/20/97 (bug fixes) Fixed various compilation-related bugs: - - "UpdateStringOfCmdName should never be called" and - "UpdateStringOfByteCode should never be called" panics. - - Segfault in TclObjInterpProc getting procedure name after evaluation - stack is reallocated (grown). - - Could not use ":" at end of variable and command names. - - Bad code generated for while and for commands with test expressions - enclosed in quotes: e.g., "set i 0; while "$i > 5" {}". - - Command trace procedures would crash if they did a Tcl_EvalObj that - reallocated the evaluation stack. - - Break and continue commands did not reset the interpreter result. - - The Tcl_ExprXXX routines, both string- or object-based, always - modified the interpreter result even if there was no error. - - The argument parsing procedure used by several compile procedures - always treated "]" as end of a command: e.g., "set a ]" would fail. - - Changed errorInfo traceback message for compilation errors from - "invoked from within" to "while compiling". - - Problem initializing Tcl object managers during interpreter creation. - - Added check and error message if formal parameter to a procedure is - an array element. (BL) - -6/23/97 (new feature) Added "registry" package to allow manipulation -of the Windows system registry. See manual entry for details. (SS) - -6/24/97 (feature change) Converted http to a package and added the -http1.0 subdirectory of the Tcl script library. This means you have -to do a "package require http" to use this, as advertised in the man page. (BW) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** - -6/24/97 (bug fix) Ensure that Tcl_Set/GetVar C APIs, when called without -TCL_LEAVE_ERR_MSG, don't touch the interp result. (DL) - -6/26/97 (feature change) Changed name of Tcl_ExprStringObj to -Tcl_ExprObj. (BL) -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** - ------------------ Released 8.0b2, 6/30/97 ----------------------- - -7/1/97 (new feature) TCL_BUILD_SHARED flag set in tclConfig.sh -when Tcl has been built with --enable-shared. A new tclLibObjs -make target, echoing the list of the .o's needed to build a tcl -library, is now provided. (DL) - -7/1/97 (feature change) compat/getcwd.c removed and changed the -only place where getcwd is used so a new USEGETWD flag selects -the use of the replacement "getwd". Adding this flag is recommended -for SunOS 4 (because getcwd on SunOS 4 uses a pipe to pwd(1)!). (DL) - -7/7/97 (feature change) The split command now supports binary data (i.e., -null characters in strings). (BL) - -7/7/97 (bug fix) string first returned the wrong result if the first -argument string was empty. (BL) - -7/8/97 (bug fix) Fixed core dump in fcopy that could occur when a command -callback was supplied and an error or eof condition caused no background -activity. A refcount bug triggered a panic in Tcl_ListObjAppendElement. (BW) - -7/8/97 (bug fix) Relaxed the pattern matching on http_get so you do not -need a trailing path component. You can now get away with just -http_get www.scriptics.com (BW) - -7/9/97 (bug fix) Creating anonymous interpreters no longer smashes existing -commands with names similar to the generated name. Previously creating an -anonymous interpreter could smash an existing command, now it skips until -it finds a command name that isn't being used. (JL) - -7/9/97 (feature change) Removed the policy management mechanism from the -Safe Base; left the aliases to source and load modules, and to do a limited -form of the "file" command. See entry of 11/15/96. (JL) - -7/9/97 (bug fixes) Fixed various compilation-related bugs: - - Line numbers in errorInfo now are the same as those in Tcl7.6 unless -there are compilation errors. Compilation error messages now include the -entire command in error. - - Trailing ::s after namespace names weren't being ignored. - - Could not refer to an namespace variable with an empty name using a -name of the form "n::". (BL) - -7/9/97 (bug fix) Fixed bug in Tcl_Export that prevented you from exporting -from other than the current namespace. (BL) - -7/9/97 (bug fix) env.test was removing env var needed for proper finding -of libraries in child process. (DL) - -7/10/97 (bug fixes/new feature) Cleanup in Tcl_MakeSafe. Less information -is leaked to safe interps. Error message fixes for interp sub commands. -Likewise changes in safealias.tcl; tcl_safeCreateInterp can now be called -without argument to generate the slave name (like in interp create). (DL) - -7/10/97 (bug fixes) Bytecode compiler now generates more detailed -command location information: subcommands as well as commands now have -location information. This means command trace procedures now get the -correct source string for each command in their command parameter. (BL) - -7/22/97 (bug fixes) Performance improvement in Safe interpreters -handling. Added new mask value to (tclInt.h) Interp.flags record. (DL) - -7/22/97 (bug fix) Fixed panic in 'interp target {} foo'. This bug -was present since Tcl 7.6. (JL) - -7/22/97 (bug fix) Fixed bug in compilation of procedures in namespaces: the -procedure's namespace must be used to look up compile procedures, not the -current namespace. (BL) - -7/22/97 (bug fix) Use of the -channel option of http_get was not setting -the end of line translations mode on the channel, so copying binary data -with the -channel option was corrupting the result on non-unix platforms. (BW) - -7/22/97 (bug fixes) file commands and ~user (seg fault and other -improper returns). (DL) - -7/23/97 (feature change) Reenabled "vwait" in Safe Base. (JL) - -7/23/97 (bug fixes) Fixed two bugs involving read traces on array variables -in procedures: trace procedures were sometimes not called, and reading -nonexistant array elements didn't create undefined element variables that -could later be defined by trace procedures. (BL) - -7/24/97 (bug fix) Windows memory allocation performance was -superlinear in some cases. Made the Mac allocator generic and changed -both the Mac and Windows platforms to use the new allocator instead of -malloc and free. (SS) - -7/24/97 - 8/12/97 (bug fixes/change of features) Completely revamped safe -sourcing/loading (see safe.n) to hide pathnames, use virtual -paths tokens instead, improved security in several respects and made it -more tunable. Multi level interp loading can work too now. Package auto -loading now works in safe interps as long as the package directory is in -the auto_path (no deep crawling allowed in safe interps). (DL) -*** POTENTIAL INCOMPATIBILITY with previous alpha and beta releases *** - -7/24/97 (bug fixes) Made Tcl_SetVar* and Tcl_NewString* treat a NULL value -as an empty string. (This fixes hairy crash case where you would crash -because load command for other interps assumed presence of -errorInfo...). (DL) - -7/28/97 (bug fix) Fixed pkg_mkIndex to understand namespaces. It will -use the export list of a namespace and create auto_index entries for -all export commands. Those names are in their fully qualified form in the -auto_index. Therefore, I tweaked unknown to try both $cmd and ::$cmd. -Also fixed pkg_mkIndex so you can have "package require" commands inside -your packages. These commands are ignored, which is mostly ok except -when you must load another package before loading yours because of -linking dependencies. (BW) - -7/28/97 (bug fix) A variable created by the variable command now persists -until the namespace is destroyed or the variable is unset. This is true even -if the variable has not been initialized; these variables used to be -destroyed if an error occurred when accessing them. In addition, the "info -vars" command lists uninitialized namespace variables, while the "info -exists" command returns 0 for them. (BL) - -7/29/97 (feature change) Changed the http package to use the ::http -namespace. http_get renamed to http::geturl, http_config renamed to -http::config, http_formatQuery renamed to http::formatQuery. -It now provides the 2.0 version of the package. -The 1.0 version is still available with the old names. -*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b2 but not with Tcl 7.6 *** - -7/29/97 (bug fix, new feature) Tcl_Main now uses Tcl objects internally to -preserve NULLs in commands and command output. Added new API procedure -Tcl_RecordAndEvalObj that resembles Tcl_RecordAndEval but takes an object -containing a command. (BL) - -7/30/97 (bug fix) Tcl freed strings in the environ array even if it -did not allocate them. (SS) - -7/30/97 (bug fix) If a procedure is renamed into a different namespace, it -now executes in the context of that namespace. (BL) - -7/30/97 (bug fix) Prevent renaming of commands into and from namespaces as -part of hiding them. (JL) - -7/31/97 (feature change) Moved the history command from C to tcl. -This uses the ::history namespace. The "words" and "substitute" options -are no longer supported. In addition, the "keep" option without a value -returns the current keep limit. There is a new "clear" option. -The unknown command now supports !! again. (BW) -*** POTENTIAL INCOMPATIBILTY *** - -7/30/97 (bug fix) Made sure that a slave can not fool the master into -hiding the wrong command. Made sure we don't crash in hiding + namespaces -issues. (DL) - -8/4/97 (bug fix) Concat, eval, uplevel, and similar commands were -incorrectly trimming trailing space characters from their arguments -even when the space characters were preceded by a backslash. (JO) - -8/4/97 (bug fix) Removed the hard link between bgerror and tkerror. -Only bgerror is supported in tcl core. Tk will still look for a -tkerror but using regular tcl code for that feature. (DL) -*** POTENTIAL INCOMPATIBILTY with code relying on the hard link *** - -8/6/97 (bug fix) Reduced size required for compiled bytecodes by using a -more compact encoding for the command pc-to-source map. (BL) - -8/6/97 (new feature) Added support for additional compilation and execution -statistics when Tcl is compiled with the TCL_COMPILE_STATS flag. (BL) - -8/7/97 (bug fix) Expressions not in {}s that have a comparison operator as -the topmost operator must be compiled out-of-line (call the expr cmd at -runtime) to properly support expr's two-level substitution semantics. An -example is "set a 2; set b {$a}; puts [expr $b == 2]". (BL) - -8/11/97 (bug fix) The catch command would sometimes crash if a variable name -was given and the bytecode evaluation stack was grown when executing the -argument script. (BL) - -8/12/97 (feature change) Reinstated the variable tcl_precision to control -the number of digits used when floating-point values are converted to -strings, with default of 12 digits. However, had to make tcl_precision -shared among all interpreters (except that safe interpreters can't -modify it). This makes the Tcl 8.0 behavior almost identical to 7.6 -except that the default precision is 12 instead of 6. (JO) -*** POTENTIAL INCOMPATIBILITY *** - ------------------ Released 8.0, 8/18/97 ----------------------- - -8/19/97 (bug fix) Minimal fix for glob -nocomplain bugs: -"glob -nocomplain unreadableDir/*" was generating an anonymous -error. More in depth fixes will come with 8.1. (DL). - -8/20/97 (bug fix) Removed check for FLT_MIN in binary command so -underflow conditions are handled by the compiler automatic -conversions. (SS) - -8/20/97 (bug fixes) Fixed several compilation-related bugs: - - Array cmd wasn't detecting arrays that, while compiled, do not yet - exist (e.g., are marked undefined since they haven't been assigned - to yet). - - The GetToken procedure in tclCompExpr.c wasn't recognizing properly - whether an integer token was invalid. For example, "0x$" is not - a valid integer. - - Performance bug in TclExecuteByteCode: the size of its stack frame - was reduced by over 20% by moving errorInfo code elsewhere. - - Uninitialized memory read error in tclCompile.c. (BL) - -8/21/97 (bug fix) safe::interpConfigure now behave like Tk widget's -configure : it changes only the options you provide and you can get -the current value of any single option. New ?-nested boolean? and -?-statics boolean? for all safe::interp* commands but we still -accept (upward compatibility) the previously defined non valued -flags ?-noStatics? and ?-nestedLoadOk?. Improved the documentation. (DL). - -8/22/97 (bug fix) Updated PrintDbl.3 to reflect the fact that the -tcl_precision variable is still used and that it is now shared by all -interpreters. (BL) - -8/25/97 (bug fix) Fixed array access bug in IllegalExprOperandType -procedure in tclExecute.c: it was not properly supporting the || and && -operators. (BL) - -8/27/97 (bug fix) In cases where a channel handler was created with an -empty event mask while data was still buffered in the channel, the -channel code would get stuck spinning on a timer that would starve -idle handlers. This mostly happened in Tk when reading from stdin. (SS) - -9/4/97 (bug fix) Slave interps now inherit the maximum recursion limit -of their parent instead of starting back at the default. {nb: this still -does not prevent stack overflow by multi-interps recursion or aliasing} (DL) - -9/11/97 (bug fix) An uninitialized variable in Tcl_WaitPid caused -pipes to fail to report eof properly under Windows. (SS) - -9/12/97 (bug fix) "exec" was misidentifying some DOS executables as not -executable. (CCS) - -9/14/97 (bug fix) Was using the wrong structure in sizeof operation in -tclUnixChan.c. (JL) - -9/15/97 (bug fix) Fixed notifier to break out of do-one-event loop if -Tcl_WaitForEvent returns 1, so that callers of Tcl_DoOneEvent will get -a chance to check whether the event just handled is significant. This -affected mainly recursive calls to Tcl_VWaitCmd; these did not get a -chance to notice that the variable they were waiting for has been set -and thus they didn't terminate the vwait. (JL, DL, SS) - -9/15/97 (bug fix) Alignment problems in "binary format" would cause a -crash on some platforms when formatting floating point numbers. (SS) - -9/15/97 (bug fix) Fixed bug in Macintosh socket code. Now passes all -tests in socket.test that are not platform specific. (Thanks to Mark -Roseman for the pointer on the fix.) (RJ) - -9/18/97 (bug fix) Fixed bug -dictionary option of lsort that could -cause the compare function to run off the end of an array if the -number only contained 0's. (Thanks to Greg Couch for the report.) (RJ) - -9/18/97 (bug fix) TclFinalizeEnvironment was not cleaning up -properly. (DL, JI) - -9/18/97 (bug fix) Fixed long-standing bug where an "array get" command -did not trigger traces on the array or its elements. (BL) - -9/18/97 (bug fixes) Fixed compilation-related bugs: - - Fixed errorInfo traceback information for toplevel coomands that - contain nested commands. - - In the expr command, && and || now accept boolean operands as well - as numeric ones. (BL) - -9/22/97 (bug fix) Fixed bug that prevented translation modes from being -set independently for input and output on sockets if input was "auto". (JL) - -9/24/97 (bug fix) Tcl_EvalFile(3) and thus source(n) now works fine on -files containing NUL chars. (DL) - -9/26/97 (bug fix) Fixed use of uninitialized memory in the environ array -that later could cause random core dumps. Applies to all platforms. (JL) - -9/26/97 (bug fix) Fixed use of uninitialized memory in socket address data -structure under some circumstances. This could cause random core dumps. -This applies only to Unix. (JL) - -9/26/97 (bug fix) Opening files on PC-NFS volumes would cause a hang -until the system timed after the file was closed. (SS) - -10/6/97 (bug fix) The join(n) command, though objectified, was loosing -NULs in the joinString and in list elements after the 2nd one. -Now you can "join $list \0" for instance. (DL) - -10/9/97 (bug fix) Under windows, if env(TMP) or env(TEMP) referred to a -non-existent directory, exec would fail when trying to create its temporary -files. (CCS) - -10/9/97 (bug fix) Under mac and windows, "info hostname" would crash if -sockets were installed but the hostname could not be determined anyhow. -Tcl_GetHostName() was returning NULL when it should have been returning -an empty string. (CCS) - -10/10/97 (bug fix) "file attribute /" returned error on windows. (CCS) - -10/10/97 (bug fix) Fixed the auto_load procedure to handle procedures -defined in namespaces better. Also fixed pgk_mkIndex so it sees procedures -defined in nested namespaces. Index entries are still only made for -exported procedures. (BW) - -10/13/97 (bug fix) On unix, for files with unknown group or owner -attributes, querying the "file attributes" would return an error rather than -returning the group's or owner's id number, although tha command accepts -numbers when setting the file's group or owner. (CCS) - -10/22/97 (bug fix) "fcopy" did not eval the callback script at the -global scope. (SS) - -10/22/97 (bug fix) Fixed the signature of the CopyDone callback used in -the http package(s) so they can handle error cases properly. (BW) - -10/28/97 (bug fixes) Fixed a problem where lappend would free the Tcl object -in a variable if a Tcl_ObjSetVar2 failed because of an error calling a trace -on the variable. (BL) - -10/28/97 (bug fix) Changed binary scan to properly handle sign -extension of integers on 64-bit or larger machines. (SS) - -11/3/97 (bug fixes) Fixed several bugs: - - expressions such as "expr ($x)" must be compiled out-of-line - (call the expr command procedure at runtime) to ensure the correct - behavior when "$x" is an expression such as "5+10". - - "array set a {}" now creates a new array var with an empty array - value if the var didn't already exist. - - "lreplace $foo end end" no longer returns an error (just an empty - list) if foo is empty. - - upvar will no longer create a variable in a namespace that refers - to a variable in a procedure. - - deleting a command trace within a command trace callback would - make the code that calls traces to reference freed memory. - - significantly sped up "string first" and "string last" (fix from - darrel@gemstone.com). - - seg fault in Tcl_NewStringObj() when a NULL is passed as the byte - pointer argument and Tcl is compiled with -DTCL_MEM_DEBUG. - - documentation and error msg fixes. (BL) - -11/3/97 (bug fix) Fixed a number of I/O bugs related to word sizes on -64-bit machines. (SS) - -11/6/97 (bug fix) The exit code of the first process created by Tcl -on Windows was not properly reported due to an initialization -problem. (SS) - ------------------ Released 8.0p1, 11/7/97 ----------------------- - -11/19/97 (bug fix) Fixed bug in linsert where it sometimes accidently -cleared out a shared argument list object. (BL). - -11/19/97 (bug fix) Autoloading in namespaces was not working properly. -auto_mkindex is still not really namespace aware but most common -cases should now be handled properly (see init.test). (BW, DL) - -11/20/97 (enhancement) Made the changes required by the new Apple -Universal Headers V.3.0, so that Tcl will compile with CW Pro 2. - -11/24/97 (bug fix) Fixed tests in clock test suite that needed the --gmt flag set. Thanks to Jan Nijtmans for reporting the problem. (RJ) - ------------------ Released 8.0p2, 11/25/97 ----------------------- - -12/3/97 (bug fix/optimization) Removed uneeded and potentially dangerous -instances of double evaluations if "if" and "expr" statements from -the library files. It is recommended that unless you need a double -evaluation you always use "expr {...}" instead of "expr ..." and -"if {...} ..." instead of "if ... ...". It will also be faster -thanks to the byte compiler. (DL) - ----- Shipped as part of the plugin2.0b5 as 8.0p2Plugin1, Dec 8th 97 ---- - -12/8/97 (bug fix) Need to protect the newly accepted channel in an -accept callback on a socket, otherwise the callback may close it and -cause an error, which would cause the C code to attempt to close the -now deleted channel. Bumping the refcount assures that the channel sticks -around to be really closed in this case. (JL) - -12/8/97 (bug fix) Need to protect the channel in a fileevent so that it -is not deleted before the fileevent handler returns. (CS, JL) - -12/18/97 (bug fix) In the opt argument parsing package: if the description -had only flags, the "too many arguments" case was not detected. The default -value was not used for the special "args" ending argument. (DL) - -1/15/98 (improvement) Moved common part of initScript in common file. -Moved windows specific initialization to init.tcl so you can initialize -Tcl in windows without having to call Tcl_Init which is now only -searching for init.tcl {back ported from 8.1}. (DL) - ----- Shipped as part of the plugin as 8.0p2Plugin2, Jan 15th 98 ---- - -5/27/98 (bug fix) Windows socket driver did not notice new data arriving -on nonblocking sockets until the event loop was entered. (SS) - -5/27/98 (bug fix) Windows socket driver used FIONREAD, which is not -supported correctly by WinSock. (SS) - -6/9/98 (bug fix) Generic channel code failed to report readable file -events on buffered data that was left behind by a gets or read that -did not consume all available data. (SS) - -6/18/98 (bug fix) Compilation of loop expressions was too aggressive -and incorrectly inlined non-literal expressions. (SS) - -6/18/98 (bug fix) "info var" and "info locals" incorrectly reported -the existence of compiler temporary variables. (SS) - -6/18/98 (bug fix) Dictionary sorting used signed character -comparisons. (SS) - -6/18/98 (bug fix) Compile procs corrupted the exception stack in some -cases. (SS) - -6/18/98 (bug fix) Array set had erratic behavior when initializing a -variable from an empty value list. (SS) - -6/18/98 (bug fix) The Windows registry package had a bad bounds check -that could lead to a crash. (SS) - -6/18/98 (bug fix) The foreach compile proc did not correctly handle -non-local variable references. (SS) - -6/25/98 (new features) Added name resolution hooks to support [incr Tcl]. -There are new internal Tcl_*Resolver* APIs to add, query and remove the hooks. -With this changes it should be possible to dynamically load [incr Tcl] -as an extension. (MM) - -7/1/97 (bug fix) The commands "info args, body, default, procs" did -not correctly handle imported procedures. (RJ) - -7/6/98 (improvement) pkg_mkIndex now implements the "package require" -command. This makes it possible to create index files for packages -that require another package and then execute code from that package in -their file. Previously, this would throw an error because the required -package had not been loaded. The -nopkgrequied flag is provided to -revert back to the old functionality. (EMS) - -7/6/98 (improvement) back-ported the -direct flag from 8.1 into -pkg_mkIndex. This results in pkgIndex.tcl files that contain direct -source or load commands instead of tclPkgSetup commands. (EMS) - -7/6/98 (improvement) made changes to the AuxData items structures to support -storage of compiled scripts on disk. Also some related minor changes in -the compilation and execution engine. (EMS) - -6/4/98 (enhancement) Added new internal routines to support inserting -and deleting from the stat, access, and open-file-channel mechanisms. -TclAccessInsertProc, TclStatInsertProc, & TclOpenFileChannelInsertProc -insert pointers to such routines; TclAccessDeleteProc, TclStatDeleteProc, -& TclOpenFileChannelDeleteProc delete pointers to such routines. See -the file generic/tclIOUtils.c for more details. (SKS) - -7/1/98 (enhancement) Added a new internal C variable -tclPreInitScript. This is a pointer to a string that may hold an -initialization script; If this pointer is non-NULL it is evaluated in -Tcl_Init() prior to the built-in initialization script defined in the -file generic/tclInitScript.h. (SKS) - -7/6/98 (bug fix) Removed dead code in PlatformInitExitHandler so that -the TCL_LIBRARY value can be safely patched in binaries. (BW) - -7/24/98 (enhancement) Incorporated a new version of auto_mkindex that -can support the [incr Tcl] class structures. This version will index -all procedures in a source file, not just those where "proc" starts -at the beginning of the line. If you want the old behavior, use the -auto_mkindex_old procedure. (MM) - -7/24/98 (feature change) Changed the Windows registry key to be -HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, and to store the path -in the default value instead of "Root". Also, this key can be -specified at compile time in case Tcl is being used in a different -context where it needs an alternate library path from the standard Tcl -installation. (SS) - -7/24/98 (feature change) Changed the search order for init.tcl. The -tcl_library variable can now be set before calling Tcl_Init to avoid -doing any searches. If it isn't set, then Tcl checks -env(TCL_LIBRARY), the static value set at compile time, an install -directory relative to the executable, a source directory relative to -the executable, and a tcl directory relative to the source heirarchy -containing the executable. See the comment at the top of -generic/tclInitScript.h for more details. (SS) - -7/27/98 (config change) Changed the use of the DBGX flag in configure.in -and the makefile to be TCL_DBGX. Users of tclConfig.sh may need to pass -this through their configure files with AC_SUBST. (BW) - -729/98 (bug fix) Changed [info body] to return a copy of the body of a -compiled procedure instead of the body itself, to avoid invalidation -of the internal rep and loss of the byte-codes. (EMS) - -8/5/98 (bug fix) The platform init code could walk off the end of a -buffer when reading the PkgPath registry value on Windows. (SS) - -8/5/98 (Windows makefile change) Introduced a set of macros to deal with -exporting symbols when compiling DLLS on Windows. See win/README for -details. (EMS) - -8/5/98 (addendum) Added a second Windows registry key under -HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, named "pkgPath". -This is a multi-string value used to initialize the tcl_pkgPath -variable. This is required if extension DLLs are in architecture specific -subdirectories. (SS) - -8/6/98 (new feature) Added tcl_findLibrary to init.tcl for use by -extensions, including Tk. This searches in a canonical way for -an extensions library directory and initialization file. (BW) - -8/10/98 (bug fix) Imported commands used to get lost if the target -of the import was redefined. Tcl_CreateCommand and Tcl_CreateObjCommand -were updated to restore import links. (Note that if you rename a command, -the import links move to the new name, and if you delete a command then -the import links get lost. These semantics have not changed.) (MC) - --------- Released 8.0.3 to the Tcl Consortium CD-ROM project, 8/10/98 ------ - -9/3/98 (bug fix) Tcl_Realloc was failing under Windows because the -GlobalReAlloc API was not correctly re-allocating blocks that were -32k+. The fix was to use newer Win32 APIs (HeapAlloc, HeapFree, and -HeapReAlloc.) (BS) - -10/5/98 (bug fix) Fixed bug in pkg_mkIndex that caused some files that do -a "package require" of packages in the Tcl libraries to give a warning like - warning: "xx.tcl" provides more than one package ({xx 2.0} {yy 0.3}) -and generate a broken pkgIndex.tcl file. (EMS) - -10/5/98 (bug fix) Pkg_mkIndex was not doing a case-insensitive comparison -of extensions to determine whether to load or source a file. Thus, under -Windows, MYDLLNAME.DLL was sourced, and mydllname.dll loaded. (EMS) - -10/5/98 (new feature) Created a new Tcl_Obj type, "procbody". This object's -internal representation holds a pointer to a Proc structure. Extended -TclCreateProc to take both strings and "procbody". (EMS) - -10/13/98 (bug fix) The "info complete" command can now handle strings -with NULLs embedded. Thanks to colin@field.medicine.adelaide.edu.au -for providing this fix. (RJ) - -10/13/98 (bug fix) The "lsort -dictionary" command did not properly -handle some numbers starting with 0. Thanks to Richard Hipp - for submitting the fix to Scriptics. (RJ) - -10/13/98 (bug fix) The function Tcl_SetListObj was creating an invalid -Tcl_Obj if the list had zero elements (despite what the comments said -it would do). Thanks to Sebastian Wangnick for reporting the -problem. (RJ) - -10/20/98 (new feature) Added tcl_platform(debug) element to the -tcl_platform array on Windows platform. The existence of the debug -element of the tcl_platform array indicates that the particular Tcl -shell has been compiled with debug information. Using -"info exists tcl_platform(debug)" a Tcl script can direct the -interpreter to load debug versions of DLLs with the load -command. (SKS) - -10/20/98 (feature change) The Makefile and configure scripts have been -changed for IRIX to build n32 binaries instead of the old 32 abi -format. If you have extensions built with the o32 abi's you will need -to update them to n32 for them to work with Tcl. (RJ) -*** POTENTIAL INCOMPATIBILITY *** - -10/23/98 (bug fix) tcl_findLibrary had a stray ] in one of the -pathnames it searched for the initialization script. tclInitScript.h -was incorrectly adding the parent of tcl_library to tcl_pkgPath. This -logic was moved into init.tcl, and the initialization of auto_path was -documented. Thanks to Donald Porter and Tom Silva for related -patches. (BW) - -10/29/98 (bug fix) Fixed Tcl_NotifyChannel to use Tcl_Preserve instead -of Tcl_RegisterChannel so that 1) unregistered channels do not get -closed after their first fileevent, and 2) errors that occur during -close in a fileevent script are actually reflected by the close -command. (BW) - -10/30/98 (bug fix) Overhaul of pkg_mkIndex to deal with transitive -package requires and packages split among scripts and binary files. -Also fixed ommision of global for errorInfo in tcl_findLibrary. (BW) - -11/08/98 (bug fix) Fixed the resource command to always detect -the case where a file is opened a second time with the same -permissions. IM claims that this will always cause the same -FileRef to be returned, but in MacOS 8.1+, this is no longer the case, -so we have to test for this explicitly. (JI) - -11/10/98 (feature change) When compiling with Metrowerk's MSL, use the -exit function from MSL rather than ExitToShell. This allows MSL to -clean up its temporary files. Thanks to Vince Darley for this -improvement. (JI) - ------------------ Released 8.0.4, 11/19/98 ------------------------- - -11/20/98 (bug fix) Handle possible NULL return in TclGetStdFiles. (RJ) - -11/20/98 (bug fix) The dltests would not build on SGI. They reported -that you could not mix n32 with 032 binaries. The configure script -has been modified to get the EXTRA_CFLAGS from the tcl configure -script. [Bug id: 840] (RJ) - -12/3/98 (bug fix) Windows NT creates sockets so they are inheritable -by default. Fixed socket code so it turns off this bit right after -creation so sockets aren't kept open by exec'ed processes. [Bug: 892] -Thanks to Kevin Kenny for this fix. (SS) - -1/11/98 (bug fix) On HP, "info sharedlibextension" was returning -empty string on static apps. It now always returns ".sl". (RJ) - -1/28/99 (configure change) Now support -pipe option on gcc. (RJ) - -2/2/99 (bug fix) Fixed initialization problem on Windows where no -searching for init.tcl would be performed if the registry keys were -missing. (stanton) - -2/2/99 (bug fix) Added support for HKEY_PERFORMANCE_DATA and -HKEY_DYN_DATA keys in the "registry" command. (stanton) - -2/2/99 (bug fix) ENOTSUP and EOPNOTSUPP clashed on some Linux -variants. (stanton) - -2/2/99 (enhancement) The "open" command has been changed to use the -object interfaces. (stanton) - -2/2/99 (bug fix) In some cases Tcl would crash due to an overflow of -the exception stack resulting from a missing byte code in some -expressions. (stanton) - -2/2/99 (bug fix) Changed configure so Linux and IRIX shared libraries -are linked with the system libraries. (stanton) - -2/2/99 (bug fix) Added support for BSDI 4.x (BSD/OS-4*) to the -configure script. (stanton) - -2/2/99 (bug fix) Fixed bug where upvar could resurrect a namespace -variable after the namespace had been deleted. (stanton) - -2/2/99 (bug fix) In some cases when creating variables, the -interpreter result was being modified even if the TCL_LEAVE_ERR_MSG -flag was set. (stanton) - -2/2/99 (bug fix & new feature) Changed the socket drivers to properly -handle failures during an async socket connection. Added a new -fconfigure option "-error" to retrieve the failure message. See the -socket.n manual entry for details. (stanton) - -2/2/99 (bug fix) Deleting a renamed interp alias could result in a -panic. (stanton) - -2/2/99 (feature change/bug fix) Changed the behavior of "file -extension" so that it splits at the last period. Now the extension of -a file like "foo..o" is ".o" instead of "..o" as in previous versions. -*** POTENTIAL INCOMPATIBILITY *** - ------------------ Released 8.0.5, 3/9/99 ------------------------- - -======== Changes for 8.0 go above this line ======== -======== Changes for 8.1 go below this line ======== - -6/18/97 (new feature) Tcl now supports international character sets: - - All C APIs now accept UTF-8 strings instead of iso8859-1 strings, - wherever you see "char *", unless explicitly noted otherwise. - - All Tcl strings represented in UTF-8, which is a convenient - multi-byte encoding of Unicode. Variable names, procedure names, - and all other values in Tcl may include arbitrary Unicode characters. - For example, the Tcl command "string length" returns how many - Unicode characters are in the argument string. - - For Java compatibility, embedded null bytes in C strings are - represented as \xC080 in UTF-8 strings, but the null byte at the end - of a UTF-8 string remains \0. Thus Tcl strings once again do not - contain null bytes, except for termination bytes. - - For Java compatibility, "\uXXXX" is used in Tcl to enter a Unicode - character. "\u0000" through "\uffff" are acceptable Unicode - characters. - - "\xXX" is used to enter a small Unicode character (between 0 and 255) - in Tcl. - - Tcl automatically translates between UTF-8 and the normal encoding for - the platform during interactions with the system. - - The fconfigure command now supports a -encoding option for specifying - the encoding of an open file or socket. Tcl will automatically - translate between the specified encoding and UTF-8 during I/O. - See the directory library/encoding to find out what encodings are - supported (eventually there will be an "encoding" command that - makes this information more accessible). - - There are several new C APIs that support UTF-8 and various encodings. - See Utf.3 for procedures that translate between Unicode and UTF-8 - and manipulate UTF-8 strings. See Encoding.3 for procedures that - create new encodings and translate between encodings. See - ToUpper.3 for procedures that perform case conversions on UTF-8 - strings. - -9/18/97 (enhancement) Literal objects are now shared by the ByteCode -structures created when compiled different scripts. This saves up to 45% -of the total memory needed for all literals. (BL) - -9/24/97 (bug fixes) Fixed Tcl_ParseCommand parsing of backslash-newline -sequences at start of command words. Suppressed Tcl_EvalDirect error logging -if non-TCL_OK result wasn't an error. (BL) - -10/17/97 (feature enhancement) "~username" now refers to the users' home -directory on Windows (previously always returned failure). (CCS) - -10/20/97 (implementation change) The Tcl parser has been completely rewritten -to make it more modular. It can now be used to parse a script without actually -executing it. The APIs for the new parser are not correctly exported, but -they will eventually be exported and augmented with Tcl commands so that -Tcl scripts can parse other Tcl scripts. (JO) - -10/21/97 (API change) Added "flags" argument to Tcl_EvalObj, removed -Tcl_GlobalEvalObj procedure. Added new procedures Tcl_Eval2 and -Tcl_EvalObjv. (JO) -*** POTENTIAL INCOMPATIBILITY *** - -10/22/97 (API change) Renamed Tcl_ObjSetVar2 and Tcl_ObjGetVar2 to -Tcl_SetObjVar2 and Tcl_GetObjVar2 (for consistency with other C APIs) -and changed the name arguments to be strings instead of objects. (JO) -*** POTENTIAL INCOMPATIBILITY *** - -10/27/97 (enhancement) Bytecode compiler rewritten to use the new Tcl -parser. (BL) - -11/3/97 (New routines) Added Tcl_AppendObjToObj, which appends the -string rep of one Tcl_Obj to another. Added Tcl_GetIndexFromObjStruct, -which is similar to Tcl_GetIndexFromObj, except that you can give an -offset between strings. This allows Tcl_GetIndexFromObjStruct to be -called with a table of records which have strings in them. (SRP) - -12/4/97 (enhancement) New Tcl expression parser added. Added new procedure -Tcl_ParseExpr and new token types TCL_TOKEN_SUB_EXPR and -TCL_TOKEN_OPERATOR. Expression compiler is reimplemented to use this -parser. (BL) - -12/9/97 (bug fix) Tcl_EvalObj() increments/decrements the refcount of the -script object to prevent the object from deleting itself while in the -middle of being evaluated. (CCS) - -12/9/97 (bug fix) Memory leak in Tcl_GetsObjCmd(). (CCS) - -12/11/97 (bug fix) Environment array leaked memory when compiled with -Visual C++. (SS) - -12/11/97 (bug fix) File events and non-blocking I/O did not work on -pipes under Windows. Changed to use threads to achieve non-blocking -behavior. (SS) - -12/18/97 (bug fixes) Fixed segfault in "namespace import"; importing a -procedure that causes a cycle now returns an error. Modified "info procs", -"info args", "info body", and "info default" to return information about -imported procedures as well as procedures defined in a namespace. (BL) - -12/19/97 (enhancement) Added new Tcl_GetString() procedure that can be used -in place of Tcl_GetStringFromObj() if the string representation's length -isn't needed. (BL) - -12/18/97 (bug fix) In the opt argument parsing package: if the description -had only flags, the "too many arguments" case was not detected. The default -value was not used for the special "args" ending argument. (DL) - -1/7/98 (clean up) Moved everything not absolutly necessary out of init.tcl -procs now in auto.tcl and package.tcl can be autoloaded if needed. (DL) - -1/7/98 (enhancement) tcltest made at install time will search for it's -init.tcl where it is, even when using virtual path compilation. (DL) - -1/8/98 (os bug workaround) when needed, using a replacement for memcmp so -string compare "char with high bit set" "char w/o high bit set" returns -the expected value on all platforms. (DL) - -1/8/98 (unix portability/configure) building from .../unix/targetName/ -subdirectories and simply using "../configure" should now work fine. (DL) - -1/14/98 (enhancement) Added new regular expression package that -supports AREs, EREs, and BREs. The new package includes new escape -characters, meta-syntax, and character classes inside brackets. -Regexps involving backslashes may behave differently. (MH) -*** POTENTIAL INCOMPATIBILITY *** - -1/16/98 (os workaround) Under windows, "file volume" was causing chatter -and/or several seconds of hanging when querying empty floppy drives. -Changed implementation to call an empirically-derived function that doesn't -cause this. (CCS) - -1/16/98 (enhancement) Converted regular expressions to a Tcl_Obj type so -their compiled form gets cached automatically. Reduced NSUBEXP from 100 -to 20. (BW) - -1/16/98 (documentation) Change unclear documentation and comments for -functions like Tcl_TranslateFileName() and Tcl_ExternalToUtfDString(). Now -it explicitly says they take an uninitialized or free DString. A DString -that is "empty" or "not holding anything" could have been interpreted as one -currently with a zero length, but with a large dynamically allocated buffer. -(CCS) - ------------------ Released 8.1a1, 1/22/98 ----------------------- - -1/28/98 (new feature) Added a "-direct" optional flag to pkg_mkIndex -to generate direct loading package indexes (such those you need -if you use namespaces and plan on using namespace import just after -package require). pkg_mkIndex still has limitations regarding -package dependencies but errors are now ignored and with -direct, correct -package indexes can be generated even if there are dependencies as long -as the "package provide" are done early enough in the files. (DL) - -1/28/98 (enhancement) Performance tuning of regexp and regsub. (CCS) - -1/28/98 (bug fix) regexp and regsub with "-indices" returned the byte-offsets -of the characters in the UTF-8 representation, not the character offsets -themselves. (CCS) - -1/28/98 (bug fix) "clock format 0 -format %Z -gmt 1" would return the local -timezone string instead of "GMT" on Solaris and Windows. - -1/28/98 (bug fix) Restore tty settings when closing serial device on Unix. -This is good behavior when closing real serial devices, essential when -closing the pseudo-device /dev/tty because the user's terminal settings -would be left useless, in raw mode, when tcl quit. (CCS) - -1/28/98 (bug fix) Tcl_OpenCommandChannel() was modifying the contents of the -argv array passed to it, causing problems for any caller that wanted to -continue to use the argv array after calling Tcl_OpenCommandChannel(). (CCS) - -2/1/98 (bug fix) More bugs with %Z in format string argument to strftime(): -1. Borland always returned empty string. -2. MSVC always returned the timezone string for the current time, not the - timezone string for the specified time. -3. With MSVC, "clock format 0 -format %Z -gmt 1" would return "GMT" the first - time it was called, but would return the current timezone string on all - subsequent calls. (CCS) - -2/1/98 (bug fix) "file stat" was broken on Windows. -1. "file stat" of a root directory (local or network) or a relative path that - resolved to a root directory (c:. when in pwd was c:/) was returning error. -2. "file stat" on a regular file (S_IFREG), the st_mode was sign extended to - a negative int if the platform-dependant type "mode_t" was declared as a - short instead of an unsigned short. -3. "file stat" of a network directory, the st_dev was incorrectly reported - as the id of the last accessed local drive rather than the id of the - network drive. (CCS) - -2/1/98 (bug fix) "file attributes" of a relative path that resolved to a -root directory was returning error. (CCS) - -2/1/98 (bug fix) Change error message when "file attribute" could not -determine the attributes for a file. Previously it would return different -error messages on Unix vs. Windows vs. Mac. (CCS) - -2/4/98 (bug fixes) Fixed several instances of bugs where the parser/compiler -would reach outside the range of allocated memory. Improved the array -lookup algorithm in set compilation. (DL) - -2/5/98 (change) The TCL_PARSE_PART1 flag for Set/Get(Obj)Var2 C APIs is now -deprecated and ignored. The part1 is always parsed when the part2 argument -is NULL. This is to avoid a pattern of errors for extension writers converting -from string based Tcl_SetVar() to new Tcl_SetObjVar2() and who could easily -forget to provide the flag and thus get code working for normal variables -but not for array elements. The performance hit is minimal. A side effect -of that change is that is is no longer possible to create scalar variables -that can't be accessed by tcl scripts because of their invalid name -(ending with parenthesis). Likewise it is also parsed and checked to -ensure that you don't create array elements of array whose name is a valid -array element because they would not be accessible from scripts anyway. -Note: There is still duplicate array elements parsing code. (DL) -*** POTENTIAL INCOMPATIBILITY *** - -2/11/98 (bug fix) Sharing objects between interps, such as by "interp -eval" or "send" could cause a crash later when dereferencing an interp -that had been deleted, given code such as: - set a {set x y} - interp create foo - interp eval foo $a - interp delete foo - unset a -Interp "foo" was gone, but "a" had a internal rep consisting of bytecodes -containing a dangling pointer to "foo". Unsetting "a" would attempt to -return resources back to "foo", causing a crash as random memory was -accessed. The lesson is that that if an object's internal rep depends on -an interp (or any other data structure) it must preserve that data in -some fashion. (CCS) - -2/11/98 (enhancement) The "interp" command was returning inconsistent error -messages when the specified slave interp could not be found. (CCS) - -2/11/98 (bug fix) Result codes like TCL_BREAK and TCL_CONTINUE were not -propagating through the master/slave interp boundaries, such as "interp -eval" and "interp alias". TCL_OK, TCL_ERROR, and non-standard codes like -teh integer 57 work. There is still a question as to whether TCL_RETURN -can/should propagate. (CCS) - -2/11/98 (bug fix) TclCompileScript() was derefering memory 1 byte before -start of the string to compile, looking for ']'. (CCS,DL) - -2/11/98 (bug fix) Tcl_Eval2() was derefering memory 1 byte before start -of the string to eval, looking for ']'. (CCS,DL) - -2/11/98 (bug fix) Compiling "set a(b" was running off end of string. (CCS,DL) - -2/11/98 (bug fix) Windows initialization code was dereferencing -uninitialized memory if TCL_LIBRARY environment didn't exist. (CCS) - -2/11/98 (bug fix) Windows "registry" command was dereferencing -uninitialized memory when constructing the $errorCode for a failed -registry call. (CCS) - -2/11/98 (enhancement) Eliminate the TCL_USE_TIMEZONE_VAR definition from -configure.in, because it was the same information as the already existing -HAVE_TM_ZONE definition. The lack of HAVE_TM_ZONE is used to work around a -Solaris and Windows bug where "clock format [clock sec] -format %Z -gmt 1" -produces the local timezone string instead of "GMT". (CCS) - -2/11/98 (bug fix) Memleaks and dereferencing of uninitialized memory in -regexp if an error occurred while compiling a regular expression. (CCS). - -2/18/98 (new feature) Added mutexes and thread local storage in order -to make Tcl thread safe. For testing purposes, there is a testthread -command that creates a new thread and an interpreter inside it. See -thread.test for examples, but this script-level interface is not fixed. -Each thread has its own notifier instance to manage its own events, -and threads can post messages to each other's message queue. -This uses pthreads on UNIX, and native thread support on other platforms. -You enable this by configuring with --enable-threads. Note that at -this time *Tk* is still not thread safe. Special thanks to -Richard Hipp: his earlier implementation inspired this work. (BW, SS, JI) - -2/18/98 (hidden feature change) The way the env() array is shared among -interpreters changed. Updates to env used to trigger write traces in -other interpreters. This undocumented feature is no longer implemented. -Instead, variable tracing is used to keep the C-level environ array in sync -with the Tcl-level env array. This required adding TCL_TRACE_ARRAY support -to Tcl_TraceVar2 so that array names works properly. (BW) -*** POTENTIAL INCOMPATIBILITY *** - -2/18/98 (enhancement) Conditional compilation for unix systems (e.g., -IRIX, SCO) that use f_bsize instead of st_blksize to determine disk block -size. (CCS) - -2/23/98 (bug fix) Fixed the emulation of polling selects in the threaded -version of the Unix notifier. The bug was showing up on a multiprocessor -as starvation of the notifier thread. (BW) - ------------------ Released 8.1a2, Feb 23 1998 ----------------------- - -9/22/98 (bug fix) Changed the value of TCL_TRACE_ARRAY so it no longer -conflicts with the deprecated TCL_PARSE_PART1 flag. This should -improve portability of C code. (stanton) - -10/6/98 (bug fix) The compile procedure for "if" incorrectly attempted -to match against the literal string "if", resulting in a stack -overflow when "::if" was compiled. It also would incorrectly accept -"if" instead of "elsif" in later clauses. (stanton) - -10/15/98 (new feature) Added a "totitle" subcommand to the "string" -command to convert strings to capitalize the first character of a string -and lowercase all of the other characters. (stanton) - -10/15/98 (bug fix) Changed regexp and string commands to properly -handle case folding according to the Unicode character -tables. (stanton) - -10/21/98 (new feature) Added an "encoding" command to facilitate -translations of strings between different character encodings. See -the encoding.n manual entry for more details. (stanton) - -11/3/98 (bug fix) The regular expression character classification -syntax now includes Unicode characters in the supported -classes. (stanton) - -11/6/98 (bug fix) Variable traces were causing crashes when upvar -variables went out of scope. [Bug: 796] (stanton) - -11/9/98 (bug fix) "format" now correctly handles multibyte characters -in %s format strings. (stanton) - -11/10/98 (new feature) "regexp" now accepts three new switches -("-line", "-lineanchor", and "-linestop") that control how regular -expressions treat line breaks. See the regexp manual entry for more -details. (stanton) - -11/17/98 (bug fix) "scan" now correctly handles Unicode -characters. (stanton) - -11/17/98 (new feature) "scan" now supports XPG3 position specifiers -and the "%n" conversion character. See the "scan" manual entry for -more details. (stanton) - -11/17/98 (bug fix) The Tcl memory allocator now returns 8-byte aligned -chunks of memory which improves performance on Windows and avoids -crashes on other platforms. [Bug: 834] (stanton) - -11/23/98 (bug fix) Applied various regular expression performance bug -fixes supplied by Henry Spencer. (stanton) - -11/30/98 (bug fix) Fixed various thread related race conditions. [Bug: -880 & 607] (stanton) - -11/30/98 (bug fix) Fixed a number of memory overflow and leak -bugs. [Bug: 584] (stanton) - -12/1/98 (new feaure) Added support for Korean encodings. (stanton) - -12/1/98 (feature change) Changed the Tcl_EvalObjv interface to remove -the string and length arguments. -*** POTENTIAL INCOMPATIBILITY with previous alpha releases *** - -12/2/98 (bug fix) Fixed various bugs related to line feed -translation. [Bug: 887] (stanton) - -12/4/98 (new feature) Added a message catalog facility to help with -localizing Tcl scripts. Thanks to Mark Harrison for contributing the -initial implementation of the "msgcat" package. (stanton) - -12/7/98 (bug fix) The memory allocator was failing to update the -block list for large memory blocks that were reallocated into a -different address. [Bug: 933] (stanton) - ------------------ Released 8.1b1, Dec 10 1998 ----------------------- - -12/22/98 (performance improvement) Improved the -command option of the -lsort command to better use the object system for improved -performance (about 5x speed up). Thanks to Syd Polk for suppling the -patch. [RFE: 726] (rjohnson) - -2/10/99 (bug fix) Restored the Tcl_ObjSetVar2/Tcl_ObjGetVar2 -interfaces from 8.0 and renamed the Tcl_GetObjVar2/Tcl_SetObjVar2 -interfaces to Tcl_GetVar2Ex and Tcl_SetVar2Ex. This should provide -better compatibility with 8.0. (stanton) -*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** - -2/10/99 (bug fix) Made the eval interfaces compatible with 8.0 by -renaming Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to -Tcl_EvalEx and restoring Tcl_EvalObj and Tcl_GlobalEvalObj interfaces -so they match Tcl 8.0. (stanton) -*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** - -2/25/99 (bug fix/new feature) On Windows, the channel drivers for -consoles and serial ports now completely support file events. (redman) - -3/5/99 (bug fix) Integrated patches to fix various configure problems -that affected HP-UX-11, 64-bit IRIX, Linux, and Solaris. (stanton) - -3/9/99 (bug fix) Integrated various AIX related patches to improve -support for shared libraries. (stanton) - -3/9/99 (new feature) Added tcl_platform(user) to provide a portable -way to get the name of the current user. (welch) - -3/9/99 (new feature) Integrated the stub library mechanism contributed -by Jan Nijtmans, Paul Duffin, and Jean-Claude Wippler. This feature -should make it possible to write extensions that support multiple -versions of Tcl simultaneously. It also makes it possible to -dynamically load extensions into statically linked interpreters. This -patch includes the following changes: - - Added a Tcl_InitStubs() interface - - Added Tcl_PkgProvideEx, Tcl_PkgRequireEx, Tcl_PkgPresentEx, - and Tcl_PkgPresent. - - Added va_list versions of all VARARGS functions so they can be - invoked from wrapper functions. -See the manual for more information. (stanton) - - -3/10/99 (feature change) Replaced Tcl_AlertNotifier with -Tcl_ThreadAlert since the Tcl_AlertNotifier function relied on passing -internal data structures. (stanton) -*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** - -3/10/99 (new feature) Added a Tcl_GetVersion API to make it easier to -check the Tcl version and patch level from C. (redman) - -3/14/99 (feature change) Tried to unify the TclpInitLibrary path -routines to look in similar places from Windows to UNIX. The new -library search path is: TCL_LIBRARY, TCL_LIBRARY/../tcl8.1, relative -to DLL (Windows Only) relative to installed executable, relative to -develop executable, and relative to compiled-in in location (UNIX -Only.) This fix included: - - Defining a TclpFindExecutable - - Moving Tcl_FindExecutable to a common area in tclEncoding.c - - Modifying the TclpInitLibraryPath routines. -(surles) - -3/14/99 (feature change) Added hooks for TclPro Wrapper to initialize -the location of the encoding files and libraries. This fix included: - - Adding the TclSetPerInitScript routine. - - Modifying the Tcl_Init routines to evaluate the non-NULL - preinit script. - - Adding the Tcl_SetdefaultEncodingDir and Tcl_GetDefaultEncodingDir - routines. - - Modifying the TclpInitLibrary routines to append the default - encoding dir. -(surles) - -3/14/99 (feature change) Test suite now uses "test" namespace to -define the test procedure and other auxiliary procedures as well as -global variables. - - Global array testConfige is now called ::test::testConfig. - - Global variable VERBOSE is now called ::test::verbose, and - ::test::verbose no longer works with numerical values. We've - switched to a bitwise character string. You can set - ::test::verbose by using the -verbose option on the Tcl command - line. - - Global variable TESTS is now called ::test::matchingTests, and - can be set on the Tcl command line via the -match option. - - There is now a ::test::skipTests variable (works similarly to - ::test::matchTests) that can be set on the Tcl command line via - the -match option. - - The test suite can now be run in any working directory. When - you run "make test", the working directory is nolonger switched - to ../tests. -(hirschl) -*** POTENTIAL INCOMPATIBILITY *** - ---------------- Released 8.1b2, March 16, 1999 ---------------------- - -3/18/99 (bug fix) Fixed missing/incorrect characters in shift-jis table -(stanton) - -3/18/99 (feature change) The glob command ignores the -FS_CASE_IS_PRESERVED bit on file systesm and always returns -exactly what it gets from the system. (stanton) -*** POTENTIAL INCOMPATIBILITY *** - -3/19/99 (new feature) Added support for --enable-64bit. For now, -this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun -compiler. (redman) - -3/23/99 (bug fix) Fixed fileevents and gets on Windows consoles and -serial devices so that non-blocking channels do not block on partial -input lines. (redman) - -3/23/99 (bug fix) Added a new Tcl_ServiceModeHook interface. -This is used on Windows to avoid the various problems that people -have been seeing where the system hangs when tclsh is running -outside of the event loop. As part of this, renamed -TclpAlertNotifier back to Tcl_AlertNotifier since it is public. -(stanton) - -3/23/99 (feature change) Test suite now uses "tcltest" namespace to -define the test procedure and other auxiliary procedures as well as -global variables. The previously chosen "test" namespace was thought -to be too generic and likely to create conflits. -(hirschl) -*** POTENTIAL INCOMPATIBILITY *** - -3/24/99 (bug fix) Make sockets thread safe on Windows. -(redman) - -3/24/99 (bug fix) Fix cases where expr would incorrect return -a floating point value instead of an integer. (stanton) - -3/25/99 (bug fix) Added ASCII to big5 and gb2312 encodings. -(stanton) - -3/25/99 (feature change) Changed so aliases are invoked at current -scope in the target interpreter instead of at the global scope. This -was an incompatibility introduced in 8.1 that is being removed. -(stanton) -*** POTENTIAL INCOMPATIBILITY with previous beta releases *** - -3/26/99 (feature change) --enable-shared is now the default and build -Tcl as a shared library; specify --disable-shared to build a static Tcl -library and shell. -*** POTENTIAL INCOMPATIBILITY *** - -3/29/99 (bug fix) Removed the stub functions and changed the stub -macros to just use the name without params. Pass &tclStubs into the -interp (don't use tclStubsPtr because of collisions with the stubs on -Solaris). (redman) - -3/30/99 (bug fix) Loadable modules are now unloaded at the last -possible moment during Tcl_Finalize to fix various exit-time crashes. -(welch) - -3/30/99 (bug fix) Tcl no longer calls setlocale(). It looks at -env(LANG) and env(LC_TYPE) instead. (stanton) - -4/1/99 (bug fix) Fixed the Ultrix multiple symbol definition problem. -Now, even Tcl includes a copy of the Tcl stub library. (redman) - -4/1/99 (bug fix) Internationalized the registry package. - -4/1/99 (bug fix) Changed the implemenation of Tcl_ConditionWait and -Tcl_ConditionNotify on Windows. The new algorithm eliminates a race -condition and was suggested by Jim Davidson. (welch) - -4/2/99 (new apis) Made various Unicode utility functions public. -Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString, Tcl_UniCharLen, -Tcl_UniCharNcmp, Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha, -Tcl_UniCharIsDigit, Tcl_UniCharIsLower, Tcl_UniCharIsSpace, -Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar, Tcl_WinUtfToTChar, -Tcl_WinTCharToUtf (stanton) - -4/2/99 (feature change) Add new DDE package and removed the Tk -send command from the Windows version. Changed DDE-based send -code into "dde eval" command. The DDE package can be loaded -into tclsh, not just wish. Windows only. (redman) - -4/5/99 (bug fix) Changed safe-tcl so that the encoding command -is an alias that masks out the "encoding system" subcommand. -(redman) - -4/5/99 (bug fix) Configure patches to improve support for -OS/390 and BSD/OS 4.*. (stanton) - -4/5/99 (bug fix) Fixed crash in the clock command that occurred -with negative time values in timezones east of GMT. (stanton) - -4/6/99 (bug fix) Moved the "array set" C level code into a common -routine (TclArraySet). The TclSetupEnv routine now uses this API to -create an env array w/ no elements. This fixes the bug caused when -every environ varaible is removed, and the Tcl env variable is -synched. If no environ vars existed, the Tcl env var would never be -created. (surles) - -4/6/99 (bug fix) Made the Env module I18N compliant. (surles) - -4/6/99 (bug fix) Changed the FindVariable routine to TclpFindVariable, -that now does a case insensitive string comparison on Windows, and not -on UNIX. (surles) - ---------------- Released 8.1b3, April 6, 1999 ---------------------- - -4/9/99 (bug fix) Fixed notifier deadlock situation when the pipe used -to talk back notifier thread is filled with data. Found as a result of the -focus.test for Tk hanging. (redman) - -4/13/99 (bug fix) Fixed bug where socket -async combined with -fileevent for writing did not work under Windows NT. (redman) - -4/13/99 (encoding fix) Restored the double byte definition of GB2312 -and added the EUC-CN encoding. EUC-CN is a variant of GB2312 that -shifts the characters into bytes with the high bit set and includes -ASCII as a subset. (stanton) - -4/27/99 (bug fix) Added 'extern "C" {}' block around the stub table -pointer declaration so the stub library can be used from C++. (stanton) - ---------------- Released 8.1 final, April 29, 1999 ---------------------- - -4/22/99 (bug fix) Changed Windows NT socket implementation to avoid -creating a communication window. This avoids the problem where the -system hangs waiting for tclsh to respond to a system-wide synchronous -broadcast (e.g. if you change system colors). (redman) - -4/22/99 (bug fix) Added call to TclWinInit from TclpInitPlatform when -building a static library since DllMain will not be invoked. This -could break old code that explicitly called TclWinInit, but should be -simpler in the long run. (stanton) -*** POTENTIAL INCOMPATIBILITY *** - -4/23/99 (bug fix) Added support for the koi8-r Cyrillic -encoding. [Bug: 1771] (stanton) - -4/28/99 (bug fix) Changed internal Tcl_Obj usage to avoid freeing the -internal representation after the string representation has been -freed. This makes it easier to debug extensions. (stanton) - -4/30/99 (bug fix) Fixed a memory leak in CommandComplete. (stanton) - -5/3/99 (bug fix) Fixed a bug where the Tcl_ObjType was not being set -in a duplicated Tcl_Obj. [Bug: 1975, 2047] (stanton) - -5/3/99 (bug fix) Changed Tcl_ParseCommand to avoid modifying eval'ed -strings that are already null terminated. [Bug: 1793] (stanton) - -5/3/99 (new feature) Applied Jeff Hobbs's string patch which includes -the following changes: - - added new subcommands: equal, repeat, map, is, replace - - added -length option to "string compare|equal" - - added -nocase option to "string compare|equal|match" - - string and list indices can be an integer or end?-integer?. - - added optional first and last index args to string toupper, et al. -See the string.n manual entry for more details about the new string -features. [Bug: 1845] (stanton) - -5/6/99 (new feature) Added Tcl_UtfNcmp and Tcl_UtfNcasecmp to make Utf -string comparision easier. (stanton) - -5/7/99 (bug fix) Improved OS/390 support. [Bug: 1976, 1997] (stanton) - -5/12/99 (bug fix) Changed Windows initialization code to avoid using -GetUserName system call in favor of the env(USERNAME) variable. This -provides a significant startup speed improvement. (stanton) - -5/12/99 (bug fix) Replaced the per-interpreter regexp cache with a -per-thread cache. Changed the Regexp object to take advantage of this -extra cache. Added a reference count to the TclRegexp type so regexps -can be shared by multiple objects. Removed the per-interp regexp cache -from the interpreter. Now regexps can be used with no need for an -interpreter. This set of changes should provide significant speed -improvements for many Tcl scripts. [Bug: 1063] (stanton) - -5/14/99 (bug fix) Durining initialization on Unix, Tcl now extracts the -encoding subfield from the LANG/LC_ALL environment variables in cases -where the locale is not found in the built-in locale table. It also -attempts to initialize the locale subsystem so X11 is happy. [Bug: 1989] -(stanton) - -5/14/99 (bug fix) Applied the patch to fix 100-year and 400-year -boundaries in leap year code, from Isaac Hollander. [Bug: 2066] (redman) - -5/14/99 (bug fix) Fixed a crash caused by a failure to reset the result -before evaluating the test expression in an uncompiled for -statement. (stanton) - -5/18/99 (bug fix) Modified initialization code on Windows to avoid -inherenting closed or invalid channels. If the standard input is -anything other than a console, file, serial port, or pipe, then we fall -back to the standard Tk window console. (stanton) - -5/19/99 (bug fix) Added an extern "C" block around the entire tcl.h -header file to avoid C++ linkage issues. (redman) - -5/19/99 (new feature) Applied Jeff Hobb's patch to add -Tcl_StringCaseMatch to support case insensitive glob style matching and -Tcl_UniCharIs* character classification functions. (stanton) - -5/20/99 (bug fix) Added the directory containing the executuble and the -../lib directory relative to that to the auto_path variable. (redman) - ---------------- Released 8.1.1, May 25, 1999 ---------------------- - -5/21/99 (bug fix) Fixed launching command.com on Win95/98, no longer -hangs. [Bug: 2105] (redman) - -5/28/99 (bug fix) Fixed bug where dde calls were being passed an -invalid dde handle. [Bug: 2124] (stanton) - -6/1/99 (bug fix) Small configure.in patches. [Bug: 2121] (stanton) - -6/1/99 (bug fix) Applied latest regular expression patches to fix an -infinite loop bug and add support for testing whether a string could -match with additional input. [Bug: 2117] (stanton) - -6/2/99 (bug fix) Fixed incorrect computation of relative ordering in -Utf case-insensitive comparison. [Bug: 2135] (stanton) - -6/3/99 (bug fix) Fxied bug where string equal/compare -nocase -reported wrong result on null strings. [Bug: 2138] (stanton) - -6/4/99 (new feature) Windows build now uses Cygwin tools plus GNU -make and autoconf to build static/dynamic and debug/nodebug. (stanton) - -6/7/99 (new feature) Optimized string index, length, range, and -append commands. Added a new Unicode object type. (hershey) - -6/8/99 (bug fix) Rolled back Windows socket driver to 8.1.0 -version. (stanton) - -6/9/99 (new feature) Added Tcl_RegExpMatchObj and Tcl_RegExpGetInfo -to public Tcl API, these functions are needed by Expect. Changed -tools/genStubs.tcl to always write output in LF mode. (stanton) - -6/14/99 (new feature) Merged string and Unicode object types. Added -new public Tcl API functions: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj, -Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, -Tcl_AppendUnicodeToObj. (hershey) - -6/16/99 (new feature) Changed to conform to TEA specification, added -tcl.m4 and aclocal.m4 macro libraries for configure. (wart) - -6/17/99 (new feature) Added new regexp interfaces: -expanded, -line, --linestop, and -lineanchor switches. Renamed Tcl_RegExpMatchObj to -Tcl_RegExpExecObj and added new Tcl_RegExpMatchObj that is equivalent -to Tcl_RegExpMatch. Added public macros for regexp flags. Added -REG_BOSONLY flag to allow Expect to iterate through a string and only -find matches that start at the current position within the -string. (stanton) - -6/21/99 (bug fix) Fixed memory leak in TclpThreadCreate where thread -attributes were not being released. [Bug: 2254] (stanton) - -6/23/99 (new feature) Updated Unicode character tables to reflect -Unicode 2.1 data. (stanton) - -6/25/99 (new feature) Fixed bugs in non-greedy quantifiers for regular -expression code. (stanton) - -6/25/99 (new feature) Added initial implementation of new Tcl test -harness package. Modified test files to use new tcltest package. -(jenn) - -6/26/99 (new feature) Applied patch from Peter Hardie to add poke -command to dde and changed the dde package version number to -1.1. (redman) - -6/28/99 (bug fix) Applied patch from Peter Hardie to fix problem in -Tcl_GetIndexFromObj() when the key being passed is the empty string. -[Bug: 1738] (redman) - -6/29/99 (new feature) Added options to tcltest package: -preservecore, --limitconstraints, -help, -file, -notfile, and flags. (jenn) - -7/3/99 (new feature) Changed parsing of variable names to allow empty -array names. Now "$(foo)" is a variable reference. Previously you -had to use something line $::(foo), which is slower. This change was -requested by Jean-Luc Fontaine for his STOOOP package. (welch) - -7/3/99 (new feature) Added Tcl_SetNotifier (public API) and -associated hook points in the notifiers to be able to replace the -notifier calls at runtime. The Xt notifier and test program use this -hook. (welch) - -7/3/99 (new feature) Added a new variant of the "Trf core patch" from -Andreas Kupries that adds new C APIs Tcl_StackChannel, -Tcl_UnstackChannel, and Tcl_GetStackedChannel. This allows the Trf -extension to work without applying patches to the Tcl core. (welch) - -7/6/99 (new feature) Added -timeout option to http.tcl to handle -timeouts that occur during connection attempts to hosts that are -down. (welch) - -7/6/99 (bug fix) Applied new implementation of the Windows serial -port driver from Rolf Schroedter that fixes reading only one byte from -the port at a time. Uses polling every 10ms to implement -fileevents. [Bug: 1980 2217] (redman) - -7/8/99 (bug fix) Applied fix for bug in DFA state caching under -lookahead conditions (regular expressions). [Bug: 2318] (stanton) - -7/8/99 (bug fix) Fixed bug in string range bounds checking -code. (stanton) - ---------------- Released 8.2b1, July 14, 1999 ---------------------- - -7/16/99 (bug fix) Added Tcl_SetNotifier to stub table. [Bug: 2364] -Added check for Alpha/Linux to correct the IEEE floating point flag, -patch from Don Porter. (redman) - -7/20/99 (bug fix) Merged 8.0.5 code to handle tcl_library properly, -also fixed a bug that caused TCL_LIBRARY to be ignored. (hershey) - -7/21/99 (bug fix) Implemented modified socket driver for Windows that -uses a thread to manage the socket event window. Code works the same -on all supported versions of Windows and was based on original 8.1.0 -code. [Bug: 2178 2256 2259 2329 2323 2355] (redman) - -7/21/99 (new feature) Applied patch from Rolf Schroedter to add --pollinterval option to fconfigure for Windows serial ports. Allows -the maxblocktime to be modified to control how often serial ports are -checked for fileevents. Also added documentation for \\.\comX -notation for opening serial ports on Windows. (redman) - -7/21/99 (bug fix) Changed APIs in stub tables to use "unsigned long" -instead of the platform-specific "size_t", primarily after SunOS 4 -users could no longer compile. (redman) - -7/22/99 (bug fix) Fixed crashing during "array set a(b) {}". -[Bug: 2427] (redman) - -7/22/99 (bug fix) The install-sh script must be given execute -permissions prior to running. [Bug: 2413] (redman) - -7/22/99 (bug fix) Applied patch from Ulrich Ring to remove ANSI-style -prototypes in the code. [Bug: 2391] (redman) - -7/22/99 (bug fix) Added #if blocks around #includes of sys/*.h header -files, to allow an extension author on Windows to use the MetroWerks -compiler. [Bug: 2385] (redman) - -7/22/99 (bug fix) Fixed running the safe.test test suite, one change -to the Windows Makefile.in to fix paths and another in safe.test to -check for the tcl_platform(threaded) variable properly. (redman) - -7/22/99 (bug fix) Fixed hanging in new Win32 socket driver with -threads enabled. (redman) - -7/26/99 (bug fix) Fixed terminating of helper threads by holding any -mutexes from the primary thread while waiting for the helper thread to -terminate. Fixes dual-CPU WinNT hangs, only one rare sporadic hang -that still exists with dual-CPU WinNT. Also fixed test cases so that -they would not depend as much on timing for dual-CPU WinNT. (redman) - -7/27/99 (bug fix) Some test suite cleanup. (jenn) - -7/29/99 (bug fix) Applied patch to fix typo in .SH NAME line in -doc/Encoding.n [Bug: 2451]. Applied patch to avoid linking pack.n to -pack-old.n [Bug: 2469]. Patches from Don Porter. (redman) - -7/29/99 (bug fix) Allow tcl to open CON and NUL, even for redirection -of std channels. [Bug: 2393 2392 2209 2458] (redman) - -7/30/99 (bug fix) Applied fixed Trf patch from Andreas Kupries. -[Bug: 2386] (hobbs) - -7/30/99 (bug fix) Fixed bug in info complete. [Bug: 2383 2466] (hobbs) - -7/30/99 (bug fix) Applied patch to fix threading on Irix 6.5, patch -provided by James Dennett. [Bug: 2450] (redman) - -7/30/99 (bug fix) Fixed launching of 16bit applications on Win9x from -wish. The command line was being primed with tclpip82.dll, but it was -ignored later. - -7/30/99 (bug fix) Added functions to stub table, patch provided by Jan -Nijtmans. [Bug: 2445] (hobbs) - -8/1/99 (bug fix) Changed Windows socket driver to terminate threads -by sending a message to the window rather than calling -TerminateThread(), which seems to leak about 4k from the helper -thread's stack space. (redman) - ---------------- Released 8.2b2, August 5, 1999 ---------------------- - -8/4/99 (bug fix) Applied patches supplied by Henry Spencer to greatly -enhance performance of certain classes of regular expressions. -[Bug: 2440 2447] (stanton) - -8/5/99 (doc change) Made it clear that tcl_pkgPath was not set for -Windows. [Bug: 2455] (hobbs) - -8/5/99 (bug fix) Fixed reference to bytes that might not be null -terminated in tclLiteral.c. [Bug: 2496] (hobbs) - -8/5/99 (bug fix) Fixed typo in http.tcl. [Bug: 2502] (hobbs) - -8/9/99 (bug fix) Fixed test suite to handle larger integers -(64bit). Patch from Don Porter. (hobbs) - -8/9/99 (documentation fix) Clarified Tcl_DecrRefCount docs -[Bug: 1952]. Clarified array pattern docs [Bug: 1330]. Fixed clock docs -[Bug: 693]. Fixed formatting errors [Bug: 2188 2189]. Fixed doc error -in tclvars.n [Bug: 2042]. (hobbs) - -8/9/99 (bug fix) Fixed path handling in auto_execok [Bug: 1276] (hobbs) - -8/9/99 (internal api change) Removed the TclpMutexLock and TclpMutexUnlock -APIs and added a new exported api, Tcl_GetAllocMutex. These APIs are all for -the mutex used in the simple memory allocators. By making this change -we are able to substitute different implementations of the thread-related -APIs without having to recompile the Tcl core. (welch) - -8/9/99 (new C API) Tcl_GetChannelNames returns a list of open channel -names in the interpreter result. Still no Tcl-level version of this, -but server-like applications can use this to clean up files without -deleting interpreters. (welch) - -8/9/99 (bug fix) Traces were not firing on "info exists", which used to -happen in Tcl 7.6 and earlier. An "info exists" now fires a read trace, -if defined. This makes it possible to fully implement variables that -are defined via traces. (welch) - -8/10/99 (bug fix) Fixed Brent's changes so that they work on -Windows. (redman) - ---------------- Released 8.2b3, August 11, 1999 ---------------------- - -8/12/99 (Mac) Rearrange projects in tclMacProjects.sea.hqx so that the -build directory is separate from the sources. (Jim Ingham) - -8/12/99 (bug fix) Fixed bug in Tcl_EvalEx where the termOffset was not -being updated in cases where the evaluation returned a non TCL_OK -error code. [Bug: 2535] (stanton) - ---------------- Released 8.2.0, August 17, 1999 ---------------------- - -9/21/99 (config fixes) fixed several AIX configuration issues. gcc and -threading may still cause problems on AIX. (hobbs) - -9/21/99 (bug fix) fixed expr double-eval problem. [Bug: 732] (hobbs) - -9/21/99 (bug fix) fixed static buffer overflow problem. [Bug: 2483] (hobbs) - -9/21/99 (bug fix) fixed end-int linsert interpretation. [Bug: 2693] (hobbs) - -9/21/99 (bug fix) fixed bug when setting array in non-existent -namespace. [Bug: 2613] (hobbs) - ---- Released 8.2.1, October 04, 1999 - -10/30/99 (feature enhancement) new regexp engine from Henry Spencer -was patched in - should greatly reduce stack space usage. (spencer) - -10/30/99 (bug fix) fixed Purify reported memory leaks in findexecutable -test command, TclpCreateProcess on Unix, in handling of C environ array, -and in testthread code. No more known (reported) mem leaks for Tcl -built using gcc on Solaris 2.5.1. Also none reported for Tcl on NT -(using Purify 6.0). (hobbs) - -10/30/99 (bug fix) fixed improper bytecode handling of -'eval {set array($unknownvar) 5}' (also for incr) (hobbs) - -10/30/99 (bug fix) fixed event/io threading problems by making -triggerPipe non-blocking (nick kisserbeth) - -10/30/99 (bug fix) fixed Tcl_AppendStringsToObjVA and Tcl_AppendResultVA -to only iterates once over the va_list (avoiding non-portable memcpy). -(joe english, hobbs) - -10/30/99 (bug fix) removed savedChar trick in tclCompile.c that appeared -to be causing a segv when the literal table was released. -[Bug: 2459, 2515] (David Whitehouse) - -10/30/99 (bug fix) fixed [string index] to return ByteArrayObj -when indexing into one (test case string-5.16) [Bug: 2871] (hobbs) - -10/30/99 (bug fix) fixes for mac UTF filename handling (ingham) - ---- Released 8.2.2, November 04, 1999 - -11/19/99 (feature enhancement) bug fixes for http package as well as -patch required by TLS (SSL) extension that adds http::(un)register -and -type to http::geturl. Up'd http pkg version to 2.2. - -11/19/99 (bug fix) removed extra decr of numLevels in Tcl_EvalObjEx -that could cause seg fault (mjansen@wendt.de) - -11/19/99 (bug fixes) numerous minor big fixes, including correcting the -installation of the koi8-r encoding and tcltest1.0 on Windows. - -11/30/99 (bug fix) fixes scan where %[..] didn't match anything - -11/30/99 (bug fix) fixed setting of isNonBlocking flag in PipeBlockModeProc -so you can now close a non-blocking channel without waiting. - -11/30/99 (bug work-around) prevented the unloading of DLLs for Unix in -TclFinalizeLoad. This stops the seg fault on exit that some users would -see (ie with oratcl) when using DLLs that do nasty things like register -atexit handlers. - -12/07/99 (bug fix) fixes for 'expr + {[incr]}' and 'expr + {[error]}' -cases (different causes). - ---- Released 8.2.3, December 16, 1999 - -1999-09-14 (feature enhancement) added -start switch to regexp and regsub. - -1999-09-15 (feature enhancement) add 'array unset' command. - -1999-09-15 (feature enhancement) rewrote runtime libraries to use new -string functions - -1999-08-18 (feature enhancement) added 'file channels' command, along with -Tcl_GetChannelNames(Ex) public C APIs. - -1999-10-19 (feature enhancement) enhanced tcltest package - -1999-09-16 (feature enhancement) added -milliseconds switch to 'clock clicks' - -1999-10-28 (feature enhancement) added support for inline 'scan' - -1999-10-28 (feature enhancement) added support for touch functionality by -extendeding 'file atime' and 'file mtime' to take an optional time argument - -1999-11-24 (feature enhancement) added 'fconfigure $sock -lasterror' -command to Windows to query the last error received on a serial socket. - -1999-11-30 (bug fix) fixed handling of %Z on NT for timezones that don't -have DST - -1999-12-03 (feature enhancement) improved error message in bad octal cases -and improper use of comments. (hobbs) - -1999-12-07 (bug fix) fixed Tcl_ScanCountedElement to not step -beyond the end of the counted string - -1999-12-09 (feature enhancement) removed all references to 16 bit -compatibility code for Windows (hobbs) - -1999-12-10 (bug fix) removed check for vfork - Tcl now uses only fork in -exec. (hobbs) - -1999-12-10 (optimization) changed Tcl_ConcatObj to return a list -object when it receives all pure list objects as input (used by 'concat'), -added optimizations in Tcl_EvalObjEx for pure list case, and optimized -INST_TRY_CVT_TO_NUMERIC in TclExecuteByteCode for boolean objects. -(oakley, hobbs) - -1999-12-12 (feature enhancement) enhanced glob command with -type, -path, --directory and -join switches. (darley, hobbs) - -1999-12-21 (bug fix) changed CreateThread to _beginthreadex and -ExitThread to _endthreadex to prevent 4K mem leak (gravereaux) - -1999-12-21 (bug fix) fixed applescript for I18N - -1999-12-21 (feature enhancement) added -unique option to lsort (hobbs) - -1999-12-21 (bug fix) changed thread ids to longs (for 64bit systems) - ---- Released 8.3b1, December 22, 1999 - -2000-01-10 (feature enhancement) clock scan now supports the common -ISO 8601 date/time formats. See docs for details. (melski) - -2000-01-10 (bug fix) prevented \ooo substitution from accepting -non-octal digits [Bug: 3975] (hobbs) - -2000-01-11 (bug fix) fixed improper handling of DST by clock when -using relative times (like "1 month" or "tomorrow"). (melski) - -2000-01-12 (bug fix) improved build support for Tru64 v5, NetBSD -and Reliant Unix (hobbs) - -2000-01-12 (bug fix) made imported commands also import their -compile procedure (duffin) - -2000-01-12 (bug fix) fixed 'info procs ::namesp::*' behavior to return -procs in a namespace (dejong) - -2000-01-12 (feature enhancement) added support for setting permissions -symbolicly (like chmod) in [file attributes $file -permissions ...] (schoebel) - -2000-01-13 (bug fix) fixed lsort -dictionary problem when sorting -characters between 'Z' and 'a' (flawed upper/lower comparison logic) (melski) - ---- Released 8.3b2, January 13, 2000 - -2000-01-14 (feature enhancement) clock format %Q added, clock scan updated - -2000-01-20 (bug fix) corrected complex array elem compiling (Spjuth) - -2000-01-20 (bug fix) made [info body] always return a string type arg, -to prevent possible misuse of bytecodes in the wrong context (hobbs) - -2000-01-20 (bug fixes) several fixes to variable handling to prevent -possible crashes, and further definition of correct behavior (melski) - -2000-01-25 (bug fixes) improved QNX, Ultrix and OSF1 (Tru64) config and -compatibility (edge, furukawa) - -2000-01-25 (bug fix) fixed mem leak when calling lsort with a bad -command -argument (hobbs) - -2000-01-27 (feature enhancement) package mechanism overhaul: changed -behavior of pkg_mkIndex to do -direct by default, added -lazy option. -Fixed pkg_mkIndex to handle odd proc names and auto_mkIndex to use platform -independent file paths. Other fixes for odd package quirks. Added -::pkg namespace and ::pkg::create helper function. (melski) - -2000-02-01 (bug fix) fixed problem where http POST would send one extra -newline (vasiljevic) - -2000-02-02 (feature enhancement) added docs for new regexp -inline and --all switches. (hobbs) - -2000-02-08 (bug fix) corrected handling of "next monthname" in clock scan -(melski) - -2000-02-09 (bug fix) restored Mac source to build readiness and prevented -mac panic from an error when closing an async socket (steffen, ingham) - -2000-02-10 (feature enhancement) improved error reporting for failed -loads on Windows (dejong, hobbs) - ---- Released 8.3.0, February 10, 2000 - -2000-03 (bug fixes, feature enhancement) overhaul of http package for -proper handling of async callbacks (new options), version is now at 2.3 -(tamhankar, welch) - -2000-03 (performance enhancement) speedup in Windows filename handling (newman) -and ==/!= empty string in exprs. (hobbs) - -2000-03-27 (bug fix) added uniq'ing test to namespace export list to -prevent unnecessary mem growth (hobbs) - -2000-03-29 (bug fix) fixed mem leak when repeatedly sourcing the same -bytecompiled (tbc) code repeatedly across different interpreters (hobbs) - -2000-03-29 (config enhancement) improved build support for gcc/mingw on -Windows (nijtmans, hobbs) and added RPM target (melski) - -2000-03-31 (bug fix) corrected data encoding problem when using -"exec << $data" construct (melski) - -2000-04 (feature enhancement) overhaul of threading mechanism to better -support tcl level thread command (new APIs Tcl_ConditionFinalize, -Tcl_MutexFinalize, Tcl_CreateThread, etc, all docs in Thread.3). -(kupries, graveraux) -This enables the tcl level thread extension. (welch) - -2000-04-10 (bug fix) fixed infinite loop case in regexp -all (melski) - -2000-04-13 (config enhancement) added support for --enable-64bit-vis -Sparc target. (hobbs) - -2000-04-18 (bug fix) moved tclLibraryPath to thread-local storage to fix -possible race condition on MP machines (hobbs) - -2000-04-18 (config enhancement) added MacOS X build target and -tclLoadDyld.c dl type. (sanchez) - -2000-04-23 (bug fix) several Mac socket fixes (ingham) - -2000-04-24 (bug fix) fixed hang in threaded Unix case when backgrounded -exec process was running (dejong) - ---- Released 8.3.1, April 26, 2000 - -2000-04-26 (doc fix) updated/added documentation for many API's and -commands (melski) - -2000-05-02 (feature enhancement) added support for joinable threads; -extended API's for channels to allow channels to move between threads -(kupries) - -2000-05-02 (feature enhancement) changed error return for procedures -with incorrect args to be like the Tcl_WrongNumArgs API, with a "wrong -# args: ..." message printed, with an args list (hobbs) - -2000-05-08 (feature enhancement) added [array statistics] command - -2000-05-08 (performance enhancement) rewrote Tcl_StringCaseMatch -algorithm for better performance; this affects the [string match] -command; added "eq" and "ne" operands to expr, for testing -string equality and inequality (hobbs) - -2000-05-09 (feature enhancement) extended [lsearch] to support sorted -list searches and typed list searches (melski) - -2000-05-10 (feature enhancement) added [namespace exists] command -(darley) - -2000-05-18 (build enhancement) added support for mingw compile env and -cross-compiling (dejong) - -2000-05-18 (bug fix) corrected clock grammar to properly handle the -"ago" keyword when it follows multiple relative unit specifiers -(melski) - -2000-05-22 (compile fix) type cast cleanups (dejong) - -2000-05-23 (performance enhancement) added byte-compiled -implementation of [return] command and [string] command (melski) - -2000-05-26 (performance enhancement) extended byte-compiled [string] -command with support for [string compare/index/match] (hobbs) - -2000-05-27 (feature enhancement) added ability to set [info script] -return value ([info script ?newFileName?]) (welch) - -2000-05-31 (feature enhancement) added support for regexp and exact -pattern matching for [array names] (gazetta) - -2000-05-31 (feature enhancement) added -nocomplain and -- flags to -[unset] to allow for silent unset operation (hobbs) - ---- Released 8.4a1, June 6, 2000 - -2000-05-29 (bug fix) corrected resource cleanup in http error cases. -Improved handling of error cases in http. (tamhankar) - -2000-07 (feature rewrite) complete rewrite of the Tcl IO channel subsystem -to correct problems (hangs, core dumps) with the initial stacked channel -implementation. The new system has many more tests for robustness and -scalability. There are new C APIs (see Tcl_CreateChannel), but only -stacked channel drivers are affected (ie: TLS, Trf, iogt). The iogt -extension has been added to the core test code to test the system. -(hobbs, kupries) - **** POTENTIAL INCOMPATABILITY **** - -2000-07 (build improvements) cleanup of the makefiles and configure scripts -to correct support for building under gcc for Windows. (dejong) - -2000-08-07 (bug fix) corrected sizeof error in Tcl_GetIndexFromObjStruct. -(perkins) - -2000-08-07 (bug fix) correct off-by-one error in HistIndex, which was -causing [history redo] to start its search at the wrong event index. (melski) - -2000-08-07 (bug fix) corrected setlocale calls for XIM support and locale -issues in startup. (takahashi) - -2000-08-07 (bug fix) correct code to handle locale specific return values -from strftime, if any. (wagner) - -2000-08-07 (bug fix) tweaked grammar to properly handle the "ago" keyword -when it follows multiple relative unit specifiers, as in -"2 days 2 hours ago". (melski) - -2000-08-07 (doc fixes) numerous doc fixes to correct SEE ALSO and NAME -sections. (english) - -2000-08-07 (bug fix) new man pages memory.n, TCL_MEM_DEBUG.3, Init.3 and -DumpActiveMemory.3. (melski) - ---- Released 8.3.2, August 9, 2000 - -2000-06 thru 2000-11 (build improvements) Added support for mingw (gcc on -Windows), AIX-5 and Win64 builds (dejong, hobbs) - -2000-06-23 (feature enhancement) ability to use Tcl_Obj *s as hash keys (duffin) - -2000-06-29 (new features) added [mcmax] and [mcmset] and extended [unknown] in -msgcat package (duperval, krone, nelson) -=> msgcat 1.1 - -2000-08 thru 2000-09 added tclPlatDecls.h to default install (melski, hobbs) - -2000-08-24 (new feature) Enhanced trace syntax to add: - trace {add|remove|list} {variable|command} name ops command -(darley, melski) - -2000-09-06 (cross-platform feature) Set ^Z (\x1A) as default EOF char. (hobbs) - -2000-09-07 partial fix for bug 2460 to prevent exec mem leak on Windows for the -common case (gravereaux) - -2000-09-14 Improved string allocation growth for large strings (hintermayer, -melski) - -2000-09-14 New non-panic'ing mem allocation functions Tcl_AttemptAlloc, -Tcl_AttemptRealloc, Tcl_AttemptSetObjLength (melski) - -2000-09-20 (new features) completely new, enhanced syntax in tcltest package. -Backwards compatable with tcltest v1. (hom) -=> tcltest 2.0 - -2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that -didn't set nonBlocking correctly when resetting the flags for the write -side (mem leak) Correct mem leak in channels when statePtr was released -(hobbs) - -2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason) - -2000-10-06 (bug fix) corrected [file channels] to only return channels in -the current interpreter (hobbs) - -2000-10-20 (performance enhancement) call stat only when necessary in 'glob' to -speed up command significantly in base cases (hobbs) - -2000-10-27 Fixed mem leak in Tcl_CreateChannel. Re-purified core via test -suites. (hobbs) - -2000-10-30 (new feature) add "ja_JP.eucJP" map to "euc-jp" encoding (takahashi) - -2000-11-01 (mem leak) Corrected excessive mem use of info exists on a -non-existent array element (hobbs) - -2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded -environment (gravereaux) - -2000-11-03 (new feature) Tcl_SetMainLoop enables defining an event loop for -tclsh. This enables Tk as a truly loadable package. (hobbs) - ---- Released 8.4a2, November 3, 2000 - -2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that -didn't set nonBlocking correctly when resetting the flags for the write -side (mem leak) Correct mem leak in channels when statePtr was released -(hobbs) - -2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason) - -2000-10-06 (bug fix) corrected [file channels] to only return channels in -the current interpreter (hobbs) - -2000-10-20 (performance enhancement) call stat only when necessary in 'glob' to -speed up command significantly in base cases (hobbs) - -2000-11-01 (mem leak) Corrected excessive mem use of info exists on a -non-existent array element (hobbs) - -2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded -environment (gravereaux) - -2000-11-23 (mem leak) fixed potential memory leak in error case of lsort -(fellows) - -2000-12-09 (feature enhancement) changed %o and %x to use strtoul instead -of strtol to correctly preserve scan<>format conversion of large integers -(hobbs) -Fixed handling of {!} in expressions (hobbs, fellows) - -2000-12-14 (feature enhancement) improved (s)rand for 64-bit platforms -(porter) - -2001-01-04 (bug fix) corrected parsing of $tcl_libPath at startup on -Windows (porter) - -2001-01-30 (bug fix) Fixed possible hangs in fcopy. (porter) - -2001-02-15 (performance enhancement) improved efficiency of [string split] -(fellows) - -2001-03-13 (bug fix) Correctly possible memory corruption in string map {} -$str (fellows) - -2001-03-29 (bug fix) prevent potential race condition and security leak in -tmp filename creation on Unix. (max) -Fixed handling of timeout for threads (corrects excessive CPU usage issue -for Tk on Unix in threaded Tcl environment). (ruppert) - -2001-03-30 (bug fix) corrected Windows memory error on exit (wu) -Fixed race condition in readability of socket on Windows. - -2001-04-03 (doc fixes) numerous doc corrections and clarifications. -Update of READMEs. - -2001-04-04 (build improvements) redid Mac build structure (steffen) -Corrected IRIX-5* configure (english). Added support for AIX-5 (hobbs). -Added support for Win64 (hobbs). - ---- Released 8.3.3, April 6, 2001 - -2000-11-23 (new feature)[TIP 7] higher resolution timer on Windows (kenny) - -2001-01-18 (new feature) Tcl_InitHashTableEx renamed to Tcl_InitCustomHashTable -(kupries) - -2001-03-30 (new feature)[TIP 10] support for thread-aware/hot channels (kupries) - -2001-04-06 (new feature)[219280] auto-loading hidden in ::errorInfo (porter) - -2001-04-07 (bug fix)[406709] corrected panic when extra items left on the -byte compiler execution stack (sofer) - -2001-04-09 (bug fix)[219136,232558] improved use of thread-safe functions in -unix time commands (kenny) - -2001-04-24 (new feature)[TIP 27] started CONST-ification of the Tcl APIs (kenny) - -2001-05-03 (new feature) [auto_import] now matches patterns like -[namespace import], not like [string match] (porter) - **** POTENTIAL INCOMPATABILITY **** - -2001-05-07 (new feature)[416643] distinct srand() seed per interp (sofer) - -2001-05-15 (new feature) new Tcl_GetUnicodeFromObj API (hobbs) - -2001-05-16 (performance enhancement) byte-compiled versions of [lappend], -[append] simple cases (hobbs) - -2001-05-23 (new feature) added ISO-8859-15 and koi8-u encodings, updated other -encoding tables based on http://www.unicode.org/Public/MAPPINGS/ (kuhn) - -2001-05-27 (new feature) updated to Unicode 3.1.0 data set (still using 16 -bits for Tcl_UniChar though) (hobbs) - -2001-05-30 (new feature)[TIP 15] Tcl_GetMathFuncInfo, Tcl_ListMathFuncs, -Tcl_InfoObjCmd, InfoFunctionsCmd APIs (fellows) - -2001-06-08 (bug fix,feature enhancement)[219170,414936] all Tcl_Panic -definitions brought into agreement (porter) - -2001-06-12 (bug fix)[219232] regexp returned non-matching sub-pairs to have -index pair {-1 -1} (fellows) - -2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII -characters. (hobbs, riefenstahl) - -2001-06-28 (bug fix)[231259] failure to re-compile after cmd shadowing (sofer) - -2001-07-02 (bug fix)[227512] corrected [concat] treatment of UTF-8 strings -(hobbs, barras) - -2001-07-12 (new feature)[TIP 36] Tcl_SubstObj API (fellows) - -2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows -(hobbs, jsmith) - -2001-07-18 (bug fix)[427196] corrected memory overwrite error when buffer size -of a channel is changed after channel use has already begun (kupries, porter) - -2001-07-31 (new feature)[TIP 17] TclFS* APIs provide new virtual file -system. This includes the addition of 'file normalize', 'file system', -'file separator' and 'glob -tails' (darley) - -2001-08-06 (bug fix) removed use of tmpnam in TclpCreateTempFile on Unix (lim) - - * improved build support for IRIX, GNU HURD, Mac OS 9 and OS X - - * configure scripts revamped for better support of cygwin and gcc on - Windows (mdejong) - - * corrected several minor errors noted by Purify (hobbs) - ---- Released 8.4a3, August 6, 2001 - -2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII -characters. (hobbs, riefenstahl) - -2001-06-28 (bug fix)[231259] failure to re-compile after cmd shadowing (sofer) - -2001-07-02 (bug fix)[227512] corrected [concat] treatment of UTF-8 strings -(hobbs, barras) - -2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows -(hobbs, jsmith) - -2001-07-18 (bug fix)[427196] corrected memory overwrite error when buffer size -of a channel is changed after channel use has already begun (kupries, porter) - -2001-08-06 (bug fix)[442665] corrected object reference counting in [gets] -(jikamens) - -2001-08-06 (new feature) added GNU (HURD) configuration target. (brinkmann) - -2001-08-07 (bug fix)[406709] corrected panic when extra items left on the -byte compiler execution stack (see test foreach-5.5) (sofer, tallneil, jstrot) - -2001-08-08 (new features) updated packages msgcat 1.1.1, opt 0.4.3, -tcltest 1.0.1, dependencies checked (porter) - -2001-08-20 (new feature)[452217] http 2.3.2: include port number in Host: header -to comply with HTTP/1.1 spec (RFC 2068) (hobbs, tils) - -2001-08-23 (new feature) added QNX-6 build support (loverso) - -2001-08-23 (bug fix) corrected handling of spaces in path name passed to -[exec] on Windows (kenpoole) - -2001-08-24 (bug fix) corrected [package forget] stopping on non-existent -package (porter) - -2001-08-24 (bug fix) corrected construction of script library search path -relative to executable (porter) - -2001-08-24 (bug fix) [auto_import] now matches patterns like -[namespace import], not like [string match] (porter) - **** POTENTIAL INCOMPATABILITY **** - -2001-08-27 (new feature) added Tcl_SetMainLoop() to enable loading Tk as a -true package (hobbs) - -2001-08-30 (bug fix) build support for Crays (andreasen) - -2001-09-01 (bug fix) rewrite of Tcl_Async* APIs to better manage thread -cleanup (gravereaux) - -2001-09-06 (new feature) http 2.4: honor the Content-encoding and charset -parameters; add -binary switch for forcing the issue (hobbs, saoukhi, orwell) -=> http 2.4 - -2001-09-06 (performance enhancement) rewrite of file I/O flush management on -Windows. Approximately 100x speedup for some operations. (kupries, traum) - -2001-09-10 (bug fix) corrected finalization error in TclInExit (darley) - -2001-09-10 (bug fix) protect against alias loops (hobbs) - -2001-09-12 (bug fix) added missing #include in tclLoadShl.c (techentin) - -2001-09-12 (bug fix) script library path construction on Windows no longer -uses registry, nor adds the current working directory to the path (porter) - -2001-09-12 (bug fix) correct bugs in compatibility strtod() (porter) - -2001-09-13 (bug fix) Tcl_UtfPrev now returns the proper location when the -middle of a UTF-8 byte is passed in (hobbs) - -2001-09-19 (bug fix) [format] and [scan] corrected for 64-bit machines (rmax) - -2001-09-19 (new feature) --enable-64-bit support for HP-11. (hobbs) - -2001-09-19 (new feature) native memory allocator now default on Windows -(hobbs) - -2001-09-20 (new feature) WIN64 support and extra processor definitions -(hobbs, mstacy) - -2001-09-26 (bug fix) corrected potential deadlock in channels that do not -provide a BlockModeProc (kupries, kogorman) - -2001-10-03 (new feature) WIN64 build support (hobbs) - -2001-10-03 (bug fix) correction in thread finalization (rbrunner) - -2001-10-04 (new feature) updated encodings with latest mappings from -www.unicode.org (hobbs) - -2001-10-11 (bug fix) corrected cleanup of self-referential bytecodes at -interpreter deletion (sofer, rbrunner) - -2001-10-16 (new feature) config support for MacOSX / Darwin (steffen) - -2001-10-16 (new feature, Mac) change in binary extension format from MachO -bundles to standard .dylib dynamic libraries like on other unices. - *** POTENTIAL INCOMPATIBILITY *** - -2001-10-18 (bug fix) corrected off-by-one-day error in clock scan with -relative months and years during swing hours. (lavana) - ---- Released 8.3.4, October 19, 2001 - -2001-08-21 (bug fix)[219184] overagressive compilation of [catch] (sofer) - -2001-08-22 (new feature)[227482] [dde request -binary] (hobbs) -=> dde 1.2 - -2001-08-30 (performance enhancement)[456668] fully qualified command names use -cached Command for all namespaces, avoiding repeated lookups (sofer) - -2001-08-31 (performance enhancement) bytecompiled [list] (hobbs) - -2001-09-02 (bug fix)[403553] Add -Zl to VC++ compile line for tclStubLib to -avoid any specific C-runtime library dependence. (gravereaux) - -2001-09-05 (new feature) restored support for Borland compiler (gravereaux) - -2001-09-05 (new feature)[TIP 49] Tcl_OutputBuffered API (schroedter, fellows) - -2001-09-07 (new feature) restored VC++ 5.0 compatibility (gravereaux) - -2001-09-10 (performance enhancement)[TIP 53,451441] [proc foo args {}] now -compiles to 0 bytecodes (sofer) - -2001-09-13 (new feature)[TIP 56] Tcl_EvalTokensStandard API (sofer) - -2001-09-17 (new feature) compiling with TCL_COMPILE_DEBUG now required to -enable all compile and execution tracing (sofer) - *** POTENTIAL INCOMPATIBILITY *** - -2001-09-19 (bug fix)[411825] made TclNeedSpace UTF-8 aware (fellows) - -2001-09-19 (bug fix)[219166] overagressive compilation of "quoted" bodies of -[for], [foreach], [if], and [while] (sofer) - -2001-09-19 (performance enhancement) bytecompiled [string match] (hobbs) - -2001-10-15 (new feature)[TIP 35] serial channel configuration: Win (schroedter) - -2001-11-06 (bug fix)[478856] loss of fileevents due to short reads (kupries) - -2001-11-06 (new feature) revitalized makefile.vc (gravereaux) - -2001-11-07 (new feature) Cygwin gcc support dropped. Use mingw (dejong) - *** POTENTIAL INCOMPATIBILITY *** - -2001-11-07 (new feature) Support --include-dir= and --libdir= options to -configure. Store in tclConfig.sh as TCL_INCLUDE_SPEC and TCL_LIB_SPEC. -(dejong) - *** POTENTIAL INCOMPATIBILITY *** - -2001-11-08 (new feature) Enable --enable-threads on FreeBSD (dejong) - -2001-11-08 (new feature) New make target 'make gdb' (dejong) - -2001-11-09 (bug fix)[480176] [global] mishandled varnames matching :* (porter) - -2001-11-12 (new feature)[TIP 22,33,45] new command [lset], -[lindex] extended to accept multiple indices. (kenny, hobbs) - -2001-11-16 (new feature) new configure option --enable-langinfo=no. -By default, nl_langinfo() is used on Unix to determine system encoding. -Tcl's built-in system is used only if that fails, or configured with ---enable-langinfo=no. (hobbs, wagner) - -2001-11-19 (new feature)[TIP 62] A Tcl_VarTraceProc can now return Tcl_Obj * -or a dynamic string as well as a static string to indicate an error (fellows) - -2001-11-19 (new feature)[TIP 73] Tcl_GetTime API (kenny) - -2001-11-19 (bug fix)[478847] overflows in [time] of >2**31 microseconds (kenny) - -2001-11-29 (performance enhancement) caching scheme added to [binary scan] -(fellows) - -2001-12-05 (new feature) new algorithm for [array get] adds safety when read -traces modify the array. (sofer) - *** POTENTIAL INCOMPATIBILITY *** - -2001-12-10 (bug fix)[490514] doc fixes (porter,english) - -2001-12-18 (new feature) removed unix/dltest/configure; unix/configure does -all (dejong) - -2001-12-19 (new feature) New make target 'make shell' (dejong) - -2001-12-21 (new feature) MaxOSX / Darwin support (steffen) - -2001-12-28 (new feature) new command [memory onexit] replaces [checkmem] when -compiled with TCL_MEM_DEBUG. Added documentation. (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2001-12-28 (bug fix) proper case in [auto_execok] use of $env(COMPSPEC) (hobbs) - -2002-01-05 (feature rewrite) Tcl_Main() rewritten and documentation improved. -Interactive operation and event loop operation (via Tcl_SetMainLoop) now -interleave cleanly. Also more robust against strange happenings. (porter) - -2002-01-17 (bug fix)[504642] Tcl_Obj refCounts in [gets] (griffen,kupries) - -2002-01-21 (bug fix)[506297] infinite loop writing in iso2022-jap encoding -(forssen,kupries) - -2002-01-24 (HTTP server bug workaround)[504508] leave the default port out -of the Host: header value -=> http 2.4.1 (hobbs) - -2002-01-25 (new feature)[496733] socket options -eofchar and -translation -return read-only values (dejong) - -2002-01-28 (performance enhancement) bytecompiled [regexp] for trivial cases -that amount to string matching. Also -nocase and --. (hobbs) - -2002-02-05 (bug fix) [http::error] called when [::error] intended -=> http 2.4.2 (porter) - -2002-02-05 (bug fix)[465765] avoid zero-byte writes to STREAMs -(talcott,kupries) - -2002-02-06 (performance enhancement) [regsub] special cases that map to -[string map] detected. (hobbs) - -2002-02-06 (bug fix)[495213] [scan] accept 0x as prefix of base 16 value -(hobbs) - -2002-02-10 (new feature)[TIP 32,79] Tcl_CreateObjTrace API (kenny) - -2002-02-12 (new feature) partial support for DJGPP Tcl on DOS (gravereaux) - -2002-02-14 (mem leak) Fixed leaking an empty Tcl_Obj when [gets $chan] -errored out. (kupries, sofer) - -2002-02-15 (new feature)[TIP 72] support for 64-bit integer values on -32-bit platforms and ability to work with >2GiB files. Extends many -commands. See TIP for details. - *** POTENTIAL INCOMPATIBILITY *** - -2002-02-22 (bug fix)[476537] Fix panic when loading shared library without -proper use of stubs on platform without backlinking (porter) - -2002-02-22 (new feature) 64-bit support for xlc compiler on AIX-4 (hobbs) - -2002-02-22 (new feature)[521560] Removed limits on filename length and -format [source]able through the Safe Base (hobbs) - -2002-02-22 (performance enhancement) optimized bytecodes for [if], [for], -[while] and constant conditions (sofer) - -2002-02-22 (new feature)[TIP 76] [regsub] can now return result (fellows) - -2002-02-25 (bug fix)[495207] buffer overrun when closing ] left out of -argument to [subst] (sofer, english) - -2002-02-25 (bug fix)[514392] [load] updated for Mac OS X 10.1 (steffen) - -2002-02-26 (bug fix) [info hostname] choked on names >31 characters (hobbs) - -2002-02-26 (new feature)[TIP 35] serial channel configuration: Unix -(schroedter, hobbs) - -2002-02-25 (bug fix)[483575] [fconfigure ... -error] now no-op on Mac (kupries) - -2002-02-28 (performance enhancement)[458872] fully qualified command names use -cached Command for all namespaces, avoiding repeated lookups (sofer) - - * (new feature)[TIP 27] completed CONST-ification of TCL APIs. -Added compiler macro USE_NON_CONST to keep using those old API prototypes -that present irreconcilable source incompatibilities with header files -of prior Tcl releases. Others will need to be reconciled. - *** POTENTIAL INCOMPATIBILITY *** - -2002-03-04 (bug fix)[474358, 218099, 219314, 524674] fixed several problems -related to the handling of iso2022 text and finalization of escape-based -encodings. (taguchi, takahashi, hobbs) - ---- Released 8.4a4, March 5, 2002 - -2002-03-06 (new feature)[TIP 80] expanded [lsearch] options (wilkason, fellows) - -2002-03-07 (new feature)[TIP 87] [interp recursionlimit] (trier) - -2002-03-08 (platform feature) mingw 1.1 build favored (dejong) - -2002-03-20 (new feature)[TIP 27] CONST-ified variable access functions (porter) - -2002-03-24 (bug fix)[511666,511658,523217,530960] expanded -Tcl_FSMatchInDirectory to handle assorted [glob] bugs in VFS. (darley) - *** POTENTIAL INCOMPATIBILITY with prior 8.4a releases *** - -2002-03-25 (bug fix)[495726] stopped tcltest disabling of auto-loading (porter) - -2002-03-25 (bug fix)[495977] allow \n in test constraints (porter) - -2002-03-27 (platform support)[527941,533862] VC/winhelp/W9X (spjuth, -gravereaux) - -2002-03-28 (bug fix)[219181] exception at level 0 issues (sofer) - -2002-03-28 (bug fix)[219362] command termination; Tcl_CreateTrace (knoll,sofer) - -2002-04-05 (bug fix)[536879] exceptions during variable subst (porter) - -2002-04-15 (bug fix)[497446,513983] tcltest syntax errors now raised (porter) - ***POTENTIAL INCOMPATIBILITY with prior tcltest 2.0.* (8.4aX)*** - -2002-04-17 (bug fix)[495660] [(save|restore)state] deprecated (porter) - -2002-04-17 (bug fix)[526524] escape-based encodings corrected (yamamoto, hobbs) - -2002-04-18 (bug fix)[542588] [expr] error msgs improved (ehrens, sofer) - -2002-04-18 (bug fix)[545325] [info level $level] now returns [namespace eval] -as documented (suchenwirth,sofer) - -2002-04-19 (bug fix)[544727] export [mcload]; ns context of [mcmax] (porter) -=> msgcat 1.2.3 - -2002-04-22 (performance enhancement) threaded memory allocator (AOL, hobbs) - -2002-04-24 (new feature) TCLTK_NO_LIBRARY_TEXT_RESOURCES #define disables -inclusion of tcl library code in resource fork on Mac. (steffen) - -2002-05-21 (platform support) static libs on OSF (dejong) - -2002-05-24 (bug fix)[557878] set encoding on listening socket (staplin, -kupries) - -2002-05-24 (new feature)[TIP 91] Tcl_Seek compatibility (fellows) - -2002-05-28 (bug fix)[545579] VFS [load] left temp file (darley) - -2002-05-28 (bug fix)[559376] plug timezone env leak on Windows (hobbs) - -2002-05-29 (performance enhancement) [string compare] optimized (hobbs,fellows) - -2002-05-31 (bug fix)[550534] plug interp leak in [pkg_mkIndex] (helmut) - -2002-05-31 (dead code)[474335,555635] removed all use of matherr() (english) - *** POTENTIAL INCOMPATIBILITY *** - -2002-06-04 (new feature)[TIP 85,521362] custom result match in tcltest -(markus, porter) -=> tcltest 2.1 - -2002-06-06 (bug fix)[524352] encoding, threading, and environment issues on -MacOSX (steffen) - -2002-06-06 (bug fix)[512214,558742,512214,461000] lazy initialization of -tcltest constraints (porter) - -2002-06-07 (bug fix)[563122,564595] EOVERFLOW definitions (fellows) - -2002-06-11 (bug fix)[567386] [info locals] corrections (sofer) - -2002-06-14 (new feature)[TIP 102] [trace list] renamed [trace info] (fellows) - -2002-06-17 (new feature)[525522,525525] msgcat support for XPG4 locales; -examination of LC_ALL, LC_MESSAGES environment variables (haible, porter) -=> msgcat 1.3 - -2002-06-17 (new feature)[565088] header files assume modern C compiler by -default; older compilers may need configuration (english) - *** POTENTIAL INCOMPATIBILITY *** - -2002-06-17 (bug fix)[554068] [exec] argument quoting on Windows (darley) - -2002-06-17 (new feature)[TIP 62,462580] command execution traces (lavana) - -2002-06-19 (bug fix)[558324] regexp sets a linked variable (watson) - - * (performance enhancment) optimizations of bytecode execution (sofer) - -2002-06-21 (new feature)[TIP 99,562970] new [file link] command (darley) - -2002-06-24 (new feature)[TIP 101] new [tcltest::configure] command (porter) -=> tcltest 2.2 - -2002-06-25 (new feature) --enable-man-symlinks and --enable-man-compression -options to configure (max) - -2002-06-26 (bug fix)[565880] [clock format] now respects locale (max) - *** POTENTIAL INCOMPATIBILITY *** - -2002-07-03 (bug fix)[577015] [catch] catches even compile errors (sofer) - ---- Released 8.4b1, July 5, 2002 - -2002-07-08 (bug fix) restored compatibility of [viewFile] in tcltest (porter) - -2002-07-11 (bug fix) [file normalize] returns long form on Win 95/98/ME (darley) - -2002-07-15 (performance enhancment) variable operations rewritten to store - and use cached Var pointers (sofer) - -2002-07-22 (bug fix)[218000] Inf and Nan are floating-point values (fellows) - -2002-07-23 (platform support)[219220] 64-bit compile on IRIX (dejong) - -2002-07-25 (bug fix)[219218] return codes in background errors (english) - -2002-07-28 (bug fix)[582522] alias fires exec traces (sofer) - -2002-07-29 (bug fix)[578363] regexp (fellows,pvgoran) - -2002-07-30 (bug fix)[584603] WriteChars infinite loop non-UTF-8 string (kupries) - -2002-08-04 (new feature)[584051,580433,585105,582429][TIP 27] Tcl interfaces - are now fully CONST-ified. Use the symbols USE_NON_CONST or - USE_COMPAT_CONST to select interfaces with fewer changes. - *** POTENTIAL INCOMPATIBILITY *** - -2002-08-05 (bug fix)[589859] tcltest setup and cleanup scripts skipped when - test body is skipped (porter) - => tcltest 2.2 - -2002-08-07 (bug fix)[587488] mem leak with USE_THREAD_ALLOC (sofer,sass) - -2002-08-07 (feature enhancement)[584794,584650,472576] boolean values - are no longer always re-parsed from string. (sofer) - -Many internal bugs fixed. -Considerable cleanup of the test suite. - ---- Released 8.4b2, August 9, 2002 - -2002-08-20 (new feature) --enable-memdebug configure option (kupries) - -2002-08-23 (bug fix)[597936] mem leak with USE_THREAD_ALLOC (sofer,zoran) - -2002-08-26 (bug fix)[599788] segfault in compiler (sofer,wilkason) - -2002-08-28 (bug fix)[414910] avoid mem leaks accessing environment variables - on Windows (welton,gravereaux) - -2002-08-31 (platform support)[TIP 108] Mac OS X port (steffen,ingham) - -2002-09-02 (platfrom support) 64-bit compile on HP-11 (martin) - ---- Released 8.4.0, September 10, 2002 - -2002-09-18 (platform support) Updated support for compiling with Cygwin and -either mingw or gcc. (khan, howell, dejong) - -2002-09-22 (bug fix)[612786, 611922] Corrected [puts -nonewline] within -test bodies. Also corrected reporting of body return code. Updated tcltest -to v2.2.1. - -2002-09-24 (bug fix)[613117] More robust 64-bit wide integer value -detection (fellows) - -2002-09-26 (bug fix) correct overeager optimization of noop proc to handle -the precompiled case. (sofer, hobbs) - -2002-09-26 (bug fix)[615115] removed extraneous spaces in koi8-u.enc that -confused encoding reader. - -2002-09-29 (bug fix)[219355] Added proper exiting conditions using Win32 -console signals. This handles the existing lack of a Ctrl+C exit to call -exit handlers when built for thread support. Also, properly handles exits -from other conditions such as CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and -CTRL_SHUTDOWN_EVENT signals. In all cases, exit handlers will be called. -(gravereaux) - -2002-09-30 (bug fix) improve the checking for bad regular expressions -during regexp compilation. Resultant compiles were correct, but much -slower than necessary. (hobbs) - -2002-10-01 (bug fix) fix precompiled locals to support 8.3 precompiled -code. (hobbs) - -2002-10-09 (bug fix)[620735] Added code to set an exit handler on Windows -that terminates the thread that calibrates the performance counter, so that -the thread won't outlive unloading the Tcl DLL. (kenny) - -2002-10-09 (build support) all --enable-symbols to take the enhanced -options yes|no|mem|compile|all. (hobbs) - -2002-10-10 (build support) enable USE_THREAD_ALLOC (new threaded allocator) -by default on Windows. (hobbs, gravereaux) - -2002-10-14 (bug fix)[623269] correct possible mem leak in -Tcl_PutEnv. (brouwers) - -2002-10-15 (bug fix)[615043] fix in execution traces with idle tasks -firing. (lavana) - -2002-10-15 (platform support) Correct AIX-5 ppc and 4/5 64-bit build flags. -Correct HP 11 64-bit gcc building. (martin, hobbs) - -2002-10-17 (bug fix)[624755] Fixed code that check for proper # of args to -[array names] (porter) - -2002-10-18 (feature enhancement)[625453] Added support for broadcasting -changes to the registry Environment on Windows. Updated registry package -to v1.1. (hobbs) - -2002-10-22 (platform support)[624509] On macosx, add embedded framework -dirs to tcl_pkgPath: @executable_path/../Frameworks and -@executable_path/../PrivateFrameworks (if they exist), as well as the dirs -in DYLD_FRAMEWORK_PATH (if set). (steffen) - ---- Released 8.4.1, October 22, 2002 - -2002-10-28 (bug fix)[627660] [package unknown] chaining for platform specifics - -2002-10-29 (bug fix)[627546] verbose [load] (dyld) error mesages on MacOSX - -2002-11-01 (bug fix) [package provide registry] consistent versions. - -2002-11-06 (bug fix)[582039] missing ar program -> configuration error - -2002-11-06 (feature enhancement) added new TclInThreadExit function to -test for thread exit vs whole process exit condition. The TclInExit -function now correctly returns 1 during Tcl_Finalize processing. - *** POTENTIAL INCOMPATIBILITY *** - -2002-11-13 (bug fix)[615043] some execution traces were not firing - -2002-11-18 (bug fix)[634856] multiple signs no longer accepted as valid integer -[string is integer ++1] => 0 - *** POTENTIAL INCOMPATIBILITY *** - -2002-11-26 (bug fix)[593810,597924] clean exit of channel worker threads on Win - -2002-11-28 (new feature) `make valgrind` target - -2002-12-03 (bug fix)[615304] repeated load/unload of Tcl now possible - -2002-12-11 (bug fix)[647307] negative return codes now propagated by procs - -2002-12-11 (bug fix)[648441] syntax error in [expr 0x] now detected. - -2003-01-07 (bug fix)[633204] [catch {return}] => 2 (not 0) - -2003-01-09 (bug fix)[634151] [file (a|m)time $nonASCIIpath $time] now works - -2003-01-16 (bug fix) dde eval with {} service name does not crash. -=> dde 1.2.1 - -2003-01-16 (bug fix)[635200,655645,615043,571385] many command trace fixes - -2003-01-31 (bug fix)[675614,678415,676978] tcltest conflicts in cleanup -and -outfile; also failure in space-containing path; also missing [close] -=> tcltest 2.2.2 - -2003-02-01 (bug fix)[670042] corrected [info loaded {}] for static -packages in multiple interps. - -2003-02-01 (bug fix)[675356] [clock clicks {}]; [clock clicks -] - syntax errs - -2003-02-01 (bug fix)[656660] MT-safety for [clock format] - -2003-02-03 (bug fix)[651271] command rename traces get fully-qualified names - *** POTENTIAL INCOMPATIBILITY *** - -2003-02-07 (performance improvement) [glob] on Windows is 2.5 times faster - -2003-02-07 (feature change) lack of Cygwin support indicated by config error - -2003-02-11 (bug fix)[684744] [info complete] stopped by \x00 - -2003-02-11 (bug fix)[685445] [glob -types l] missed broken symlinks on Unix - -2003-02-11 (bug fix) [lsearch -regexp $a $a] doesn't crash - -2003-02-13 (bug fix)[685926] accept non-ASCII7 for tcl_platform(user) on Win - -2003-02-15 (bug fix)[673714] stop crash when Tcl_DeleteEvents deletes last - -2003-02-15 (bug fix)[681841] parser missed some missing ] syntax errors - -2003-02-17 (bug fix)[684756] memory leak during command rename plugged - -2003-02-18 (bug fix)[689100] reduced per-thread memory overhead - -2003-02-18 (platform support)[651811] use xnet library on HP 11 (64 bit). - -2003-02-20 (bug fix)[Patch 689341] correct jis round-trip encoding - -2003-02-20 (bug fix)[689835] stop MacOSX hang trying to read a write-only pipe - -2003-02-07 (performance improvement) [tclPkgUnknown]: fewer vfs calls - -2003-02-18 (platform support) cut and splice procs for file channels on Mac - -2003-02-21 (bug fix)[690774] [binary scan] failed on some wide ints - -2003-02-22 (bug fix)[571002] plugged data leak during thread exit - -2003-02-25 (feature change) [pkg_mkIndex -load]: case-insensitive match - *** POTENTIAL INCOMPATIBILITY *** - -2003-02-27 (bug fix)[694232] stop [lsearch -start 0 {} x] segfault - ---- Released 8.4.2, March 3, 2003 - -2003-03-06 (bug fix)[699042] Correct case-insensitive unicode string -comparison in Tcl_UniCharNcasecmp - -2003-03-11 (bug fix) Corrected loading of tclpip8x.dll on Win9x - -2003-03-12 (bug fix)[702383] Corrected parsing of interp create -- - -2003-03-12 (bug fix)[685106] Correct Tcl_SubstObj handling of \x00 bytes - -2003-03-14 (bug fix)[702622 699060] Correct wide int issues in 'format' - -2003-03-14 (bug fix)[698146] Remove assumption that file times and longs -are the same size. - -2003-03-18 (bug fix)[697862] Allow Tcl to differentiate between reparse -points which are symlinks and mounted drives on Windows - -2003-03-19 (bug fix)[705406] Bad command count on TCL_OUT_LINE_COMPILE - -2003-03-20 (bug fix)[707174] Store pointers to notifier funcs in a struct -to work around some platform linker issues - -2003-03-22 (bug fix)[708218] Load correct (non-)debug dll for dde or -registry - -2003-03-24 (bug fix)[631741 696893] Fixing ObjMakeUpvar's lookup algorithm -for the created local variable - -2003-04-07 (bug fix)[713562] Make sure that tclWideIntType is defined and -somewhat sensible everywhere - -2003-04-07 (bug fix)[711371] Corrected string limits of arguments -interpolated in error messages for 'if' - -2003-04-11 (bug fix)[718878] Corrected inconsistent results of -[string is integer] observed on systems where sizeof(long) != sizeof(int) - -2003-04-12 (bug fix) Substantial changes to the Windows clock synch -phase-locked loop in a quest for improved loop stability - -2003-04-16 [713562] Made changes so that the "wideInt" Tcl_ObjType is -defined on all platforms, even those where TCL_WIDE_INT_IS_LONG is defined. -Also made the Tcl_Value struct have a wideValue field on all platforms. -Potential incompatibility for TCL_WIDE_INT_IS_LONG platforms because that -struct changes size. - *** POTENTIAL INCOMPATIBILITY *** - -2003-04-25 (bug fix)[727271] Catch any errors returned by the Windows -functions handling TLS ASAP instead of waiting to get some mysterious crash -later on due to bogus pointers. - -2003-04-29 (bug fix) Correct 'glob -path {[tcl]} *', where leading -special character instead lists files in '/'. Bug only occurs on Windows -where '\' is also a directory separator. - -2003-05-09 (bug fix)[731754] Fixed memory leak in threaded allocator on -Windows caused by treating cachePtr as a TLS index - -2003-05-10 (bug fix)[710642] Ensure cd is thread-safe - -2003-05-10 (bug fix)[718002] Correct mem leak on closing a Windows serial -port - -2003-05-10 (bug fix)[714106] Prevent string repeat crash when overflow -sizes were given (throws error). - -2003-05-13 (feature enhancement)[736774] Use new versioned bundle resource -API to get tcl runtime library for TCL_VERSION on Mac OS X. - -2003-05-13 (bug fix)[711232] Worked around the issue of realpath() not -being thread-safe on Mac OS X by defining NO_REALPATH for threaded builds -on Mac OS X. - -2003-05-14 (bug fix)[557030] Correct handling of the gb2312 encoding by -making it an alias of the euc-cn encoding and creating a gb2312-raw -encoding for the original. Most uses of gb2312 really mean euc-cn. - -2003-05-14 (bug fix)[736421] Corrected another putenv() copy behavior -problem when compiling on Windows and using Microsoft's runtime. - ---- Released 8.4.3, May 20, 2003 - -2003-05-23 (bug fix)[726018] reverted internals change to the -'cmdName' Tcl_ObjType that broke several extensions (TclBlend, e4graph...) -in the 8.4.3 release. - -2003-06-10 (bug fix)[495830] stop eval of bytecode in deleted interp. - -2003-06-17 (bug fix) corrections to regexp when matching emtpy string. - -2003-06-25 (bug fix)[748957] -*ieee compiler flags for Tru64 builds. - -2003-07-11 (bug fix) [pkg_mkIndex] indexes provided packages, not indexed ones. - -2003-07-15 (feature enhancement) MacOSX build system rewrite. - -2003-07-15 (bug fix)[771613] corrected segfault in [if] (buffer overflow) - -2003-07-16 (bug fix)[756791] corrected assumption that Tcl_Free == free - -2003-07-16 (feature enhancement) -DTCL_UTF_MAX=6 compile option forces -internal UCS-4 representation of Unicode (default is recommended UCS-2). - -2003-07-16 (bug fix)[767578] 64-bit corrections in thread notifier. - -2003-07-16 (bug fix)[759607] Safe Base tests normalized paths. - -2003-07-16 (feature enhancement)[Patch 679315] improved Cygwin path support - -2003-07-18 (bug fix)[706359] corrected broken -output option of [tcltest::test] -=> tcltest 2.4.4 - -2003-07-18 (bug fix)[753315] MT-safety of VFS records. - -2003-07-18 (bug fix)[759888] support for user:pass in URL by [http::geturl] -=> http 2.4.4 - -Improved documentation, new tests, and some code cleanup. -[655300, 720634, 735364, 748700, 756112, 756744, 756951, 758488, 760768, -763312, 769895, 771539, 771840, 771947, 771949, 772333] - ---- Released 8.4.4, July 22, 2003 - -2003-07-23 (bug fix)[775976] fix registry compilation for VC7. - -2003-08-05 (enhancement)[781585] Use Tcl_ResetResult in bytecodes to -prevent potential costly Tcl_Obj duplication. - -2003-08-06 (bug fix)[781609] prevent non-Windows platforms from trying to -use the registry package inside msgcat. - -2003-08-27 (bug fix)[411825] Fix TclNeedSpace to handle non-breaking space -(\u00A0) and backslash escapes correctly. - -2003-09-01 (bug fix)[788780] Fix thread-safety issues in filesystem records. - -2003-09-19 (bug fix)[804681] Protect ::errorInfo and ::errorCode traces -from corrupting stack. - -2003-09-23 (bug fix)[218871] Fix handling of glob-sensitive chars in -auto_load and auto_import. - -2003-10-03 (bug fix)[811483] Fixed refcount management for command and -execution traces. - -2003-10-04 (bug fix)[789040] Fixed exec command.com error for Win9x. - -2003-10-06 (bug fix)[767834, 813273] Fixed volumerelative file -normalization and 'file join' inconsistencies. - -2003-10-08 (bug fix)[769812] Fix Tcl_NumUtfChars string length calculation -when negative parameter is given. - -2003-10-22 (bug fix)[800106] Handle VFS mountpoints inside glob'd dirs. - -2003-10-22 (bug fix)[599468] Watch for FD_CLOSE too on Windows when -asked for writable events by the generic layer. - -2003-10-23 (bug fix)[813606] Detect OS X pipes correctly. - -2003-11-05 (bug fix)[832657] Allow .. in libpath initialization. - -2003-11-11 (bug fix) Improve AIX-64 build configuration. - -2003-11-17 (bug fix)[230589, 504785, 505048, 703709, 840258] fixes to -various odd regexp "can't happen" bugs. - ---- Released 8.4.5, November 20, 2003 - -2003-12-02 (bug fix)[851747] object sharing fix in [binary scan] - -2003-12-09 (platform support)[852369] update errno usage for recent glibc - -2003-12-12 (bug fix)[858937] fix for [file normalize ~nobody] - -2003-12-17 (bug fix)[839519] fixed two memory leaks (vasiljevic) - -2004-01-09 (bug fix)[873311] fixed infinite loop in TclFinalizeFilesystem - -2004-02-02 (bug fix)[405995] Tcl_Ungets buffer filling fix - -2004-02-04 (bug fix)[833910] tcltest command line option parsing error -=> tcltest 2.4.5 - -2004-02-04 (bug fix)[833637] code error in tcltest -preservecore operation - -2004-02-12 (feature enhancement) update HP-11 build libs setup - -2004-02-17 (bug fix)[849514,859251] corrected [file normailze] of $link/.. - -2004-02-17 (bug fix)[772288] Unix std channels forced to exist at startup. - -2004-02-17 (new default) tcltest::configure -verbose {body error} - -2004-02-19 (bug fix) init.tcl search path with unusual --libdir (samson) - -2004-02-25 (bug fix)[554068] stopped broken [exec] quoting of { (gravereaux) - -2004-02-25 (bug fix)[888777] plugged memory leak with long host names (cassoff) - -2004-03-01 (bug fix)[462580] corrected level interpretation of Tcl_CreateTrace - -2004-03-01 (platform support)[218561] Allow 64-bit configure on IRIX64-6.5* - ---- Released 8.4.6, March 1, 2004 - -Changes to 8.5a1 include all changes to the 8.4 line through 8.4.6, -plus the following, which focuses on the high-level feature changes -in this changeset (new minor version) rather than bug fixes: - - * refactored IO code to split FS path code into generic/tclPathObj.c - and generic/tclFileSystem.h - - * refactored trace code into generic/tclTrace.c - - * configure scripts now require autoconf 2.57 for regeneration - - * updated runtime library scripts to use newer Tcl code features - (like replacing regsub with string map) - - * improve robustness of tcltest test suite across environments - - * changed the bytecode evaluation-stack addressing mode, from array-style - to pointer-style; the catch stack and evaluation stack are now - contiguous in memory - - * switch command is now byte-compiled - - * enhanced checking in 'file' command for Windows NT file permissions - - * [TIP #57] new 'lassign' command (adopted from TclX) - - * [TIP #75] switch -regexp now provides submatch info - - * [TIP #90] extended 'catch' and 'return' to enable creation of procs - that are a true replacement for 'return' - - * [TIP #100] new 'unload' command (can unload DLLs loaded via 'load', - requires the extension writer to support it) - - * [TIP #111] new 'dict' command. Several commands have been updated - to handle the list form of dicts implicitly at the C level where - only lists were previously accepted - - * [TIP #112] 'namespace ensemble' command addition allows for ensembles - that build on the namespace abstraction - - * [TIP #118] file attributes -readonly option for unices that support - chflags(), support Mac Classic attribute options on OS X, add - -rsrclength for OS X, enhance file copy on OS X to copy finder - attributes and resource forks transparently - - * [TIP #120] enable dde in safe interpreters - * [TIP #130] enable unique dde server names on Windows - * [TIP #135] change dde servername -exact option to -force -=> dde 1.3 - - * [TIP #121] new Tcl_SetExitProc C API to control application shutdown - - * [TIP #123] expr ** exponentiation operator - - * [TIP #124] 'clock clicks -milliseconds' now returns a wide integer and a - new 'clock clicks -microseconds' returns a wide integer, representing - the number of microseconds, both since the Posix epoch - - * [TIP #127] added 'lsearch -index' option - - * [TIP #136] added 'lrepeat' command - - * [TIP #137/151] Add -encoding option to 'source' command and main tclsh - executable. - *** POTENTIAL INCOMPATIBILITY *** - For Tcl embedders that build on Tcl_Main() and make use of Tcl_Main's - former ability to pass a leading "-encoding" option to interactive shell - operations, this will now be consumed by Tcl. - - * [TIP #138] New TCL_HASH_KEY_SYSTEM_HASH option for Tcl hash tables - - * [TIP #139] documented portions of Tcl's namespace C APIs - - * [TIP #148] correct [list]-quoting of the '#' character - *** POTENTIAL INCOMPATIBILITY *** - For scripts that assume a particular (buggy) string rep for lists. - - * [TIP #156] add "root locale" to msgcat -=> msgcat 1.4 - - * [TIP #157] leading {expand} syntax on words to cause argument expansion. - This is a safer/cleaner alternative to the use of 'eval'. - ---- Released 8.5a1, March 3, 2004 - -2004-03-04 (new feature) registry package is [unload]able (thoyts) -=> registry 1.1.4 - -2004-03-08 (bug fix)[910525] [glob -path] in root directory (darley) - -2004-03-12 (new feature)[TIP 163] [dict merge] (english, fellows) - -2004-03-18 (platform support) support for Mac Classic removed (steffen) - -2004-03-28 (bug fix)[925121] corrected segfault in bc compiler (sofer) - -2004-03-30 (bug fix)[495830,729692] bytecode execution checks -each command/interp validity before executing. (sofer) - -2004-03-31 (bug fix)[811457] support translation to "" (porter) -2004-03-31 (bug fix)[811461] ignore locales with no "language" part (porter) -=> msgcat 1.4.1 - -2004-04-01 (bug fix) make [glob -type d -dir . *] work across VFS boundary - -2004-04-06 (clean up) refactored Tcl header file #include order. Might -create need for changes in extensions that #include private headers. -Changed source code files should work with older Tcl as well. - *** POTENTIAL INCOMPATIBILITY *** - -2004-04-07 (bug fix)[920667] install into any Unicode path on Win (hobbs) - -2004-04-07 (platform support) properly substitute more values in Windows -tclConfig.sh (hobbs) - -2004-04-23 (bug fix)[930851] reset channel EOF when eofchar changes (kupries) - -2004-04-28 (bug fix)[600812][TIP 184] [upvar 0 scalar array(foo)] raises error - -2004-05-03 (bug fix)[947070] stack overflow prevention on Win (kenny) - -2004-05-03 (bug fix)[868853] fix leak in [fconfigure $serial -xchar] (cassoff) - -2004-05 (bug fix)[928353,929892,928808,947440,948177] test fixes: OSX (abner) - -2004-05-05 (bug fix)[794839] socket connect error -> r/w fileevents -(gravereaux) - -2004-05-07 (bug fix)[949905] corrected utf-8 encoding of \u0000 on I/O (max) - -2004-05-13 (new feature)[TIP 129] [binary scan tnmrRqQ] (markus, fellows) - -2004-05-13 (new feature)[TIP 142] [interp limit] (fellows) - -2004-05-14 (bug fix)[940278,922848] [clock] notices $::env(TZ) changes, -gmt works on all platforms. (kenny, welton, glessner) - -2004-05-16 (feature rewrite) bytecode execution of {expand} changed - *** POTENTIAL INCOMPATIBILITY with prior 8.5a releases *** - -2004-05-18 (platform support) makefile.vc now generates tclConfig.sh (thoyts) - -2004-05-18 (bug fix)[500285,500389,852944] [clock %G %V] ISO8601 week numbers -(kenny) - -2004-05-22 (bug fix)[735335,736729] variable name resolution error (sofer) - -2004-05-24 (bug fix) support for non-WIDE_INT aware math functions (hobbs) - -2004-05-25 (new feature) [http::config -urlencoding] (hobbs) -=> http 2.5.0 - -2004-05-26 (bug fix)[960926] file count doubled when -singleproc 1 (porter) -=> tcltest 2.2.6 - -2004-05-26 (bug fix)[874058] improved build configuration on 64-bit systems. -Corrects Tcl_StatBuf definition issues. (hobbs) - -2004-05-30 (platform support) Win: allow signed short exit codes (gravereaux) - -2004-06-05 (bug fix)[976722] hi-res clock fixes: Win -(godfrey, suchenwirth, kenny) -2004-06-10 (bug fix)[932314] bad return values from Tcl_FSChdir() (vasiljevic) - -2004-06-18 (platform support) regonize more unix locales (huang) - -2004-06-18 (bug fix) prevent stack overflow from long free() chains (fellows) - -2004-06-21 (platform support) exceptions w/ gcc -O3 on Win (dejong) - -2004-06-23 (feature rewrite)[976496] thread local storage done with hash -tables to avoid system limits (mistachkin) - -2004-06-29 (bug fix)[981733] SafeBase global pollution (fellows) - -2004-06-30 (new feature)[TIP 188] [string is wideinteger] (kenny) - -2004-07-02 (new feature)[TIP 202] pipe redirection 2>@1 (hobbs) - -2004-07-03 (bug fix)[908375] round() wide integer support (lavana, sofer) - -2004-07-07 (bug fix)[458361] shimmer of single-word scripts suppressed (sofer) - -2004-07-15 (bug fix)[770053] crash in thread finalize of notifier (vasiljevic) - -2004-07-15 (bug fix)[990453] plug mutex leaks on reinit -(mistachkin, vasiljevic) - -2004-07-16 (bug fix)[990500] clean exit of notifier thread -(mistachkin, kupries) - -2004-07-19 (bug fix)[987967] improved self-init of mutexes on Win (vasiljevic) - -2004-07-20 (bug fix) pure Darwin/CFLite support (steffen) - -2004-07-20 (bug fix)[736426] plug leaky allocator reinit (mistachkin, kenny) - -2004-07-30 (bug fix)[999084] no deadlock in re-entrant Tcl_Finalize (porter) - -2004-08-02 (new feature)[TIP 207] [interp invokehidden -namespace] (porter) - -2004-08-10 (bug fix) thread IDs on 64-bit systems (ratcliff,vasiljevic) - -2004-08-13 (bug fix) avoid malicious code acceptance by [mclocale] (porter) -=> msgcat 1.3.3 - -2004-08-16 (bug fix)[1008314] Tcl_SetVar TCL_LIST_ELEMENT (sofer,porter) - -2004-08-18 (new feature)[TIP 173,209] complete [clock] rewrite (kenny) - *** POTENTIAL INCOMPATIBILITY *** - -2004-08-18 (new feature)[TIP 189] package loading for Tcl Modules (kupries) - -2004-08-19 (bug fix)[1011860] [scan %ld] fix on LP64 (fellows,porter) - -2004-08-23 (bug fix)[695441] extend [tcl_findLibrary] search path to include - $::auto_path and [pkgconfig get scriptdir,runtime] (porter) - -2004-08-27 (platform support) TCL_MODULE_PATH values for Mac OSX (steffen) - -2004-08-27 (bug fix)[1017022] recognize imported ensembles (fellows) - -2004-08-30 (bug fix) [string map $x $x] crash (fellows) - -2004-09-01 (bug fix)[1020445] WIN64 support (hobbs) - -2004-09-03 (bug fix)[1020538] crash in [file copy] (violi,fellows) - -2004-09-07 (bug fix)[1016167] [after] overwrites its imports (kenny) - -2004-09-08 (bug fix) fixed [clock format 0 -format %k] (kenny) - -2004-09-09 (bug fix)[560297] fixed broken [namespace forget] logic (porter) - -2004-09-09 (bug fix)[1017299] fixed [namespace import] cycle prevention -(porter) - -2004-09-10 (performance) $x[set x {}] is now fast [K $x [set x {}]] (sofer) - -2004-09-10 (bug fix)[868489] better control over int <-> wideInt -(fellows,kenny) - -2004-09-10 (bug fix)[1025359] POSIX errorCode from wide seeks (kupries,fellows) - -2004-09-10 (bug fix)[707104,1026493] fix [rename] of [interp alias] (porter) - -2004-09-18 (bug fix)[868467] fix [expr 5>>32] => 0, not 5 (hintermayer,fellows) - -2004-09-21 (bug fix) consistent errorinfo from [namespace eval x error foo bar] - and [namespace eval c {error foo bar}] (porter) - -2004-09-22 (feature change) syntax errors not reported at compile time; - deferred to runtime. Support [return -errorline]. (porter) - -2004-09-23 (bug fix)[1016726] fix `make clean` in static config -(leitgeb,dejong) - -2004-09-22 (feature change) report all compile errors at runtime (porter) - -2004-09-29 (bug fix)[1036649] syntax error in [subst] => buffer overflow -(sofer) - -2004-09-30 (bug fix)[1038021] save/restore error state: var traces (porter) - -2004-10-01 (performance) stackframe level values in internal reps (fellows) - -2004-10-01 (feature change)[1037235] auto-create [dict] key paths (fellows) - -2004-10-04 (bug fix)[884830] eq and ne parse in expr (fellows) - -2004-10-05 (reform) errorInfo, errorCode management (porter) - *** POTENTIAL INCOMPATIBILITY for traces on those vars *** - -2004-10-06 (feature change)[1041072] re-bless and enhance Tcl_AppendResult -(dkf) - -2004-10-06 (reform) more robust interp result appends (porter) -=> dde 1.3.1 -=> registry 1.1.5 - -2004-10-06 (reform) re-write of [glob] guts (fellows) - -2004-10-07 (reform)[925620] improved platform split of VFS code (darley) - -2004-10-08 (new feature)[TIP 201] "in" and "ni" expr operators (fellows) - -2004-10-08 (new feature)[TIP 212] [dict update]; [dict with] (fellows) - -2004-10-08 (bug fix)[954263] case insensitive [file exec] for Win -(hobbs,darley) - -2004-10-14 (performance) [info commands/globals/procs/vars $pattern] faster - when $pattern is trivial (fellows) - -2004-10-14 (new feature)[TIP 217] [lsort -indices] (salsman,fellows) - -2004-10-24 (reform) replaced bit flag values with macros for Var handling - *** POTENTIAL INCOMPATIBILITY for accesses to Var internals *** - -2004-10-26 (new feature)[1054370] install msgcat, http, tcltest as TM's -(porter) - -2004-10-26 (bug fix)[767676] negative PIDs with pipes (giese,gravereaux) - -2004-10-27 (bug fix)[731778] stop critical section leaks -(mistachkin,gravereaux) - -2004-10-27 (bug fix)[926088] -load option to find tested packages (gravereaux) - -2004-10-28 (bug fix)[1030548] restore the --enable-symbols --enable-threads -build on Win (mistachkin,kenny,kupries) - -2004-10-29 (bug fix)[1055673] fix command line syntax error message (porter) -=> tcltest 2.2.7 - -2004-10-30 (bug fix)[926106] fix [file mtime] DST anomaly (kenny) - -2004-10-31 (bug fix)[1057461] fix [info globals ::varName] (fellows) - -2004-11-02 (bug fix)[761471] fix [expr {NaN == NaN}] (sofer) - -2004-11-02 (bug fix)[1017151] misleading errorInfo after tests (seeger,porter) - -2004-11-03 (bug fix)[527164] preserve errorinfo from var traces (porter) - -2004-11-08 (bug fix){947693] Made -blocking option of channel during [close] -consistent on Windows with Unix (gravereaux) - *** POTENTIAL INCOMPATIBILITY *** - -2004-11-11 (bug fix)[1034337] recursive file delete, MacOSX (steffen) - -2004-11-12 (new feature)[TIP 221] [interp bgerror] (porter) - -2004-11-12 (new feature)[TIP 226] Tcl_(Save|Restore|Discard)InterpState -(porter) - -2004-11-12 (new feature)[TIP 227] Tcl_(Get|Set)ReturnOptions (porter) - -2004-11-12 (bug fix)[1004065] stop crash when TCL_UTF_MAX==6 (hobbs,porter) - -2004-11-15 (bug fix)[10653678] [trace variable],[trace remove] interop (porter) - -2004-11-16 (bug fix)[1067709] crash in [fconfigure -ttycontrol] (hobbs) - -2004-11-18 (new feature) configure options --enable-man-suffix (max) - -2004-11-22 (bug fix)[1030465] Improve HAVE_TYPE_OFF64_T check (dejong) - -2004-11-22 (bug fix)[1043129] Fixed the treatment of backslashes in file -join on Windows (darley) - -2004-11-22 (bug fix)[976438] Move init.tcl search path construction to -tclInit (porter) - -2004-11-24 (bug fix)[1072654] Fixed segfault in info vars trivial -matching branch (new in 8.4.8) (porter) - -2004-11-24 (bug fix)[1001325, 1071701] Fixed readdir_r detection and usage -(dejong, kenny, porter) - -2004-11-24 (bug fix)[1071807] Fixed all uses of 'select' to use standard -macros rather than older bit-whacking style (kenny) - -2004-11-26 (bug fix)[1073524] Simplify the code to check for correctness of -strstr, strtoul and strtod on unix (fellows) - -2004-11-26 (bug fix)[1072136] Remove file normalize on tcl_findLibrary -search path uniqification added in 8.4.8 (porter) - -2004-11-30 (bug fix)[976520] Rework startup/initialization of the Tcl -library, encoding search initialization, and Tcl_FindExecutable structure. -[tclInit] no longer driven by the value of $::tcl_libPath (TCLLIBPATH). -(porter) - *** POTENTIAL INCOMPATIBILITY : makes encoding names case sensitive - on Windows, where they have been case insensitive *** - -2004-12-02 (bug fix)[1074671] Ensure tilde paths are not returned specially -by 'glob' (darley) - -Doc improvements [759545,926590,935853,1017072,1018486,1022527,1027849, - 1032243,1047928,1048005,1058446,1062647,1065732,1073334,etc.] -Test suite expansion [1036649,1001997,etc.] - ---- Released 8.5a2, December 7, 2004 - -2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter) - -2004-12-13 (bug fix)[1082349] restored C++ extension support (porter) - -2004-12-14 (bug fix)[1081541] workaround automake-ism "$U" (porter) - -2004-12-15 (new feature) CallFrames on execution, not C, stack (sofer) - -2004-12-16 (bug fix)[1085023] [interp limit] support in [vwait], etc. (fellows) - -2004-12-29 (bug fix)[1090413] make [clock scan 0030] work (morian,kenny) - -2004-12-29 (bug fix)[1092789] make [clock scan 10000] work (porter,kenny) - -2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs) - -2005-01-06 (performance)[1020491] [http::mapReply] (fellows) -=> http 2.5.1 - -2005-01-09 (bug fix)[1095909] stopped use of readdir_r (english) - -2005-01-10 (enhancement)[1081595] stopped use of TCL_DBGX (english) - -2005-01-17 (bug fix)[1100542] [glob] of Windows shares (schar,darley) - -2005-01-19 (new feature)[TIP 235] C API for ensembles (fellows) - -2005-01-21 (new feature)[TIP 233] virtual time (kupries) - -2005-01-25 (bug fix)[1101670] [auto_reset] update for [namespace] (porter) -***POTENTIAL INCOMPATIBILITY*** -May cause re-[source]-ing of files that have not anticipated that before. - -2005-01-27 (new feature)[TIP 218] Tcl_Channel API update for threads (kupries) - -2005-01-27 (bug fix)[1109484] Tcl_Expr* updates for Tcl_WideInt (hobbs) - -2005-01-28 (platform support)[1021871] Solaris gcc 64-bit support (hobbs) - -2005-02-10 (bug fix)[1119369] Tcl_EvalObjEx: avoid shimmer loss of List intrep -(sofer,macdonald) - -2005-02-11 (platform support) correct gcc builds for AIX-4+, HP-UX-11 (hobbs) - -2005-02-24 (bug fix)[1119798] prevent [source $directory] (porter,mpettigr) -=> tcltest 2.2.8 - -2005-03-10 (bug fix)[1153871] bad ClientData cast (porter,victorovich) - -2005-03-15 (platform support) OpenBSD ports patch (thoyts) - -2005-03-18 (bug fix)[1115904] restore recursion limit in direct eval (porter) - -2005-03-24 (bug fix) stop conflict between Tcltest and Thread packages (porter) - -2005-03-29 (platform support) allow msys builds without cygwin (hobbs) - -2005-04-01 (internal change)[1158008] internal rep of "list" Tcl_Obj's -now uses a refcounted struct (sofer) -***POTENTIAL INCOMPATIBILITY*** -For any code that goes poking into the internals of "list" Tcl_Obj's - -2005-04-05 (performance)[1174551] Tcl_DecrRefCount of Tcl_Obj "chains" (sofer) - -2005-04-08 (performance)[1077262] better Tcl_Encoding cache lifetimes (porter) - -2005-04-10 (bug fix)[1180368] [interp invokehidden] mem leak (kenny,porter) - -2005-04-12 (performance)[1177363] startup encoding file scan (porter) - -2005-04-12 (performance)[1182459] [clock format] (kenny) - -2005-04-13 (bug fix) min buffer size dropped from 10 to 1 byte (gravereaux) - -2005-04-16 (bug fix)[1178445] fix memory waste at thread exit (vasiljevic) - -2004-04-16 (bug fix)[1084111] [array names] memory leak (ade,sofer) - -2005-04-19 (bug fix)[1185933] [clock] init clobbered global vars (ring,kenny) - -2005-04-19 (new feature) [::tcl::unsupported::EncodingDirs] - unsupported -command to set search path for encoding files (porter) - -2005-04-20 (bug fix)[1090869] Tcl_GetInt accept 0x80000000, 64-bit -(porter,singh) - -2005-04-22 (bug fix)[1187123] [string is boolean] respect EIAS (porter) - -2005-04-25 (enhancement) update to tzdata2005i (kenny) - -2005-04-25 (platform support) builds on Mac OS X 10.1 (steffen) - -2005-04-27 (new feature)[TIP 183] [open $f {... BINARY ...}] (porter) - -2005-04-29 (new feature)[TIP 176] simple index arithmetic (porter) - -2005-05-06 (platform support) x86_64 Solarix cc and Solaris 10 builds (hobbs) - -2005-05-10 (bug fix)[1198892] [expr {i**0}] error (kaitschu,markus) - -2005-05-10 (new feature)[TIP 132] floating-point conversion to string (kenny) -***POTENTIAL INCOMPATIBILITY*** -For scripts that rely on (tcl_precision==12) number formatting - -2005-05-10 (new feature)[TIP 232] math functions as commands (kenny) -***POTENTIAL INCOMPATIBILITY*** -Tcl_GetMathFuncInfo functioning is reduced; routine is now deprecated - -2005-05-13 (feature removed) TCL_NO_MATH compiler directive (porter) - -2005-05-14 (platform support) Mac OSX: configurable CoreFoundation API -(steffen) - -2005-05-14 (platform support) Mac OSX: use realpath when threadsafe (steffen) - -2005-05-17 (feature removed) Tcl_ObjType's "list", "procbody", "index", -"ensembleCommand", "localVarName", "levelReference, "boolean" are no -longer registered (porter) -***POTENTIAL INCOMPATIBILITY*** -For any callers of Tcl_GetObjType on those strings - -2005-05-20 (bug fix)[1201589] boolean literal prefix in expressions (porter) - -2005-05-24 (platform support) Darwin build support merged into unix (steffen) - -2005-05-24 (new feature)[1202209] Mac OSX: support [load] of .bundle binaries -Can support [load] from memory as well (steffen) - -2005-05-24 (new feature)[1202178] [time] returns non-integer result (steffen) - -2005-05-25 (new feature)[TIP 182] [expr {bool(...)}] (mistachkin,porter) - -2005-05-30 (new feature)[TIP 229] [namespace path] (fellows) - -2005-05-31 (bug fix)[1082283] Unix: notifier thread now joinable (vasiljevic) - -2005-06-01 (new feature)[TIP 241] -nocase: lsort, lsearch, switch (mistachkin) - -2005-06-01 (bug fix)[1209759] "return TCL_RETURN;" could cause panic (porter) - -Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.] - ---- Released 8.5a3, June 4, 2005 - -2005-06-06 (bug fix)[1213678] Windows/gcc: crash in stack.test (kenny) - -2005-06-07 (new feature)[TIP 208] [chan] and [chan truncate] (fellows) - -2005-06-07 (revert) Restored registration of "procbody" Tcl_ObjType (porter) -Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17. - -2005-06-13 (bug fix)[1217375,1219176] [file mkdir] race (diekhans,darley) - -2005-06-14 (bug fix)[1220058] [namespace delete] crash (duquette,fellows) - -2005-06-17 (bug fix)[1221395] Tcl_LimitSetTime able to break [vwait] (fellows) - -2005-06-18 (bug fix)[1154163] [format %h] on 64-bit OS's (kraft,fellows) - -2005-06-21 (bug fix)[1201035,1224585] execution trace crashes (porter) - -2005-06-21 (bug fix)[1194458] Windows: [file split] (kenny,porter) - -2005-06-22 (bug fix)[1225727] Windows: pipe finalization crash (kenny) - -2005-06-22 (bug fix)[1225571] Windows: [file pathtype] buffer overflow (thoyts) - -2005-06-22 (bug fix)[1225044] Windows: UMR in pipe close (kenny) - -2005-06-23 (bug fix)[1225957] Windows/gcc: crashes in assembler code (kenny) - -2005-06-24 (bug fix) make Tcl_Preserve safe in Tk exit handlers (kenny) - -2005-07-01 (bug fix)[1222872] notifier spurious wake-up protection (vasiljevic) - -2005-07-05 (bug fix)[1230597] allow idempotent [namespace import] (porter) - -2005-07-15 (bug fix)[1237907] localtime() => NULL => crash (kenny) - -2005-07-21 (dropped support) IRIX 4, RISCos, Ultrix, and ancient BSD (kenny) -***POTENTIAL INCOMPATIBILITY*** - -2005-07-22 (enhancement)[1237755] 8.4 features in script library (fradin,porter) - -2005-07-24 (new feature) configure macros SC_PROG_TCLSH, SC_BUILD_TCLSH (dejong) -2005-07-26 (bug fix)[1047286] cmd delete traces during namespace delete (porter) - -2005-07-26 (new unix feature)[1231015] ${prefix}/share on ::tcl_pkgPath (dejong) -***POTENTIAL INCOMPATIBILITY*** - -2005-07-27 (bug fix)[1214462] [unknown] can return exceptions (porter) - -2005-07-27 (new feature) value of ::tcl_precision now kept per-thread (porter) -***POTENTIAL INCOMPATIBILITY*** - -2005-07-28 (unix bug fix)[1245953] O_APPEND for >> redirection (fellows) - -2005-07-29 (bug fix)[1247135] [info globals] return only existing vars (fellows) - -2005-07-30 (new Darwin feature) TCL_LOAD_FROM_MEMORY configuration (steffen) - -2005-08-05 (bug fix)[1241572] correct [expr abs($LONG_MIN)] (kenny) - -2005-08-05 (Solaris bug fix)[1252475] recognize cp1251 encoding (wagner,fellows) - -2005-08-11 (config options) eliminated USE_THREAD_STORAGE option (kenny) - -2005-08-23 (toolchain support) autoconf-2.59 now required (dejong) - -2005-08-24 (new feature)[TIP 219] reflected channels ([chan create]) (kupries) - -2005-08-25 (bug fix)[1267380] [lrepeat] buffer overflow prevention (fellows) - -2005-08-26 (bug fix) fix [namespace ensemble] crashes in Snit (fellows) - -2005-08-29 (bug fix)[1275043] restore round() away from zero (kenny) - -2005-08-29 (bug fix)[1189657] correct [tcl::tm::roots] (porter) - -2005-09-07 (bug fix)[1283976] invalid [format %c -1] result (porter) - -2005-09-08 (new feature)[1242844][TIP 254] new types for Tcl_LinkVar (fellows) - -2005-09-07 (toolchain support) deprecate TCL_VARARGS*; stdarg.h assumed (porter) -***POTENTIAL INCOMPATIBILITY*** - -2005-09-15 (RHEL bug fix)[1287638] support open >2GB files RHEL 3 (palan) - -2005-09-08 (new feature)[TIP 255] [expr min()] and [expr max()] (hobbs) - -2005-09-30 (bug fix)[1306162] $argv encoding and list formatting (porter) - -2005-10-04 (bug fix)[1067708] [fconfigure -ttycontrol] leak (hobbs) - -2005-10-04 (bug fix)[1182373] [http::mapReply] update to RFC 3986 (aho,hobbs) -=> http 2.5.2 - -2005-10-04 (HPUX bug fix)[1204237] shl_load() and DYNAMIC_PATH (collins,hobbs) - -2005-10-05 (bug fix)[979640] buffer overrun mixing putenv(), ::env (bold,hobbs) - -2005-10-08 (new feature)[TIP 237] unlimited range for integers (kenny,porter) -***POTENTIAL INCOMPATIBILITY*** for any code that relies on implicit truncation -of integer calculations to the range of a C long - -2005-10-14 (platform support)[1256937] MSVC++ static builds (thoyts) - -2005-10-19 (bug fix)[1331475] [dict append] crash (bills,sofer) - -2005-10-20 (bug fix)[1333036] [lset] shared sublist handling (sofer) - -2005-10-23 (bug fix)[1335006] memleack in [glob] (melbardis,darley) - -2005-10-23 (bug fix)[1325803] Win: [file stat] on links (bonilla,darley) - -2005-11-01 (bug fix)[1337941] Tcl_TraceCommand() -> crash (devilliers,porter) - -2005-11-02 (platform support)[1256937] MSVC 8 support (thoyts) - -2005-11-03 (new Win NT/XP feature) Unicode console support (kovalenko,thoyts) - -2005-11-04 (bug fix)[1337229,1338280] [namespace delete] / unset traces (sofer) - -2005-11-04 (enhancement) Korean timezone abbreviations (kenny) - -2005-11-04 (platform support)[1163896] LynxOS [load] (heidibr) - -2005-11-04 (bug fix)[1334947] value refcount error in var setting (sofer) - -2005-11-04 (Win enhancement)[1267871] extended exit codes (newman,thoyts) - -2005-11-07 (bug fix)[1348775] unset trace memory leak (sofer) - -2005-11-08 (bug fix)[1162286] [package require] checks that the script -registered by [package ifneeded] provides the version it claims (lavana,porter) -*** POTENTIAL INCOMPATIBILITY *** - -2005-11-09 (bug fix)[1350293,1350291] [after $negative $script] fixed (kenny) - -2005-11-12 (bug fix)[1352734,1354540,1355942,1355342] [namespace delete] -issues with [namespace path] and command delete traces (sofer,fellows) - -2005-11-18 (bug fix)[1358369] URL parsing standards compliance (wu,fellows) -=> http 2.5.2 - -2005-11-18 (revert) Restored registration of "list" Tcl_ObjType (porter) -Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17. - -2005-11-18 (bug fix)[1359094] Tclkit crash (thoyts, kupries) - -2005-11-20 (bug fix)[1091431] Tcl_InitStubs failure crashes wish (english) - -2005-11-27 (platform support) Darwin 64bit, Tiger copyfile(), and -Max OSX universal binaries support (steffen) - -2005-11-28 (bug fix) [clock] DST transition error (mackerras,kenny) - -2005-11-29 (bug fix)[1366683] [lsearch -regexp] backrefs (cleverly,fellows) - -2005-11-30 (performance) recoded portions of [clock] in C (kenny) - -2005-11-30 (enhancement) improved bytecode compiling of [switch] (fellows) -*** POTENTIAL INCOMPATIBILITY *** -For loading bytecode compiled and saved by earlier 8.5alpha releases - -2005-12-05 (Darwin bug fix)[1034337] NFS recursive file delete (steffen) - -2005-12-08 (platform support) Win x64 build (hobbs) - -2005-12-09 (bug fix)[1374778] [lsearch -start $pastEnd] => -1 (fellows) - -2005-12-12 (bug fix)[1377619] configure syntax error exposed in bash-3.1 (hobbs) - -2005-12-13 (bug fix)[1379349] [dict for] CoW error (ring,hippler,fellows) - -2005-12-18 (bug fix)[1382528] [dict for {k v} {} {}] crash (kovalenko,fellows) - -2005-12-27 clock tzdata updated to Olson's tzdata2005r (kenny) - -2005-12-27 libtommath updated to release 0.37 (kenny) - -2006-01-09 (bug fix)[1480572] [info level $l] => "namespace inscope" (porter) - -2006-01-11 (compat support)[1397843] when ::errorInfo is traced, fall back to -old pattern of stack trace construction (porter). -Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2004-10-05. - -2006-01-12 (bug fix)[1366227] Win: [file stat] sharing violation (darley) - -2006-01-23 (bug fix)[1410553] Tcl_GetRange Unicode confusion (twylite,spjuth) - -2006-01-23 (bug fix)[1412695] args handling in precompiled procs (traum,sofer) - -2006-02-01 (new feature)[1275435][TIP 250] [namespace upvar] (sofer) - -2006-02-01 (new feature)[958222][TIP 181] [namespace unknown] (madden) - -2006-02-01 (new feature)[944803][TIP 194] [apply] (mistachkin) - -2006-02-08 (new feature)[1413934][TIP 258] [encoding dirs], etc. (porter) - -2006-02-09 (new feature)[1413115][TIP 215] auto-init [incr] (leitgeb) - -2006-03-02 (bug fix)[1379287] norm of paths with /../ back to root (porter) - -2006-03-03 (compat support) Restored registration of a "boolean" Tcl_ObjType -(porter) -Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17. - -2006-03-06 (bug fix)[1439836,1444291] fix TCL_EVAL_{GLOBAL,INVOKE} handling -when auto-loading or exec traces are present (porter) - -2006-03-10 (bug fix)[1437595] Win socket finalize with threads (vasiljevic) - -2006-03-13 (revert 2005-07-26 change) ${prefix}/share on ::tcl_pkgPath (porter) - -2006-03-14 (bug fix)[1448251] TCLX.y_TM_PATH handling (noble, kupries) - -2006-03-14 (bug fix)[768659] pipeline error when last command missing (kupries) - -2006-03-18 (bug fix)[1193497] Win porting of [file writable] (darley,vogel) - -2006-03-18 (bug fix)[1084705] [glob -nocomplain] silence empty result only, -no other errors (darley) -***POTENTIAL INCOMPATIBILITY*** - -2006-03-21 (platform enhancement)[823329] HFS globbing support (steffen) - -2006-03-23 (platform support) updated tcl.spec file (max) - -2006-03-28 (bug fix)[1064247] BSD: path normalization with realpath() (steffen) - -2006-04-03 (bug fix)[1462248] crash reading utf-8 chars spanning multiple -buffers at end of file (kraft,kupries) - -2006-04-05 (bug fix)[1464039] Tcl_GetIndexFromObj: empty key (fellows) - -2006-04-05 (bug fix) overdue dde, registry patchelevel increments (porter) -=> dde 1.3.2 -=> registry 1.2 - -2006-04-06 (bug fix)[1457515] TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING -removed (steffen) - -2006-04-11 (bug fix)[1458266] enter/enterstep trace interference (leunissen) - -2006-04-12 (feature change)[1376892] revised definition of [:print:] (fellows) - -(platform support) Use of _ANSI_ARGS_ purged. ANSI compiler required (fellows) - -Documentation improvements [1211078,1190891,1292427,1277503,1104682,1359183, -1415725,666770] - ---- Released 8.5a4, April 27, 2006 - -2006-05-04 (bug fix)[1480509] srand() accept wide input (porter,afredd) - -2006-05-05 (bug fix)[1481986] interactive Tcl_Main blocks main loop (porter,lin) - -2006-05-13 (bug fix)[1482718] proc re-compile: preserve the previous -bytecode while references still on the stack (porter,ryazanov) - -2006-05-27 (bug fix)[923072] Darwin: made unthreaded CoreFoundation notifier -naked-fork safe on Tiger (steffen) - -2006-06-20 (internal change) Dropped the internal routines used to hook into -filesystem operations back in the pre-Tcl_Filesystem days. (porter) -***POTENTIAL INCOMPATIBILITY*** -For extensions and programs that have never migrated to the supported Tcl 8.4 -interface for virtual filesystems - -2006-07-05 (enhancement) Expression parser rewrite avoids stack overflow, -reduces from O(N^2) to O(N) complexity, and greatly improves syntas error -messages (porter) -***POTENTIAL INCOMPATIBILITY*** -For any code relying on exact error messages. - -2006-07-20 (platform support) Mac OS X weak linking (steffen) - -2006-07-20 (bug fix) Darwin: execve() works iff event loop not yet run (steffen) - -2006-07-24 (bug fix)[1518166] Uninitialized Tcl_DString (afredd) - -2006-07-30 (bug fix)[1426279,1505383,1494664,1531530] [clock] fixes (kenny) - -2006-08-09 (bug fix)[1531184] [dict for {file stat} x {}] crash (fellows) - -2006-08-10 (bug fix)[1538262,1530474] code cleanup; optimizations (afredd) - -2006-08-18 (bug fix) intermittent failures in TclUnixWaitForFile() (steffen) - -2006-08-18 (platform support) Darwin x86_64 (steffen) - -2006-08-21 (bug fix)[1457797] Darwin 64-bit notifier hang (steffen) - -2006-08-21 (bug fix) Darwin: recursively called event loop (steffen) - -2006-08-21 (enhancement) Darwin: nanosec resolution clicks and [time] (steffen) - -2006-08-28 (bug fix)[1547681] TclFormatObj count arguments (mistachkin,porter) - -2006-08-28 (bug fix) stack.test failure on FreeBSD (mistachkin) - -2006-08-30 (bug fix)[1548263] filesystem segfaults (hobbs,mccormack) - -2006-08-31 (bug fix)[1541274] [expr {sqrt(-1)}] => -NaN (suchenwirth,porter) - -2006-09-06 (bug fix)[999544] use of MT-safe system calls (vasiljevic) - -2006-09-10 (platform support) Darwin: msgcat use CFLocale (steffen) -=> msgcat 1.4.2 - -2006-09-10 (new feature) tcltest option: -verbose line (steffen) -=> tcltest 2.3a1 - -2006-09-19 (bug fix)[1555271,1561260] Several ** operator bugs (porter) - -2006-09-22 (bug fix)[1562528] NULL terminates variadic calls (fellows,ryazanov) - -2006-09-22 (new feature)[1520767][TIP 268] [package] alpha/beta version; -[package require] ranges, [package prefer] selection mode (kupries) - -2006-09-26 (platform support) MSVC8 AMD64 support (thoyts) - -2006-09-27 (bug fix)[1567222] bignum << errors (porter) - -2006-09-30 (enhancement)[1190441] quiet no-op [history] (sofer) - -2006-10-04 clock tzdata updated to Olson's tzdata2006m (kenny) - -2006-10-05 (bug fix)[1570718] make [lappend $nonList] complain (sofer,virden) - -2006-10-05 (bug fix)[1122671] alignment fixes in unicode encoding routines -(hobbs,staplin) - -2006-10-05 (enhancement) Allow "_" in Tcl Module filenames (kupries) - -2006-10-05 (new feature) [set ::http::strict 0] (default value is 1) to disable -URL validity checking against RFC 2986 (hobbs) -=> http 2.5.3 - -2006-10-06 (new feature)[1565751][TIP 275] [binary scan] unsigned (thoyts) - -2006-10-10 (bug fix)[1566526] crash cleaning up [namespace path] data (porter) - -2006-10-12 (bug fix)[1576006] better error messages from [interp alias] (sofer) - -2006-10-13 (platform support) get stack size on Darwin (steffen) - ---- Released 8.5a5, October 20, 2006 - -2006-10-20 (configure change) Added autodetection for OS-supplied timezone -files (max) - -2006-10-23 (enhancement)[1577278] Ensure the Tcl call stack always has a -CallFrame, even at level 0 (sofer) - *** POTENTIAL INCOMPATIBILITY for users of tclInt.h *** - -2006-10-23 (enhancement)[1577492] Tcl_PushCallFrame and [info level] -enhanced for ensemble rewrites (sofer) - *** POTENTIAL INCOMPATIBILITY for [info level 0] on interp alias *** - -2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs) - *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** - -2006-11-04 (new feature)[TIP 274] Exponentiation operator is right -associative (porter) - -2006-11-09 (new feature)[TIP 272] Added [lreverse] and [string reverse] -commands (fellows) - -2006-11-14 (new feature)[TIP 261] [namespace import] returns list of -imported commands (porter) - -2006-11-15 (new feature)[TIP 270] New C routines Tcl_ObjPrintf, -Tcl_AppendObjToErrorInfo, Tcl_Format, Tcl_AppendLimitedToObj, -Tcl_AppendFormatToObj, Tcl_AppendPrintfToObj (porter) - -2006-11-22 (feature change) Moved TCL_REG_BOSONLY from tcl.h to tclInt (porter) - -2006-11-22 (new feature)[TIP 269] Added [string is list] classification -command (mistackin, fellows) - -2006-11-25 (new feature)[TIP 174] Added commands corresponding to most -expr operators in ::tcl::mathop (fellows) - -2006-11-26 (platform support)[1230558] --enable-64bit on more systems (steffen) - -2006-11-27 (bug fix)[1602208] Fix 64-bit handling of select() on unix where -fd was greater than 32 (fontaine, kenny) - -2006-11-28 (new feature)[TIP 280] Added [info frame] command for more -Tcl-level debugging information (kupries) - -2006-12-01 (feature change)[TIP 298] Change Tcl_GetBignumAndClearObj to -Tcl_TakeBignumFromObj (porter) - -2006-12-01 (new feature)[TIP 287] Added [chan pending] subcommand (cleverly) - -2006-12-01 (new feature)[TIP 299] Added isqrt() expr operator (kenny) - -2006-12-04 (new feature)[TIP 267] Added -ignorestderr option to exec (fellows) - -2006-12-05 (new feature)[TIP 291] ::tcl_platform(pointerSize) key (kupries) - -2007-01-11 (configure change) Remove "-Wconversion" from deflt CFLAGS (english) - -2007-01-25 (configure change) Ensure CPPFLAGS env var is used when set (steffen) - -2007-02-19 (configure change) Use SHLIB_SUFFIX=".so" on HP-UX IA64 (was -".sl") (hobbs) - -2007-02-20 (bug fix)[1479814] Handle Windows NT \\?\... extended paths (thoyts) - -2007-03-01 (bug fix)[1671138] Fix infinite loop in compiled foreach with an -empty list (fellows) - -2007-03-07 (enhancement) Improved Windows time zone tables to handle new US -DST rules (kenny) - -2007-03-09 (enhancement) Improved Y2038 compliance of zoneinfo files (kenny) - -2007-04-02 (enhancement) Added bytecode compilation for global, variable, -upvar and namespace upvar (sofer) - -2007-04-20 (bug fix) Improve clock localization for Japanese locale (kenny) - -2007-04-20 (enhancement) Document Tcl_SetNotifier & Tcl_ServiceModeHook (kenny) - -2007-04-23 (bug fix) fts_open() crash on 64bit Darwin 8 or earlier (steffen) - ---- Released 8.5a6, April 25, 2007 - -2007-04-30 (bug fix)[1705778] many valgrind-detected leaks corrected - -2007-05-01 (bug fix)[1710709] leak in [string map] (porter) - -2007-05-02 (bug fix)[1710707] leaks in filesystem paths (mistachkin,kenny) - -2007-05-18 (feature change) {expand} syntax support removed. (porter) - *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** - -2007-05-29 (bug fix)[1712723] Joinable thread death on 64-bit (virden,hobbs) - -2007-05-30 (feature change)[1725186] When expanded literals are parsed, -(example: {*}{1 2 3}), TCL_TOKEN_EXPAND_WORD token is no longer returned. -Tokens reflecting the expansion are returned instead. (porter) - *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** - -2007-06-06 (platform support) Darwin: add plist to tclsh (steffen) - -2007-06-12 (enhancement) [info] is now a [namespace ensemble] (fellows) - -2007-06-20 (enhancement) better `make html` results (hobbs) - -2007-06-21 (feature change)[1740962] leave traces created during execution -of traced command do not fire (sofer) - *** POTENTIAL INCOMPATIBILITY *** - -2007-06-23 (bug fix) Darwin: prevent post-fork() abort() (steffen) - -2007-06-27 (bug fix)[1743941] Infinite loop in Tcl_CreateTrace traces (porter) - -2007-06-29 (enhancement) Tcl_Alloc alignment on Darwin (steffen) - -2007-06-30 (bug fix)[1726873] crash in thread sync objects (vasiljevic,twylite) - -2007-06-30 (bug fix)[1717186] [lsort -command \{ $l] leak (afredd,fellows) - -2007-07-05 (bug fix)[1743676] no command named "" error message (porter,virden) - -2007-07-11 (bug fix)[1752146] [while 1 {}] & [interp limit] on commands (sofer) - -2007-07-31 (bug fix)[681877] tcl_platform(user) from system, not env (fellows) - -2007-07-31 (enhancement)[1750051] space efficiency of Tcl variables (sofer) - *** POTENTIAL INCOMPATIBILITY for C code that accesses internal - Tcl structs Var, Bytecode, Namespace, or CallFrame. *** - -2007-08-01 (enhancement)[1764318] word.tcl proc rewrites (petasis,fellows) - -2007-08-08 (bug fix)[1770224] [tcl::mathop::>> $big1 $big2] errors (porter) - -2007-08-14 (platform support) Darwin [load] from VFS on intel & 64bit (steffen) - -2007-08-15 (bug fix)[1773127] corrected open mode "a+" (rottman,fellows) - -2007-08-16 (bug fix)[1773040] ::errorInfo trace crash (janssen,porter) - -2007-08-16 (performance)[1564517] precompile constant expressions (porter) - -2007-08-21 (bug fix)[1775878] 'puts \' in interactive tclsh failed to move to -prompt for continuation line (porter) - -2007-08-25 (bug fix)[1781282] [clock scan] case senstivity (kenny) - -2007-08-25 (performance)[1767293] ** on native integer types (kenny) - -2007-09-03 clock tzdata updated to Olson's tzdata2007g (kenny) - -2007-09-06 (platform support) Darwin: drop support for Xcode 1.5 project, add -project for Xcode 3.0 (steffen) - -2007-09-08 (bug fix)[1786481] nested [dict update] crash (fellows) - -2007-09-08 (bug fix)[1710710] TclPtrSetVar leak (mistachkin,sofer) - -2005-09-09 (feature removed) Tcl_ObjType "nsName" no longer registered (porter) - *** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("nsName") *** - -2007-09-10 (bug fix)[1740631] Linked variable unlink prevention (maros,hobbs) - -2007-09-11 (bug fix)[1786481] [dict update] stack management (sofer) - *** POTENTIAL INCOMPATIBILITY with previous 8.5 alpha bytecode only *** - -2007-09-11 (bug fix)[1578344] [package require -exact] 8.4 compat (porter) - *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** - -2007-09-11 (bug fix)[1772989,1071322] Support _, : in test constraints (porter) -=> tcltest 2.3b1 - -2007-09-11 (platform support) Windows AMD64 support (thoyts) - -2007-09-14 (enhancement)[1793984] DTrace provider for Tcl (steffen) - -2007-09-14 (bug fix)[1519940] surplus ns path invalidation (fellows,bauer) - -2007-09-15 (platform support) SunOS-5.1x link with cc, not ld (steffen) - -2007-09-17 (platform support)[1748251] Fix NetBSD link failures (english) - -(bug fix)[1066755] Several stack efficiency efforts increases recursion limit -on Windows to be larger than the default [interp recursionlimit] value - ---- Released 8.5b1, September 26, 2007 - -2007-10-02 (bug fix)[1806422] proper [tcl::tm::path] autoload (porter) - -2007-10-02 (bug fix) Improve Tcl_DecrRefCount() robustness (staplin) - -2007-10-11 (bug fix)[1805887] [string is int -failindex] for 0o, 0b (porter) - -2007-10-15 (bug fix)[1813528] Tcl_ParseBraces read past buffer (mistachkin) - -2007-10-25 (bug fix)[1726873] intermittent crash in threads (vasiljevic) - ---- Released 8.5b2, October 26, 2007 - -2007-10-27 (bug fix)[1821159] fixed broken compile on x86_64 (sofer) - -2007-10-27 (bug fix)[1810264] stop panic in RE lexer (fellows) - -2007-10-28 (enhancement)[1826906] Embed iso8859-1 encoding in libtcl (fellows) - -2007-11-01 (bug fix)[1808258] [string is ascii \000] (fellows) - -2007-11-05 (bug fix)[1823576] [fconfigure $serial -xchar \000] (cassof) - -2007-11-07 (performance)[1827996] binary glob matching (hobbs) - -2007-11-07 (performance) binary [gets] (hobbs) - -2007-11-09 (performance)[1829248] interp state reset (sofer) - -2007-11-10 (performance) stack checking (sofer) - -2007-11-10 (performance) list indexing bytecode (sofer) - -2007-11-11 (performance)[1830038] macros to fetch Tcl_Obj intreps (sofer) - -2007-11-11 (performance)[1830166] RE bytecode for simple cases (hobbs) - -2007-11-13 (performance) [switch] & [regexp] use RE bytecode (hobbs, fellows) - -2007-11-14 (performance) bytecode for [info exists] (fellows) - -2007-11-15 (new feature)[1231022] configure option: --disable-rpath (fellows) - -2007-11-15 (bug fix)[1810038] infinite loop in RE compiler (lane,porter) - -Many significant documentation improvements (fellows, sofer) - ---- Released 8.5b3, November 19, 2007 - -2007-11-20 (enhancement) string rep of dict has stable order (fellows) - -2007-11-21 (enhancement) compiled ensemble support (fellows) - -2007-11-22 (enhancement) [dict] is now an ensemble (fellows) - -2007-11-23 (enhancement) [string] is now an ensemble (fellows) - -2007-11-26 (bug fix)[1815573] Correct stack checking failure (sofer,golovan) - -2007-11-27 (bug fix)[800753] Document single byte char limit for -[chan configure -eofchar] (cassoff) - -2007-12-03 (enhancement)[1836519] [switch $val $body] safe/fast (fellows,spjuth) - -2007-12-03 (release) tcltest package bump to 2.3.0 (porter) - -2007-12-03 (bug fix)[1618235] fix BSD compile errors (fellows) - -2007-12-05 (bug fix)[1844789] fix [lsearch -exact -integer] crash (fellows) - -2007-12-05 (performance)[1845092] Tcl_ObjType for channel names (hobbs) - -2007-12-14 (bug fix)[1602539] NUL pollution in [glob] result (hobbs) - -2007-12-17 (bug fix)[1851832,1851524] memory alignment correction (sofer) - -2007-12-18 (bug fix)[1810264] revised regexp engine to prevent debilitating -over-consumption of resources (drewry,lane,ormandy,fellows) - -Several documentation and release notes improvements - ---- Released 8.5.0, December 20, 2007 - -2007-12-23 (bug fix)[1857126] restore backref support to regexps (hobbs) - -2007-12-26 (enhancement)[1856994] [lsort] performance (sofer) - -2008-01-10 (bug fix)[1867855] fix [format %lli 0] crash (porter) - -2008-01-11 (bug fix)[1850424,1860425] stack checking on *bsd (sofer,noble) - -2008-01-13 (bug fix)[1353846] crash in read-only serial (hobbs,newman) - -2008-01-15 (bug fix)[1869989] mem leak; expr literals (porter,melbardis) - -2008-01-20 (bug fix)[1869405] binary [gets]; stacked channels (hobbs,ficicchia) - -2008-01-22 (bug fix)[1867855] fix [lreverse {}] crash (sofer,madden) - -2008-01-30 (bug fix)[1882373] fix Tcl_GetAlias pointer code (an00na) - -Several documentation and release notes improvements - ---- Released 8.5.1, February 5, 2008 - -2008-02-06 (enhancement) [clock format] performance (kenny) - -2008-02-12 (bug fix)[1891827] compiled [switch -nocase] error (fellows) - -2008-02-22 (bug fix)[1818565] missing state array in http::status (thoyts) -=> http 2.5.4 - -2008-02-26 (bug fix)[1868845] corrected [eof] ordering (thoyts) - -2008-02-26 (new feature) [http::meta] command (thoyts) -=> http 2.5.5 - -2008-02-26 (bug fix)[1902436] fixed regexps ending in \* (hobbs) - -2008-02-27 (bug fix)[1862555,1902423] [clock] range & l10n (kenny) - -2008-02-28 (bug fix) [return -level 0] memory leak (porter) - -2008-02-28 (bug fix) [format %llx $big] memory leak (porter) - -2008-02-28 (bug fix) expression parser error message memory leak (porter) - -2008-02-28 (bug fix) memory leak when enter trace modifies command (porter) - -2008-02-29 (enhancement) Consumer refcounting for Tcl_SetReturnOptions() -and Tcl_AddObjToErrorInfo() (spjuth,porter) - *** POTENTIAL INCOMPATIBILITY *** - -2008-03-07 (bug fix)[1899164] Avoid expr and script bytecode confusion (porter) - -2008-03-07 (bug fix)[1904907] finalize crash in Tcl_GetReturnOptions (kupries) - -2008-03-10 (bug fix)[1893815] expr {abs(-1e-350)} => -0.0 (porter) - -2008-03-10 (bug fix)[1901113] crash in [tcl::Bgerror {} {}] (madden,porter) - -2008-03-11 (bug fix)[1911919] unset trace inf loop in namespace delete (sofer) - -2008-03-12 (new feature) some HTTP 1.1 support in http (and more!) (hobbs) -=> http 2.7 - -2008-03-13 (enhancement) support space in INSTALL_ROOT or $builddir (steffen) - -2008-03-16 (bug fix)[1903325] bytecode stack space prediction crash (fellows) - -2008-03-18 (bug fix)[1914604] Tcl Modules: encoding fixed to utf-8; environment -variables without "." added to customization hooks (kupries) - *** POTENTIAL INCOMPATIBILITY *** - -2008-03-18 (bug fix)[1914503] alignment of TclStackAlloc() return (sofer)\ - -2008-03-20 (bug fix)[1868171] expose Tcl_GetMemoryInfo (for AOLserver) (fellows) - -2008-03-24 (bug fix)[1923966] crash in [binary format x0s] (thoyts) - -2008-03-27 (platform support)[1921166] Solaris 64bit build fixes (steffen) - -2008-03-27 clock tzdata updated to Olson's tzdata2008b (kenny) - ---- Released 8.5.2, March 28, 2008 - -2008-03-30 (bug fix)[1783544] more robust TclIsNaN() (kenny,teterin) - -2008-04-01 (interface)[1819422] tclStubsPtr no longer in libtcl (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2008-04-01 (bug fix)[1839067] FP round fix for Solaris/x86 (kupries,schlenker) - -2008-04-02 (bug fix)[780533,1932639] [fcopy] callbacks unreliable (ferrieux) - -2008-04-02 (interface)[1819422] libtclstub symbols MODULE_SCOPE (steffen) - -2008-04-04 (bug fix) [chan postevent] crash (kupries) - -2008-04-07 (bug fix) Fix broken [format {% d}] (max) - -2008-04-07 (bug fix)[1350564] Bi-directional [fcopy] now supported (ferrieux) - -2008-04-16 (bug fix)[1938497] Tcl_SetNotifier() fixes (steffen) - -2008-04-16 (interface)[1938497] make stubs tables 'static const' (steffen) - -2008-05-02 (new feature) [binary] is now a [namespace ensemble] (thoyts) - -2008-05-07 (bug fix) [dict append] crash (mccormack,fellows) - -2008-05-21 (bug fix)[1968882] [info complete "\\\n"] => 0 (porter) - -2008-05-22 (bug fix)[1968245] Tcl_LogCommandInfo() accept length=-1 (darroch) - -2008-05-23 (bug fix)[1965787] 32-bit overflow in [tell] result (ferrieux) - -2008-05-31 (new feature)[TIP 257] [oo::*] commands from TclOO (fellows) - -2008-06-04 (new feature)[TIP 317] [binary encode]; [binary decode] (thoyts) - -2008-06-06 (new feature)[TIP 230] [chan push]; [chan pop] (kupries) - -2008-06-08 (enhancement)[1973096] bytecompiled [uplevel] scripts (sofer) - -2008-06-12 (platform support) Solaris static build with DTrace (steffen) - -2008-06-12 (platform support) Solaris/amd64 gcc 64bit support (steffen) - -2008-06-13 (new feature)[TIP 285] [interp cancel]; Tcl_CancelEval() (mistachkin) - -2008-06-20 (bug fix)[1999035] make [interp bgerror $i] act in $i (porter) - -2008-06-23 (bug fix)[1972879] bad path intrep caching (porter) - -2008-06-24 (bug fix)[1999176] crash in [glob -dir {} a] (porter) - -2008-06-25 (bug fix)[1999119] Support TM packages in Safe Base (kupries) - ---- Released 8.6a1, June 25, 2008 - -2008-06-29 (bug fix)[2004480] plug memory leaks (ade,porter,steffen) - -2008-07-01 (enhancement)[1905562] embed recursion limit in RE engine (fellows) - -2008-07-03 (bug fix)[1969717] fix package finding on Samba shares (jos) - -2008-07-03 (bug fix)[1987821] mem leak in [seek] on reflected chan (kupries) - -2008-07-13 (enhancement)[2017110] new Non-Recursive Evaluation implementation -enables deep Tcl evaluation stacks without deep C stacks. (sofer) - -2008-07-20 (enhancement)[2008248] dict->list preserve item intreps (pasadyn) - -2008-07-21 (bug fix)[582506] imported cmds now fire execution traces (sofer) - -2008-07-21 (bug fix)[2015723] [file] bad use of inodes on Windows (thoyts) - -2008-07-21 (new feature)[TIP 304] [chan pipe] (ferrieux) - -2008-07-21 (bug fix)[2021443] more consistent "wrong # args" msgs (nijtmans) - -2008-07-21 (enhancement) [info frame] returns file data in more cases (kupries) - -2008-07-29 (bug fix)[2030670] fix rare panic in TclStackFree (pasadyn,sofer) - -2008-08-01 Tcl_Finalize() no longer called implicitly on DLL_PROCESS_DETACH. - -2008-08-05 (enhancement)[1994512] async connect logic simplified (jenglish) - -2008-08-06 (bug fix)[2040295] stopped supplying a workaround for bugs -in Itcl's use of [namespace code]. Itcl now supplies its own workaround. - *** POTENTIAL INCOMPATIBILITY for older Itcl releases *** - -2008-08-06 (bug fix)[2039178] repaired guard against dispatching oo methods -in a deleted interp. (porter) - -2008-08-08 tzdata updated to Olson's tzdata2008e (kenny) - -2008-08-11 (bug fix)[2046846] 64bit support for http zlib crc (thoyts) -=> http 2.7.1 - -2008-08-11 (enhancement) automatic [package provide] for TMs (kupries) - -2008-08-17 (bug fix)[2055782] crash involving Tcl_ConcatObj (sofer) - -2008-08-21 (new feature) CONST-ified Tcl routines passing (Tcl_ObjType *), -(Tcl_Filesystem *), or (Tcl_Timer *) arguments (nijtmans,porter) - *** POTENTIAL INCOMPATIBILITY *** - -2008-08-21 (bug fix)[2065115] Restored ***= regexp functioning (hobbs,porter) - ---- Released 8.6a2, August 25, 2008 - -2008-08-29 (bug fix)[2082299] Install TclOO header files (fellows) - -2008-09-01 oo methods called during interp deletion no longer skipped if -they do not need the dying interp (fellows) - -2008-09-02 (support) Dropped support for pre-ANSI compilers. (porter) - -2008-09-04 (bug fix)[2093947] var unset trace in coroutine (fellows,sofer) - -2008-09-10 (enhancement) efficient list->dict conversion (elby,fellows) - -2008-09-10 (bug fix)[2102930] faulty numLevels count (madden,sofer) - -2008-09-16 (bug fix)[2114165] eval failure following cancel (sofer) - -2008-09-17 (bug fix)[2116053] export [min] and [max] from tcl::mathfunc (sofer) - -2008-09-22 (new feature)[TIP 320] oo common variable declaration (fellows) - -2008-09-24 (new feature)[TIP 316] portable access to Tcl_StatBuf (fellows) - -2008-09-24 (new feature)[TIP 323] [file delete], [file mkdir] zero pathNames (porter) - -2008-09-25 (new feature)[TIP 315] new var: tcl_platform(pathSeparator) (vu,fellows) - -2008-09-25 (new feature)[TIP 323] [global], [variable] zero varNames (porter) - -2008-09-26 (new feature)[TIP 323] [lassign], [namespace upvar], [my variable] zero varNames (porter) - -2008-09-26 (new feature)[TIP 323] [tcl::tm::path add|remove] zero pathNames (porter) - -2008-09-26 (new feature)[TIP 323] [lrepeat] zero elements; zero repeats (porter) - -2008-09-27 (bug fix)[2130992] prevent overflow crash in [lrepeat] (fellows) - -2008-09-28 (new feature)[TIP 314] ensemble parameters before subcommand (hellström,fellows) - -2008-09-29 (new feature)[TIP 318] revised defaults for [string trim] (poser) - *** POTENTIAL INCOMPATIBILITY *** - -2008-09-29 (new feature)[TIP 313] [lsearch -bisect] (spjuth) - -2008-09-29 (new feature)[TIP 326] [lsort -stride] (elby) - -2008-09-29 (new feature)[TIP 323] [linsert] zero elements (porter) - -2008-09-29 (new feature)[TIP 323] [glob] zero patterns (porter) - -2008-10-02 (new feature)[TIP 330] interp->result access disabled (kenny) - *** POTENTIAL INCOMPATIBILITY *** - -2008-10-03 (new feature)[TIP 265] Tcl_ParseArgv() (bromley) - -2008-10-03 (new feature)[TIP 195] [tcl::prefix] (spjuth) - -2008-10-04 (new feature) CONST-ified Tcl routines Tcl_GetIndexFromObj, -Tcl_RegisterConfig, Tcl_InitCustomHashTable, and routines passing -(Tcl_ChannelType *). (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2008-10-04 (bug fix)[2059262] unload only libraries marked unloadable (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2008-10-05 (new feature)[TIP 331] [lset listVar end+1 $value] (kenny) - -2008-10-05 (bug fix)[2143288] correct bad isqrt() results (boffey,kenny) - -2008-10-05 (new feature) CONST-ified return value of the -Tcl_FSFileAttrStringsProc prototype. (nijtmans) - *** POTENTIAL INCOMPATIBILITY for Tcl_Filesystems *** - -2008-10-07 (new feature)[TIP 327] [tailcall] (sofer) - -2008-10-07 (new feature)[TIP 328] [coroutine],[yield],[info coroutine] (sofer) - -2008-10-08 (bug fix)[2151707] fix stack trace from variable trace (porter) - -2008-10-10 (bug fix)[2155658] crash in oo method export (fellows) - ---- Released 8.6a3, October 10, 2008 - -2008-10-13 (bug fix) Fix ability to join threads on 64-bit Windows (thoyts) - -2008-10-23 (bug fix)[2186888] Direct-eval [for] handling of [continue] was -broken by NRE reform (sofer,porter) - -2008-10-24 (bug fix) fix failure to read SHOUTcast streams (thoyts) -=> http 2.7.2 - -2008-10-27 (enhancement) system encoding at startup is now "iso8859-1", and -no longer "identity". Use of identity encoding minimized (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2008-10-31 (bug fix)[2200824] revised [oo::define] to include caller -context when resolving names. (nassau,fellows) - -2008-11-10 (bug fix)[2255235] [platform::shell::LOCATE] update (ring,kupries) -=> platform::shell 1.1.4 - -2008-11-13 (bug fix)[2269431] VFS [load] -> tempfile litter (ficicchia,nijtmans) - -2008-11-26 (bug fix)[2114900] updated tclIndex file (cassoff,kenny) - -2008-11-27 (bug fix)[2251175] [{*}{\{}] errors (hellström,ferrieux,porter) - -2008-11-29 (new feature)[TIP 210] [file tempfile] (techentin,fellows) - -2008-11-30 (bug fix)[2362156] [clock]: colon in format string (mizuno,kenny) - -2008-12-02 (bug fix)[2270477] hang in channel finalization (ferrieux,kupries) - -2008-12-02 (new feature)[TIP 336] Tcl_*ErrorLine() routines. Direct access -to the errorLine field of the interp struct denied by default. (porter) - *** POTENTIAL INCOMPATIBILITY *** - *** Define USE_INTERP_ERRORLINE to restore access for legacy code *** - -2008-12-04 (bug fix)[2385549] [file normalize] failed on some paths (porter) - -2008-12-05 (new feature)[TIP 307] Tcl_TransferResult() (leunissen,fellows) - -2008-12-05 (new feature)[TIP 335] Tcl_InterpActive() (mistachkin,fellows) - -2008-12-09 (new feature)[TIP 337] Tcl_BackgroundException() (porter) - -2008-12-10 (new feature)[TIP 341] >1 [dict filter] patterns (hellström,fellows) - -2008-12-10 (new feature)[TIP 343] [format %b $n] [scan $s %b] (ferrieux) - -2008-12-10 tzdata updated to Olson's tzdata2008i (kenny) - -2008-12-11 (new feature)[TIP 234] [zlib] and Tcl_Zlib*() (sheffers,fellows) - -2008-12-11 (bug fix)[2407783] spoil ChannelState when channel name passes -among multiple interps (kupries) - -2008-12-12 (new feature)[TIP 322] Tcl_NR*() routines to enabled non-recursive -evaluation in extensions (sofer,kenny) - -2008-12-09 (new feature)[TIP 338] Tcl_*StartupScript() (porter) - *** POTENTIAL INCOMPATIBILITY for callers of Tcl*Startup* routines *** - -2008-12-16 (new feature)[TIP 329] [try] [throw] (davel,fellows) - -2008-12-17 (new feature)[TIP 308] package tdbc 1.0b1 (kenny) - -2008-12-18 (new feature)[TIP 332] [close $chan read|write] (ferrieux) - -2008-12-18 (bug fix)[2444274] panic in long commands from {*} (goth,porter) - ---- Released 8.6b1, December 19, 2008 - -2008-12-27 [TIP 234] Tcl_Zlib* interface revisions (fellows) - *** INCOMPATIBILITY with interface of 8.6b1 *** - -2009-01-02 (platform support)[878333] IRIX compat for mkstemp() (fellows) - -2009-01-03 (bug fix)[2481670] [clock add] error message (talvo) - -2009-01-05 (bug fix)[2412068] NR-enable [source] (fellows) - -2009-01-06 (bug fix)[2489836] crash unknown method dispatch (nadkarni,fellows) - -2009-01-06 (bug fix)[2481109] fix context of instance name check (fellows) - -2009-01-08 (enhancement) more -errorcode values (fellows) - -2009-01-19 (new feature) CONFIG_INSTALL_DIR - where tclConfig.sh goes (cassoff) - -2009-01-19 (platform support) better tools for BSD ports (cassoff) - -2009-01-21 (bug fix)[2458202] exit crash with [chan create]d channel (kupries) - -2009-01-26 (bug fix)[2446662] uniformly declare EOF on RST on sockets (ferrieux) - -2009-01-26 (bug fix)[1028264] delay WSACleanup() from under our feet (ferrieux) - -2009-01-29 (bug fix)[2519474] Tcl_FindCommand() bug exposed by oo (fellows) - -2009-01-29 (bug fix)[2537939] Fix Tcl_OOInitStubs() for no-stubs build (fellows) - -2009-02-04 (bug fix)[2561746] [string repeat] overflow crash (porter) - -2009-02-05 (enhancement) optimize string operations on bytearrays (fellows) - -2009-02-12 (bug fix) enable simpler [oo::define] extension (ferri,fellows) - -2009-02-15 (bug fix)[2603158] Tcl_AppendObjToObj: append to self crash (porter) - -2009-02-17 (platform support) MSVC and _WIN64 (hobbs) - -2009-02-20 (bug fix)[2571597] [file pathtype /a] wrong result (nadkarni,porter) - -2009-03-03 (bug fix)[2662434] [zlib crc32] result now unsigned (gavilan,fellows) - -2009-03-15 (platform support) translate SIGINFO where defined (BSD) (teterin) - -2009-03-15 (bug fix)[2687952] TSD struct memleak (mistachkin) - -2009-03-18 (bug fix)[2688184] memleak in [file normalize] (mistachkin) - -2009-03-20 (bug fix)[2597185] crash in Tcl_AppendStringToObj (porter) - -2009-03-20 (bug fix)[2561794,2669109,2494093,2553906] string overflow (porter) - -2009-03-22 (bug fix)[2502037] NR-enable [namespace unknown] (sofer) - -2009-03-27 (bug fix)[2710920] [file dirname|tail /foo/] errors (epler,porter) - -2009-04-08 (bug fix)[2570363] unsafe [eval]s in tcltest (bron,porter) -=> tcltest 2.3.1 - -2009-04-08 (platform support) more Darwin kernel patterns (steffen) -=> platform 1.0.4 - -2009-04-09 (bug fix)[26245326] [http::geturl] connection failures (golovan) -=> http 2.7.3 - -2009-04-10 (new feature) Darwin: embeddable CoreFoundation notifier (steffen) - -2009-04-10 (bug fix)[1961211] Darwin [load] back-compatibility (steffen) - -2009-04-09 (new feature) http chunked+gzip modes (thoyts) -=> http 2.8.0 - -2009-04-11 (enhancement) clarified cmd name resolution in oo forwards (fellows) - -20009-04-19 (bug fix)[2715421] http: excess bytes after POST (thoyts) -=> http 2.8.1 - -2009-04-30 (bug fix)[2486550] coroutine in [interp invokehidden] (sofer) - -2009-05-07 (bug fix)[2785893] find command in deleted namespace (sofer) - -2009-05-08 (bug fix)[2414858] tailcall in oo constructor (fellows) - -2009-05-14 (new subcommand)[TIP 354] [info object namespace] (fellows) - -2009-05-29 (platform support) account for ia64_32 (kupries) -=> platform 1.0.5 - -2009-06-02 (bug fix)[2798543] incorrect [expr] integer ** results (porter) - -2009-06-10 (bug fix)[2801413] overflow in [format] (porter) - -2009-06-13 (bug fix)[2802881] corrected compile env context (tasada,porter) - -2009-06-17 (redesign) reduced ambition of [exit] finalization with aim to -avoid otherwise very tricky multi-thread finalization bugs. (staplin,ferrieux) - *** POTENTIAL INCOMPATIBILITY for exit handlers *** - -2009-06-26 (platform support) updates for Xcode 3.1 & 3.2 (steffen) - -2009-06-30 (platform support) clang static analyzer macros (steffen) - -2009-07-01 (bug fix)[2806622] Win: bad tcl_platform(user) value (thoyts) - -2009-07-05 (bug fix) zlib support asynch [chan copy] on chan transform (fellows) - -2009-07-12 (bug fix)[1895546] TclOO support for Itcl 4 method caching (fellows) - -2009-07-13 (bug fix)[1605269] NR-related [info frame] fixes (kupries) - -2009-07-14 (bug fix)[2821401] NR-enable direct eval [switch] (kenny) - -2009-07-16 (bug fix)[2819200] underflow settings on MIPS systems (porter) - -2009-07-19 (interface)[TIP 354] new routine Tcl_GetObjectName() (fellows) - -2009-07-20 (performance) favor [string is] success cases over empty (fellows) - -2009-07-22 (interface) removed TclpPanic() routine (nijtmans) - -2009-07-23 (bug fix)[2820349] plug event leak in notifier (mistachkin) - -2009-07-24 (bug fix)[2826248] crash in Tcl_GetChannelHandle (sonnenburg,kupries) - -2009-07-31 (bug fix)[2830354] overflow in [format] (misch,porter) - -2009-08-06 (bug fix)[2827000] reflected channels can signal EGAIN (kupries) - -2009-08-12 (new feature)[TIP 353] Tcl_NRExprObj() (porter) - -2009-08-20 (bug fix)[2823276] NR-enable [if], [for], [while] (fellows) - -2009-08-20 (bug fix)[2806250] EIAS violation in ~foo pathnames (porter) - -2009-08-21 (bug fix)[2837800] [glob */foo] return ./~x/foo (porter) - -2009-08-24 (bug fix) nested event loop notifier w/TkAqua Cocoa (alaoui,steffen) - -2009-08-25 (bug fix) [info frame] account for continuation lines (kupries) - -2009-08-27 (bug fix)[2845535] overflows in [format] (porter) - -2009-09-01 (bug fix) improved error message in tcltest (porter) -=> tcltest 2.3.2 - -2009-09-11 (bug fix)[2849860] http handle "quoted" charset value (fellows) -=> http 2.7.4 - -2009-09-11 (enhancement)[2314561] [subst] now bytecompiled, NR-enabled (porter) - -2009-09-24 (new feature)[TIP 356] Tcl_NRSubstObj() (porter) - -2009-10-04 (bug fix)[2569449] Core Foundation memory bug in Tiger (steffen) - -2009-10-06 (bug fix) repair intrep loss in slave interp evaluations -introduced by first versions of the NRE conversion (nadkarni,porter) - -2009-10-06 (bug fix)[1941434] broken tclTomMath.h includes (porter) - -2009-10-07 (bug fix)[2871908] leaked hash table (mistachkin,kupries) - -2009-10-08 (bug fix)[2874678] bignum leak in [dict incr] (fellows) - -2009-10-17 (bug fix)[2629338] crash in var unset traces (raney,fellows) - -2009-10-19 (bug fix)[2107634] extend [read] and [gets] to Tcl string limits -(morrison,parker,porter) - -2009-10-21 (bug fix)[2882561] Haiku OS signal support (morrison,fellows) - -2009-10-22 (bug fix)[2883857] [my varname arr(index)] (boudaillier,fellows) - -2009-10-23 (bug fix) 0-length writes: spurious SIG_PIPE (teterin,kupries) - -2009-10-24 Broken DST applied EU rules to US zones (lehenbauer,kenny) - -2009-10-29 (bug fix)[2800740] halved bignum memory on 64-bit systems (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2009-11-05 (bug fix)[2854929] TM search path support in Safe Base (kupries) - -2009-11-05 (enhancement) rewrite of the Safe Base commands (kupries) - -2009-11-11 (bug fix)[2888099] [close] loses ENOSPC error (khomoutov,ferrieux) - -2009-11-11 (bug fix)[2891171] RFC 3986 compliance for ? in URL (nijtmans) -=> http 2.8.2 - -2009-11-12 (bug fix)[2895565] [fcopy -size] miscounts when converting encodings -(kupries) - -2009-11-16 (bug fix)[2891556] encoding finalization crash (mistachkin,ferrieux) - -2009-11-18 (bug fix)[2849797] consistent names for std chans (nijtmans,fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2009-11-19 (enhancement) [load]able Tcltest extension (nijtmans) - -2009-11-24 (bug fix)[2893771] [file stat] on Win locked files (thoyts) - -2009-11-24 (bug fix)[2903011] crash call destructor from constructor (fellows) - -2009-12-03 (bug fix)[2906841] Safe Base [glob ../*] fixes (fellows) - -2009-12-09 (bug fix)[2901998] consistent I/O buffering (ferrieux,kupries) - -2009-12-11 (bug fix)[2806407] NR-enabled coroutines (sofer) - -2009-12-16 (bug fix)[2913616] msgcat: improved safe interp support (fellows) -=> msgcat 1.4.3 - -2009-12-22 (bug fix)[2918962] [lsort -index -stride] crash (moore,fellows) - -2009-12-23 (bug fix)[2913625] [info script/nameof] in safe interps (fellows) - -2009-12-28 (bug fix)[2891362] enable time limit in child interps (fellows) - -2009-12-29 (bug fix)[2922555] [binary decode hex { }] crash (thoyts) - -2009-12-29 (bug fix)[2895741] enable min(), max() in safe interps (fellows) - -2009-12-30 (bug fix)[2824981] guard [unknown] against [set] undef (sofer) - -2010-01-05 (bug fix)[2918610] [file rootname] corruption (magerya,porter) - -2010-01-18 (bug fix)[2932421] less [format %s] shimmer (ferrieux) - -2010-01-18 (bug fix)[2918110] [chan postevent] crash (bron,kupries) - -2010-01-21 (bug fix)[2910748] NR-enable epoch fallback direct eval (sofer) - -2010-01-30 (enhancement) [unset] now bytecompiled (fellows) - -2010-02-01 (bug fix)[2942697] faster match: some pathological regexp patterns -(lane,fellows) - -2010-02-01 (bug fix)[2939073] [array unset] unset trace crash (ferrieux) - -2010-02-02 (bug fix)[2944404] crash in oo destructor (fellows) - -2010-02-02 (new feature) [array] is now a [namespace ensemble] (fellows) - -2010-02-05 (enhancement) [error] now bytecompiled (fellows) - -2010-02-08 (bug fix)[2947783] Tcl_Zlib*flate fail on shared values (fellows) - -2010-02-09 (enhancement) [try] now bytecompiled (fellows) - -2010-02-11 (bug fix)[2826551] line-sensitive matching in regexp (dejong) - -2010-02-11 (bug fix)[2949740] [open |noSuch rb] crash (kovalenko,fellows) - -2010-02-15 (bug fix)[2950259] harden (delete obj ns -> delete obj) (fellows) - -2010-02-21 (bug fix)[2954959] get sign of abs($zero) right (nijtmans) - -2010-02-22 (bug fix)[2762041] zlib chan transforms read EOF too early (kupries) - -2010-02-27 (bug fix)[801429] Tcl_SetMainLoop() thread safety (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2010-03-02 (enhancement) -fvisibility-hidden build support (nijtmans) - -2010-03-04 (bug fix)[2962664] [oo::class destroy] crash (fellows) - -2010-03-05 (interface) TclOO typedefs for function pointers (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2010-03-09 (bug fix)[2936225] stop [chan copy] to slow channel consuming all -memory with buffer backup (ferrieux) - -2010-03-17 (bug fix)[2921116] crash in chan transfrom teardown (kupries) - -2010-03-19 (enhancement) [throw] now bytecompiled (fellows) - -2010-03-20 (enhancement) permit [fcopy] of > 2**31 bytes (fellows) - -2010-03-24 (new feature) [info object methodtype] (fellows) - -2010-03-24 (bug fix)[2383005] [return -errorcode] reject non-list (porter) - -2010-03-25 (bug fix)[2976504] broken fstatfs() call (reeuwijk,fellows) - -2010-03-30 (new feature)[TIP 362] [registry -32bit|-64bit] (courtney,fellows) -=> registry 1.3 - -2010-03-30 (bug fix)[2978773] refchan mem preservation (kupries) - -2010-04-02 (new feature)[TIP 357] Tcl_LoadFile, Tcl_FindSymbol, etc. (kenny) - -2010-04-05 (configure change)[TIP 364] default build: --enable-threads (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2010-04-02 (new feature)[TIP 348] [info errorstack], [return -errorstack] -(ferrieux) - -2010-04-20 (enhancement) update bundled zlib to 1.2.5 (nijtmans) - -2010-04-29 (enhancement)[2992970] optimize bytearray appends (fellows) - -2010-05-19 (bug fix)[3004007] dict/list shimmer w/o string rep loss (fellows) - -2010-06-09 (bug fixes) platform: several fixes for 64 bit systems (kupries) -=> platform 1.0.9 - -2010-06-16 (bug fix)[3016135] [clock format] in he_IL locale (nijtmans) - -2010-06-18 (bug fix)[3017997] Add .cmd to file extensions for [exec] (fellows) - -2010-06-28 (bug fix)[3019634] support errno.h changes in MSVC++ 2010 (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2010-07-02 (enhancement) -errorcode for [expr] domain errors (fellows) - -2010-07-28 (bug fix)[3037525] crash deleting vars @ callframe pop (sofer) - -2010-08-04 (bug fix)[3034840] mem corrupt when refchan loses interp (kupries) - -2010-08-04 (enhancement) Win [load] use LOAD_WITH_ALTERED_SEARCH_PATH (hobbs) - -2010-08-04 (platform support) panic on detection of win9x system (hobbs) - *** POTENTIAL INCOMPATIBILITY *** - -2010-08-10 (fix) Handle non-null-terminated bytearrys in glob matching (hobbs) - -2010-08-11 (fix) copy-paste bug in [yield] implementation (sofer, goth) - -2010-08-11 (platform) Drop pre-aix 4.2 support, ldAix (hobbs) - -2010-08-14 (frq)[2819611] changed signatures of hash fnctions, delete-file, and get-native-path (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2010-08-15 (bug fix)[3045010] tweaked error message for wrong#args of lambda's (fellows) - -2010-08-18 (bug fix)[3004191] fixed safe [glob] (fellows) - -2010-08-21 (patch)[3034251] genStubs steal features of ttkGenStubs (nijtmans) - -2010-08-26 (bug fix)[1230554] configure, OSF-1 problems, windows manifest issues (hobbs) - -2010-08-30 (bug fix) [3046594,3047235,3048771] reimplemented tailcall (sofer) - -2010-08-31 fixed manifest handling on windows (hobbs, kupries) - -2010-08-31 windows makefile and stub changes (nijtmans) - -2010-09-01 (bug fix)[3057639] compiled lappend trace consistency (hobbs,kupries) - *** POTENTIAL INCOMPATIBILITY *** - -2010-09-01 fixed safe glob handling of -directory (kupries) - -2010-09-02 fixed safe glob handling of -join (kupries) - -2010-09-08 (bug fix)[3059922] build with mingw on amd64 (porter, mescalinum) - -2010-09-15 (bug fix)[3067036] stop hang in bytearray append (fellows) - -2010-09-22 unified set of link libraries between mingw and vc (nijtmans) - -2010-09-22 (bug fix)[3072640] protect writes to ::error* variables (sofer) - -2010-09-23 fix leak of return options [catch $err m constant] (porter, hobbs) - -2010-09-24 (bugfix)[3056775] fixed race condition in windows sockets (kupries) - -2010-09-24 (performance) string eq/cmp (hobbs) - -2010-09-26 (patch)[3072080] rewritten NRE core (sofer) - -2010-09-28 (new feature)[TIP 162] implementation of ipv6 sockets (max) - -2010-10-02 (bug fix)[3079830] properly invalidate string rep of dicts (fellows) - -2010-10-06 (bug fix)[3081065] fix writing to freed Tcl_Obj (porter) - -2010-10-08 fix in ipv6 code on windows (nijtmans) - -2010-10-09 fixed overallocation of execution stack (sofer) - -2010-10-11 windows unicode changes (nijtmans) - -2010-10-12 (bug fix)[3084338] fixed meamleak in ipv6 code (max) - -2010-10-13 (bug fix)[467523,983660] alt fix allows empty literal share (porter) - -2010-10-15 (bugfix)[3085863] updated unicode tables (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2010-10-16 refactored implementation of dict iteration (fellows) - -2010-10-17 (patch)[2995655] report inner contexts on error stack (ferrieux) - -2010-10-19 (bug fix)[3081008] fixed bytearray zlib interaction (fellows) - -2010-10-19 improved crc, appending to bytearray (fellows) - -2010-10-20 improved compilation of [dict for] (fellows) - -2010-10-26 Added private support to disable reverse dns (max) - -2010-10-26 Prevent crashes when querying socket options (fellows, max) - -2010-10-28 (bug fix)[3093120] prevent freeaddrinfo(NULL) (porter, virden) - -2010-10-29 (bug fix)[2905784] stop cycle waste in short [after] (ferrieux) - -2010-11-01 tzdata updated to Olson's tzdata2010o (kenny) - -2010-11-04 (bug fix)[3099086] Clarified docs of var substitution (fellows) - -2010-11-04 improved install targets (cassof) - -2010-11-04 improved testing of sockets (max) - -2010-11-05 (frq)[491789] setargv/unicode cmdline for MSVC (nijtmans) - -2010-11-09 (bug fix)[3105999] fixed memleak in OO var resolver (fellows) - -2010-11-15 (TIP 378)[3081184] improved TIP 280 performance (kupries) - -2010-11-16 (platform) VS 2005 SP1 MSVC compiler (nijtmans) - -2010-11-18 (bug fix)[3111059] leak in [namespace delete] w coroutines (sofer) - -2010-11-28 [3120139,3105247] Tcl_PrintDouble improvements (kenny) - -2010-11-29 (new cmd) [tcl::unsupported::inject] (ferrieux,sofer) - -2010-11-30 (enhancement) Restore TclFormatInt for performance (hobbs) - -2010-12-09 (new feature) [file] is now a [namespace ensemble] (fellows) - -2010-12-19 (bug fix) [fcopy -size 1 -command] asynchronous (ferrieux) - -2010-12-12 (platform) OpenBSD build improvements (cassoff) - -2010-12-17 (platform) Revisions to support rpm 4.4.2 (cassoff) - -2010-12-27 (bug fix) crash in [lsort] w multiple -index options (fellows) - -2010-12-30 (bug fix)[3142026] GrowEvaluationStack OBOE (harder,sofer) - -2011-01-18 (bug fix)[3001438] [info frame -1] crash (mccormack,fellows) - -2011-03-01 (performance)[3168398] optimize [interp cancel] (mistachkin) - -2011-03-05 (bug fix)[3185009] crash in OO variables (danckaert,fellows) - -2011-03-05 (new cmd) [tcl::unsupported::assemble] (ugurlu,kenny) - -2011-03-06 (bug fix)[3200987,3192636] parser buffer overruns (porter) - -2011-03-08 (bug fix)[3202905] failed intrep release of interp result (mccormack) - -2011-03-09 (bug fix)[3202171] repair [namespace inscope] optimizer (porter) - -2011-03-10 (new version) better tcltest reporting from child interps (fellows) -=> tcltest 2.3.3 - -2011-03-10 (new feature) [namespace] is now a [namespace ensemble] (fellows) - -2011-03-12 (interface) reduce casting by ckalloc(), ckfree() callers (fellows) - -2011-03-14 (bug fix) Fixes from libtommath 0.42.0 release (fellows) - -2011-03-21 (bug fix)[3216070] [load] extension from embed Tcl apps (nijtmans) - ***POTENTIAL INCOMPATIBILITY*** - -2011-03-27 (performance) NRE: LIST lset foreach benchmark (twylite) - -2011-04-11 (bug fix)[3282869] coroutine + eval + locals crash (ferrieux,sofer) - -2011-04-13 (bug fix)[2662380] crash when variable append trace unsets (sofer) - -2011-04-13 (bug fix)[3285375] Buffer overflow in [concat] (porter) - -2011-05-02 (internals change) revised TclFindElement() interface (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2011-05-05 (enhancement) dict->list w/o string rep generation (porter) - -2011-05-10 (bug fix)[3173086] Crash parsing long lists (rogers,porter) - -2011-05-24 (enhancement) msgcat internal improvements (fellows) -=> msgcat 1.4.4 - -2011-05-25 (TIP 381) [info object|class call] [self call] [nextto] (fellows) - -2011-05-31 (bug fix)[3293874] let lists grow all the way to the limit (porter) - -2011-06-02 (bug fix)[3185407] cmd resolution epoch flaw (nadkarni,fellows) - -2011-06-13 (bug fix)[3315098] mem leak generating double string rep (neumann) - -2011-06-22 (new feature) DEB_HOST_MULTIARCH support (kupries) -=> platform 1.0.10 - -2011-07-15 (bug fix)[3357771] Prevent circular refs in bytecode (porter) - -2011-07-28 tzdata updated to Olson's tzdata2011h (porter) - -2011-08-01 (bug fix)[3383616] memleak exposed by XOTcl (neumann,sofer) - -Many more Tcl built-in command errors now set an -errorcode. - ---- Released 8.6b2, August 8, 2011 - -2011-07-02 (bug fix)[3349507] correct double(1[string repeat 0 23]) (kenny) - -2011-07-19 (bug fix)[3371644] Tcl_ConvertElement() segfault (sader, ferrieux) - -2011-07-21 (bug fix)[3372130] hypot(.) segfault (nijtmans) - -2011-08-12 (bug fix)[3389764] memleaks due to reference cycles in dup'd paths - -2011-08-15 (bug fix)[3390272] leak of [info script] value (porter) - -2011-08-17 (bug fix)[3393150] bignum leaks in Tcl_Get*() routines (porter) - -2011-08-18 (bug fix)[3393714] [string toupper] overflow (nijtmans) - -2011-08-30 (bug fix)[3398794] panic in interp limit setting (gavlian,fellows) - -2011-09-08 (bug fix)[3401704] revised expr parser to permit function names -like "nano()" instead of parsing as "nan o()" with missing op (duquette,porter) - *** POTENTIAL INCOMPATIBILITY *** - -2011-09-10 (bug fix)[3400658] wrong num args msg with TclOO (rsooltan,fellows) - -2011-09-13 (bug fix)[3390638] solaris studio cc workaround (kechel,porter) - -2011-09-13 (bug fix)[3405652] DTrace workaround (michelson,porter) - -2011-09-16 (bug fix)[3391977] -headers overrides -type (ziegenhagen,fellows) -=> http 2.8.3 - -2011-09-16 (TIP 388) New \Uhhhhhhhh syntax (nijtmans) - -2011-10-06 (enhancement) bytecode compile [dict with] (fellows) - -2011-10-11 (bug fix)[2935503] [file stat] returns bad mode (nadkarni,nijtmans) - -2011-10-20 (bug fix)[3418547] cmd lits and custom resolvers (soberning,fellows) - -2011-10-31 (bug fix)[3414754] EIAS violation in fs paths (porter) - -2011-11-22 (bug fix)[3354324] Win: [file mtime] sets wrong time (nijtmans) - -2011-11-30 (bug fix)[967195] Simply args passed to child processes (nijtmans) -=> tcltest 2.3.4 - -2011-12-07 (bug fix)[3444754] fix [string tolower \u01C5] (nijtmans) - -2011-12-11 (update)[3457031] Update [[:print:]] to Unicode 6.0 (nijtmans) - -2011-12-24 (bug fix)[3464428] fix [string is graph \u0120] (nijtmans) - -2012-01-08 (bug fix)[3470928] zoneinfo trouble with Windhoek data file (kenny) - -2012-01-13 (bug fix)[3472316] fix retrieval of socket error (fellows) - -2012-01-21 (bug fix)[3475667] [regexp] buffer read overflow (sebres) - -2012-01-22 (bug fix)[3475264] [dict exists] return 0, not error (fellows) - -2012-01-25 (bug fix)[3474460] [oo::copy] var resolution list (fellows) - -2012-01-26 (bug fix)[3475569,3479689] mem corrupt in fs path (sebres,porter) - -2012-01-30 (enhancement) improve bytecode compile of [catch] (fellows) - -2012-02-02 (bug fix)[2974459,2879351,1951574,1852572,1661378,1613456] Fix -problems where [file *able] would return false results on Win/Samba (porter) - -2012-02-06 (bug fix)[3484621] bump bytecode epoch on exec traces (kuhn,sofer) - -2012-02-15 (bug fix)[3487626] crash compiling [dict for] (fellows) - -2012-02-15 (enhancement) bytecode compile [lrange],[lreplace] (fellows) - -2012-02-17 (bug fix)[2233954] compile problem on AIX & Android (nijtmans) - -2012-02-29 (bug fix)[3466099] BOM in Unicode (nijtmans) - -2012-03-07 (bug fix)[3498327] RFC 3986 compliance (kupries) - -2012-03-26 (TIP 380) New builtin class [oo::Slot] (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2012-03-27 (TIP 397) method to extend [oo::copy] (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2012-03-27 (TIP 395) New subcommand [string is entier] (fellows) - -2012-04-02 (TIP 396) New command [yieldto] (fellows) - -2012-04-04 (bug fix)[3514761] crash combining objects and ensembles (fellows) - -2012-04-09 (bug fix)[2712377] [info vars] and oo variables (fellows) - -2012-04-09 (bug fix)[3396896] no dups in oo var lists (fellows) - -2012-04-11 (bug fix)[3448512] [clock scan 1958-01-01] fail on Win (nijtmans) - -2012-04-15 (bug fix)[3517696] fix flush of zlib chan xform (fellows) - -2012-04-18 tzdata updated to Olson's tzdata2012c (kenny) - -2012-04-28 (TIP 398) exit non-blocking chan without flush (ferrieux) - *** POTENTIAL INCOMPATIBILITY *** - -2012-05-02 (enhancement) Better use of Intel cpuid instruction (nijtmans) - -2012-05-03 (bug fix)[3428753] Unbreak synchronous [socket -async] (porter) - -2012-05-10 (bug fix)[2812981] force consistent config of Tcl+pkgs (ferrieux) - -2012-05-10 (bug fix)[473946] correct send of special characters (nijtmans) - -2012-05-17 (bug fix)[3445787] fix [file] ensemble in Safe Base (fellows) - -2012-05-17 (bug fix)[2964715] fix [glob] in Safe Base (fellows) - -2012-05-17 (bug fix)[3106532] proper [switch -indexvar] values (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2012-05-21 (TIP 106) New -binary option to [dde execute|poke] (oehlmann) -=> dde 1.4.0 - -2012-05-23 (bug fix)[3525907] [zlib push decompress] & [chan event] -(fellows,ferrieux,kupries) - -2012-05-28 (bug fix)[3529949] Protect ~ paths in Safe Base (fellows) - -2012-06-21 (bug fix)[3362446] [registry keys] failure (nijtmans) -=> registry 1.3.0 - -2012-06-25 (bug fix)[3537605] [encoding dirs a b] error message (fellows) - -2012-06-25 (bug fix)[3024359] crash when multi-thread concurrent [file system] -and Tcl_FSMountsChanged(). (porter) - -2012-06-29 (bug fix)[3536888] fix locale guessing (oehlmann,nijtmans) - -2012-07-05 (bug fix)[1189293] make "<<" redirect binary safe (porter) - -2012-07-08 (bug fix)[3531209] accept IPv6 URLs (max) -=> http 2.8.4 - -2012-07-24 (bug fix) stop mem corruption in stacked channel events (max,porter) - -2012-07-25 (bug fix)[3546275] [auto_execok] search match [exec] (danckaert) - -2012-07-27 (update)[3464401] Support Unicode 6.2 (nijtmans) - -2012-08-20 (bug fix)[3559678] [file normalize] EIAS failure (phao,dgp) - -2012-08-25 (bug fix)[3561330] Ukranian translation of "March" (teterin) - -2012-09-07 (TIP 404) New msgcat commands [mcflset], [mcflmset] (oehlmann) -=> msgcat 1.5.0 - -Many revisions to better support a Cygwin environment (nijtmans) - -Dropped support for OS X versions less than 10.4 (Tiger) (fellows) - ---- Released 8.6b3, September 18, 2012 - -2012-09-20 (enhancement) full Unicode support (nijtmans) -=> dde 1.4.0 - -2012-09-20 (enhancement) update bundled zlib to 1.2.7 (nijtmans) - -2012-10-03 (bug fix) exit panic on stacked std channel (griffin,porter) - -2012-10-14 (bug fix) [tcl::Bgerror] crash on non-dict options (nijtmans) - -2012-10-16 (TIP 400) New [zlib] options to set compression dict (fellows) - -2012-10-16 (TIP 405) New commands [lmap] and [dict map] (fellows) - -2012-10-24 (enhancement) [dict unset] now bytecompiled (fellows) - -2012-11-05 (TIP 413) Revisions to default [string trim*] trimset (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2012-11-05 (enhancement) Now bytecompiled: [array exists], [array set], -[array unset], [dict create], [dict exists], [dict merge], [format], -[info commands], [info coroutine], [info level], [info object], -[namespace current], [namespace code], [namespace qualifiers], [namespace tail], -[namespace which], [regsub], [self], [string first], [string last], -[string map], [string range], [tailcall], [yield]. (fellows) - -2012-11-06 (bug fix)[3581754] avoid multiple callback on keep-alive (fellows) -=> http 2.8.5 - -2012-11-07 tzdata updated to Olson's tzdata2012i (kenny) - -2012-11-13 (bug fix)[3567063] thread fp settings from master (mistachkin) - -2012-11-14 (bug fix)[2933003] tempfile creation in $TMPDIR (fellows) - -2012-11-15 (TIP 416) New [load] options -global and -lazy (nijtmans) - -2012-11-20 (bug fix)[3033307] base64 trail whitespace (kovalenko,goth) - -2012-12-03 (bug fix) [configure] query broke init from argv (porter) -=> tcltest 2.3.5 - -2012-12-13 (bug fix)[3595576] crash: [catch {} -> noSuchNs::var] (sofer,porter) - -2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter) - ---- Released 8.6.0, December 20, 2012 - -2012-12-22 (bug fix)[3598150] DString to Tcl_Obj memleak (afredd) - -2012-12-27 (bug fix)[3598580] Tcl_ListObjReplace() refcount fix (nijtmans) - -2013-01-04 (bug fix) memleak in [format] compiler (fellows) - -2013-01-08 (bug fix)[3092089,3587096] [file normalize] on junction points - -2013-01-09 (bug fix)[3599395] status line processing (nijtmans) -2013-01-23 (bug fix)[2911139] repair async connection management (fellows) -=> http 2.8.6 - -2013-01-26 (bug fix)[3601804] Darwin segfault platformCPUID (nijtmans) - -2013-01-28 (enhancement) improve ensemble bytecode (fellows) - -2013-01-30 (enhancement) selected script code improvements (fradin) -=> tcltest 2.3.6 - -2013-01-30 (bug fix)[3599098] update to handle glibc banner changes (kupries) -=> platform 1.0.11 - -2013-01-31 (bug fix)[3598282] make install DESTDIR support (cassoff) - -2013-02-05 (bug fix)[3603434] [file normalize a:/] flaw in VFS (porter,griffin) - -2013-02-09 (bug fix)[3603695] $obj varname resolution rules (venable,fellows) - -2013-02-11 (bug fix)[3603553] zlib flushing errors (vampiera,fellows) - -2013-02-14 (bug fix)[3604576] msgcat use of Windows registry (oehlmann,nijtmans) -=> msgcat 1.5.1 - -2013-02-19 (bug fix)[2438181] report errors in trace handlers (yorick) - -2013-02-21 (bug fix)[3605447] unbreak [namespace export -clear] (porter) - -2013-02-23 (bug fix)[3599194] fallback IPv6 routines (afredd,max) - -2013-02-27 (bug fix)[3606139] stop crash in [regexp] (lane) - -2013-03-03 (bug fix)[3606258] major serial port update (english) - -2013-03-06 (bug fix)[3606683] [regexp (((((a)*)*)*)*)* {}] hangs -(grathwohl,lane,porter) - -2013-03-12 (enhancement) better build support for Debian arch (shadura) - -2013-03-19 (bug fix)[2893771] [file stat] on locked files (thoyts,nijtmans) - -2013-03-21 (bug fix)[2102614] [auto_mkindex] ensemble support (griffin) - -2013-03-27 Tcl_Zlib*() routines tolerate NULL interps (porter - -2013-04-04 (bug fix) Support URLs with query but no path (max) -=> http 2.8.7 - -2013-04-08 (bug fix)[3610026] regexp crash on color overflow (linnakangas) - -2013-04-29 (enhancement) [array set] compile improvement (fellows) - -2013-04-30 (enhancement) broaden glibc version detection (kupries) -=> platform 1.0.12 - -2013-05-06 (platform support) Cygwin64 (nijtmans) - -2013-05-15 (enhancement) Improved [list {*}...] compile (fellows) - -2013-05-16 (platform support) mingw-4.0 (nijtmans) - -2013-05-19 (platform support) FreeBSD updates (cerutti) - -2013-05-20 (bug fix)[3613567] access error temp file creation (keene) - -2013-05-20 (bug fix)[3613569] temp file open fail can crash [load] (keene) - -2013-05-22 (bug fix)[3613609] [lsort -nocase] failed on non-ASCII (fellows) - -2013-05-28 (bug fix)[3036566] Use language packs (Vista+) locale (oehlmann) -=> msgcat 1.5.2 - -2013-05-29 (bug fix)[3614102] [apply {{} {list [if 1]}}] stack woes (porter) - -2013-06-03 Restored lost performance appending to long strings (elby,porter) - -2013-06-05 (bug fix)[2835313] [while 1 {foo [continue]}] crash (fellows) - -2013-06-17 (bug fix)[a876646] [:cntrl:] includes \x00 to \x1F (nijtmans) - -2013-06-27 (bug fix)[983509] missing encodings for config values (nijtmans) - -2013-06-27 (bug fix)[34538b] apply DST in 2099 (lang) - -2013-07-02 (bug fix)[32afa6] corrected dirent64 check (griffin) - -2013-07-06 tzdata updated to Olson's tzdata2013d (kenny) - -2013-07-10 (bug fix)[86fb5e] [info frame] in compiled ensembles (porter) - -2013-07-18 (bug fix)[1c17fb] revisd syntax errorinfo that shows error (porter) - -2013-07-26 (bug fix)[6585b2] regexp {(\w).*?\1} abb (lane) - -2013-07-29 [string is space \u202f] => 1 (nijtmans) - -2013-08-01 [a0bc85] Limited support for fork with threads (for Rivet) (nijtmans) - -2013-08-01 (bug fix)[1905562] RE recursion limit increased to support -reported usage of large expressions (porter) - -2013-08-02 (bug fix)[9d6162] superclass slot empty crash (vdgoot,fellows) - -2013-08-03 (enhancement)[3611643] [auto_mkindex] support TclOO (fellows) - -2013-08-14 (bug fix)[a16752] Missing command delete callbacks (porter) - -2013-08-15 (bug fix)[3610404] reresolve traced forwards (porter) - -2013-08-15 Errors from execution traces become errors of the command (porter) - -2013-08-23 (bug fix)[8ff0cb9] Tcl_NR*Eval*() schedule only, as doc'd (porter) - -2013-08-29 (bug fix)[2486550] enable [interp invokehidden {} yield] (porter) - -2013-09-01 (bug fix)[b98fa55] [binary decode] fail on whitespace (reche,fellows) - -2013-09-07 (bug fix)[86ceb4] have tm path favor first provider (neumann,porter) - -2013-09-09 (bug fix)[3609693] copied object member variable confusion (fellows) -=> TclOO 1.0.1 - -2013-09-17 (bug fix)[2152292] [binary encode uuencode] corrected (fellows) - -2013-09-19 (bug fix)[3487626] segfaults in [dict] compilers (porter) - -2013-09-19 (bug fix)[31661d2] mem leak in [lreplace] (ade,porter) - -Many optmizations, improvements, and tightened stack management in bytecode. - ---- Released 8.6.1, September 20, 2013 --- https://core.tcl-lang.org/tcl/ for details - -2013-09-27 (enhancement) improved ::env synchronization (fellows) - -2013-10-20 (bug fix)[2835313] segfault from -[apply {{} {while 1 {a {*}[return -level 0 -code continue]}}}] (fellows) - -2013-10-22 (bug fix)[3556215] [scan %E%G%X] support (fellows) - -2013-10-25 (bug fix)[3eb2ec1] upper case scheme names in url. (nijtmans) -=> http 2.8.8 - -2013-10-29 (bug fix)[414d103] HP-UX: restore [exec] in threaded Tcl (nijtmans) - -2013-11-04 (bug fix) C++ friendly stubs struct declarations (nijtmans) - -2013-11-05 (bug fix)[426679e] OpenBSD man page rendering (nijtmans) - -2013-11-12 (bug fix)[5425f2c] [fconfigure -error] breaks [socket -async] - -2013-11-20 (bug fix) Improved environment variable management (nijtmans) -=> tcltest 2.3.7 - -2013-11-21 (platforms) Support for Windows 8.1 (nijtmans) - -2013-12-06 (RFE) improved [foreach] bytecode (fellows) - -2013-12-10 (RFE) improved [lmap] bytecode (sofer) - -2013-12-11 (RFE) improved [catch] bytecode (sofer) - -2013-12-18 (bug fix)[0b874c3] SEGV [coroutine X coroutine Y info frame] (porter) - -2013-12-20 (RFE) reduced numeric conversion in bytecode (sofer) - -2014-01-07 (RFE) compilers for [concat], [linsert], [namespace origin], -[next], [string replace], [string tolower], [string totitle], [string toupper], -[string trim], [string trimleft], [string trimright] (fellows) - -2014-01-22 (RFE) compilers for [nextto], [yieldto] (fellows) - -2014-02-02 (RFE) compiler for [string is] (fellows) - -2014-02-06 (bug fix)[a4494e2] panic in test namespace-13.2 (porter) - -2014-03-20 (bug fix)[2f7cbd0] FreeBSD 10.0 build failure (nijtmans) - -2014-03-26 (RFE)[b42b208] Cygwin: [file attr -readonly -archive -hidden -system] -(nijtmans) - -2014-03-27 (bug fix) segfault iocmd-23.11 (porter) - -2014-04-02 (bug fix)[581937a] Win: readable event on async connect failure - -2014-04-04 (bug fix)[581937a,97069ea] async socket connect fail (oehlmann) - -2014-04-10 (bug fix)[792641f] Win: no \ in normalized path (nijtmans) - -2014-04-11 (bug fix)[3118489] protect NUL in filenames (nijtmans) - -2014-04-15 (bug fix)[88aef05] segfault iocmd-21.20 (porter) - -2014-04-16 (update) Win: use Winsock 2.2 (nijtmans) - -2014-04-16 (bug fix)[d19a30d] segfault clock-67.[23] (sebres) - -2014-04-21 (bug fix) segfault iocmd-21.2[12] (porter) - -2014-04-22 (bug fix) segfault iogt-2.4 (porter) - -2014-04-23 (bug fix)[3493120] memleak in thread exit - -2014-05-08 refactoring of core I/O functions (porter) - -2014-05-09 (bug fix)[3389978] Win: extended paths support (nijtmans) - -2014-05-09 (bug fix) segfault iocmd-32.1 (porter) - -2014-05-11 (bug fix)[6d2f249] nested ensemble compile failure (fellows) - -2014-05-17 (RFE)[47d6625] wideint support in [lsearch -integer] [lsort -integer] (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2014-05-20 (bug fix) Stop eof and blocked state leaking thru stacks (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2014-05-20 (bug fix)[13d3af3] Win: socket -async tried only first IP address - -2014-05-28 (platforms) work around systems that fail when a shared library -is deleted after it is [load]ed (kupries) - -2014-05-31 (bug fix) chan events on pipes must be on proper ends (porter) - -2014-06-04 (bug fix) socket-2.12 (porter) - -2014-06-05 (bug fix) io-12.6 (kupries,porter) - -2014-06-15 (RFE)[1b0266d] [dict replace|remove] return canonical dict (fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2014-06-16 (bug fix) socket-2.13 workaround broken select() (porter) - -2014-06-20 (bug fix)[b47b176] iortrans.tf-11.0 (porter) - -2014-06-22 (RFE)[2f9df4c] -cleanup scripts before -out compare (nijtmans) - -2014-07-04 (update) Update Unicode data to 7.0 (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2014-07-08 (bug) [chan push] converts blocked writes to error (aspect,porter) - -2014-07-10 (bug fix)[7368d2] memleak Tcl_SetVar2(..,TCL_APPEND_VALUE) (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2014-07-11 (bug) leaks in SetFsPathFromAny, [info frame] (porter) - -2014-07-15 (bug) compress dict leak in zlib xform channel close (porter) - -2014-07-17 (bug fix)[9969cf8] leak trace data in coroutine deletion (porter) - -2014-07-18 (RFE)[b43f2b4] fix [lappend] multi performance collapse (fellows) - -2014-07-19 (bug fix)[75b8433] memleak managing oo instance lists (porter) - -2014-07-21 (bug fix)[e6477e1] memleak in AtForkChild() (porter) - -2014-07-22 (bug fix)[12b0997] memleak in iocmd.tf-32.0 (porter) - -2014-07-28 (RFE) Optimized binary [chan copy] by moving buffers (porter) - -2014-07-30 (enhancement) use refcounts, not Tcl_Preserve to manage lifetime -of Tcl_Channel (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2014-07-31 (bug fix)[a84a720] double free in oo chain deletion (porter) - -2014-08-01 (bug fix)[e75faba] SEGV [apply {{} {namespace upvar a b [x]}}] (porter) - -2014-08-01 (update) "macosx*-i386-x86_64" "macosx-universal" no longer compatible (kupries) -=> platform 1.0.13 - -2014-08-12 tzdata updated to Olson's tzdata2014f (kenny) - -2014-08-17 (bug fix)[7d52e11] [info class subclasses oo::object] should -include ::oo::class (fellows) - -2014-08-25 (TIP 429) New command [string cat] (leitgeb,ferrieux) - ---- Released 8.6.2, August 27, 2014 --- https://core.tcl-lang.org/tcl/ for details - -2014-08-28 (bug)[b9e1a3] Correct Method Search Order (nadkarni,fellows) -=> TclOO 1.0.3 - *** POTENTIAL INCOMPATIBILITY *** - -2014-09-05 (bug)[ccc2c2] Regression [lreplace {} 1 1] (bron,fellows) - -2014-09-08 (bug) Crash regression in [oo::class destroy] (porter) - -2014-09-09 (bug)[84af11] Regress [regsub -all {\(.*} a(b) {}] (fellows) - -2014-09-10 (bug)[cee90e] [try {} on ok {} - on return {} {}] panic (porter) - -2014-09-20 (feature) [tcl::unsupported::getbytecode] disassember (fellows) - -2014-09-27 (enhancement) [string cat] bytecode optimization (leitgeb,ferrieux) - -2014-09-27 (bug)[82521b] segfault in mangled bytecode (ogilvie,sofer) - -2014-10-02 (bug)[bc5b79] Hang in some [read]s of limited size (rogers,porter) - -2014-10-03 (bug)[bc1a96] segfault in [array set] of traced array (tab,porter) - -2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans) - -2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter) - -2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter) - -2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter) - -2014-10-26 Support for Windows 10 (nijtmans) - -2014-10-31 (bug)[dcc034] restore [open comX: r+] (lll,nijtmans) - -2014-11-05 (bug)[214cc0] Restore [lappend v] return value (sayers,porter) - -2014-11-06 (bug)[5adc35] Stop forcing EOF to be permanent (porter) - ---- Released 8.6.3, November 12, 2014 --- https://core.tcl-lang.org/tcl/ for details - -2014-11-21 (bug)[743338] Win: socket error encoding (ladayaroslav,nijtmans) - -2014-12-01 (bug) restore tbcload/tclcompiler support (kupries) - -2014-12-03 (bug)[0c043a] Fix compiled [set var($) val] (porter) - -2014-12-04 (bug)[d2ffcc] Limit $... and bareword parsing to ASCII (ladayaroslav,porter) - *** POTENTIAL INCOMPATIBILITY *** - -2014-12-06 (bug)[c6cd4a] Win: hang in async socket connection (shults,nadkarni) - -2014-12-10 tzdata updated to Olson's tzdata2014j (venkat) - -2014-12-13 fix header files installation on OS X (houben) - -2014-12-17 (TIP 427) [fconfigure $h -connecting, -peername, -sockname] (oehlmann,rmax) - -2014-12-18 (bug)[af08c8] Crash in full finalize encoding teardown (porter) - -2014-12-18 (bug)[7c187a] [chan copy] crash (io-53.17) (benno,porter) - -2015-01-26 (bug)[df0848] Trouble with INFINITY macro (dower,nijtmans) - -2015-01-29 (bug) Stop crashes when extension var resolvers misbehave (porter) - -2015-01-29 (bug)[088727] [read] past EOF (io-73.4) (fenugrec,porter) - -2015-02-11 tzdata updated to Olson's tzdata2015a (venkat) - -2015-02-20 (bug)[32b615] Fix compiled [lreplace] (lreplace-4.[345]) (aspect) - -2015-03-10 (enhancement) Revise OS X notifier for better Cocoa (walzer) - *** POTENTIAL INCOMPATIBILITY *** - ---- Released 8.6.4, March 12, 2015 --- https://core.tcl-lang.org/tcl/ for details - -2015-03-19 (bug)[e66e44] Win: Ctrl-C/Ctrl-Break in console not EOF (nadkarni) - -2015-03-21 (bug)[d87cb1] Proper tailcall from compiled ensembles (sofer) - -2015-04-23 (bug)[19ea02] Win: shared read from linked dirs (bogdan,oehhar) - -2015-04-24 (bug)[879a07] Incomplete chars @ buffer ends (leunissen,porter) - -2015-04-29 (bug)[894da1] Hang flushing blocking channels (yorick) - -2015-05-14 (enhance)[b9d043] Default use of gzip transfer encoding (fellows) -=> http 2.8.9 - *** POTENTIAL INCOMPATIBILITY *** - -2015-05-15 (bug)[9dd1bd] destructor [self] after failed constructor (calvo,fellows) - -2015-05-15 (bug)[0f42ff] [tailcall] combined with [next] (aspect,fellows) - -2015-05-18 (bug)[c11a51] http: race condition in -accept option (fellows) - -2015-05-19 (enhance) More pure lists from compiled [list] (porter,fellows) - -2015-05-27 (enhancement) Relax memdebug constraint on extensions (kupries) - -2015-06-03 (bug)[268b23] crash in traced [expr] (execute-11.2)(tomkinson,porter) - -2015-06-11 (bug)[478c44] Memleak in zlib compresion errors (mistachkin) - -2015-06-16 (bug)[e770d9] Higher baud on serial channels (woods,nijtmans) - -2015-06-18 (update) Update Unicode data to 8.0 (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2015-06-18 (bug)[a4cb3f] compiled [lreplace] handling of end (bron,aspect) - -2015-06-23 (enhance) Use Unicode SendMessageTimeout() (nijtmans) -=> registry 1.3.1 - -2015-06-25 (TIP 412) msgcat dynamic locale change and package private locale (oehlmann) -=> msgcat 1.6.0 - -2015-07-05 (bug)[a0ece9] crash in traced [expr] (execute-11.3) (hans,porter) - -2015-07-10 (TIP 436) [info object isa] favors 'false' over error (fellows) -=> TclOO 1.0.4 - -2015-07-15 (bug)[b1534b][9bad63] writes beyond buffer bounds (hanno,porter) - -2015-07-18 (bug)[a3309d] Memleak in compiled [unset a($i)] (jeff,porter) - -2015-07-23 (bug)[57945b] lock in forking/multi-threading (neumann,mistachkin) - -2015-07-29 (bug)[3e7eca] Allocation overflow in expr parsing (rickyb,porter) - -2015-07-30 (bug)[f00009] Win: Memleak in [file] (rp,sebres) - -2015-07-31 (bug) Correct problems found in Coverity audit (sofer) - -2015-08-19 (bug)[00189c] MSVC 14: semi-static UCRT support (dower,nijtmans) - -2015-08-26 (bug)[0df7a1] Tolerate getcwd() failures (cato,nijtmans) - -2015-09-21 (bug)[1115587][a3c350][d7ea9f][0e0e15][187d7f] Many fixes and -improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich) - -2015-09-23 (enhance) hash lookup microoptimization (hipp) - -2015-09-23 (bug)[e0a7b3] Input buffer draining & file events (griffin,porter) - -2015-09-29 (bug)[219866] Cygwin support error (yorick,nijtmans) -=> platform 1.0.14 - -2015-10-06 (bug)[b42a85] Win: [file normalize ~user] wrong dir (nadkarni) - -2015-10-21 (bug)[1080042][8f2450] More regexp from Postgres (lane,porter) - -2015-10-23 (bug)[4a0c16] [clock] react to msgcat locale change (oehlmann) - -2015-11-10 (bug)[261a8a] Overflow segfault in I/O translation (brooks,porter) - -2015-11-20 (bug)[40f628] ListObjReplace callers fail to detect max (porter) - -2015-11-30 (enhance)[32c574] Improve list growth performance (brooks,porter) - -2015-12-11 (bug)[c9eb6b] tolerate unset ::env(TZ) (gahr, nijtmans) - -2016-01-29 (TIP 440) tcl_platform(engine) -- Tcl implementation (mistachkin) - -2016-02-03 (bug)[25842c] stream [zlib deflate] fails with 0 input (ade,fellows) - -2016-02-04 (bug)[3d96b7][593baa][cf74de] crashes in OO teardown (porter,fellows) - -2016-02-22 (bug)[9b4702] [info exists env(missing)] kills trace (nijtmans) - ---- Released 8.6.5, February 29, 2016 --- https://core.tcl-lang.org/tcl/ for details - -2016-03-01 (bug)[803042] mem leak due to reference cycle (porter) - -2016-03-08 (bug)[bbc304] reflected watch race condition (porter) - -2016-03-17 (bug)[fadc99] compile-5.3 (rodriguez,porter) - -2016-03-17 (enhancement)[1a25fd] compile [variable ${ns}::v] (porter) - -2016-03-20 (bug)[1af8de] crash in compiled [string replace] (harder,fellows) - -2016-03-21 (bug)[d30718] segv in notifier finalize (hirofumi,nijtmans) - -2016-03-23 (enhancement)[7d0db7] parallel make (yarda,nijtmans) - -2016-03-23 [f12535] enable test bindings customization (vogel,nijtmans) - -2016-04-04 (bug)[47ac84] compiled [lreplace] fixes (aspect,ferrieux,fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2016-04-08 (bug)[866368] RE \w includes 'Punctuation Connector' (nijtmans) - -2016-04-08 (bug)[2538f3] Win crash Tcl_OpenTcpServer() (griffin) - -2016-04-10 [07d13d] Restore TclBlend support lost in 8.6.1 (buratti) - -2016-05-13 (bug)[3154ea] Mem corruption in assembler exceptions (tkob,kenny) - -2016-05-13 (bug) registry package support any Unicode env (nijtmans) -=> registry 1.3.2 - -2016-05-21 (bug)[f7d4e] [namespace delete] performance (fellows) - -2016-06-02 (TIP 447) execution time verbosity option (cerutti) -=> tcltest 2.4.0 - -2016-06-16 (bug)[16828b] crash due to [vwait] trace undo fail (dah,porter) - -2016-06-16 (enhancement)[4b61af] good [info frame] from more cases (beric) - -2016-06-21 (bug)[c383eb] crash in [glob -path a] (oehlmann,porter) - -2016-06-21 (update) Update Unicode data to 9.0 (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2016-06-22 (bug)[16896d] Tcl_DString tolerate append to self. (dah,porter) - -2016-06-23 (bug)[d55322] crash in [dict update] (yorick,fellows) - -2016-06-27 (bug)[dd260a] crash in [chan configure -dictionary] (madden,aspect) - -2016-07-02 (bug)[f961d7] usage message with parameters with spaces (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2016-07-02 (enhancement)[09fabc] Sort order of -relateddir (lanam) - -2016-07-07 (bug)[5d7ca0] Win: [file executable] for .cmd and .ps1 (nadkarni) - *** POTENTIAL INCOMPATIBILITY *** - -2016-07-08 (bug)[a47641] [file normalize] & Windows junctions (nadkarni) - -2016-07-09 [ae61a6] [file] handling of Win hard-coded names (CON) (nadkarni) - *** POTENTIAL INCOMPATIBILITY *** - -2016-07-09 [3613671] [file owned] (more) useful on Win (nadkarni) - -2016-07-09 (bug)[1493a4] [namespace upvar] use of resolvers (beric,fellows) - *** POTENTIAL INCOMPATIBILITY *** - -2016-07-10 (bug)[da340d] integer division in clock math (nadkarni) - -2016-07-20 tzdata updated to Olson's tzdata2016f (venkat) - ---- Released 8.6.6, July 27, 2016 --- https://core.tcl-lang.org/tcl/ for details - -2016-09-07 (bug)[c09edf] Bad caching with custom resolver (neumann,nijtmans) - -2016-09-07 (bug)[4dbdd9] Memleak in test var-8.3 (mr_calvin,porter) - -2016-10-03 (bug)[2bf561] Allow empty command as alias target (yorick,nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2016-10-04 (bug)[4d5ae7] Crash in async connects host no address (gahr,fellows) - -2016-10-08 (bug)[838e99] treat application/xml as text (gahr,fellows) -=> http 2.8.10 - -2016-10-11 (bug)[3cc1d9] Thread finalization crash in zippy (neumann) - -2016-10-12 (bug)[be003d] Fix [scan 0x1 %b], [scan 0x1 %o] (porter) - -2016-10-14 (bug)[eb6b68] Fix stringComp-14.5 (porter) - -2016-10-30 (bug)[b26e38] Fix zlib-7.8 (fellows) - -2016-10-30 (bug)[1ae129] Fix memleak in [history] destruction (fellows) - -2016-11-04 (feature) Provisional Tcl 9 support in msgcat and tcltest (nijtmans) -=> msgcat 1.6.1 -=> tcltest 2.4.1 - -2016-11-04 (bug)[824752] Crash in Tcl_ListObjReplace() (gahr,porter) - -2016-11-11 (bug)[79614f] invalidate VFS mounts on sytem encoding change (yorick) - -2016-11-14 OSX: End panic() as legacy support macro; system conflicts (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2016-11-15 (bug) TclOO fix stops crash mixing Itcl and snit (fellows) - -2016-11-17 (update) Reconcile libtommath updates; purge unused files (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2017-01-09 (bug)[b87ad7] Repair drifts in timer clock (sebres) - -2017-01-17 (update) => zlib 1.2.11 (nijtmans) - -2017-01-31 (bug)[39f630] Revise Tcl_LinkVar to tolerate some prefixes (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2017-02-01 (bug)[d0f7ba] Improper NAN optimization. expr-22.1[01] (aspect) - -2017-02-26 (bug)[25842c] zlib stream finalization (aspect) - -2017-03-07 (deprecate) Remove unmaintained makefile.bc file (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2017-03-14 (enhancement) [clock] and [encoding] are now ensembles (kenny) - -2017-03-15 (enhancement) several [clock] subcommands bytecoded (kenny) - -2017-03-23 tzdata updated to Olson's tzdata2017b (jima) - -2017-03-29 (bug)[900cb0] Fix OO unexport introspection (napier) - -2017-04-12 (bug)[42202b] Nesting imbalance in coro injection (nadkarni,sebres) - -2017-04-18 (bug)[bc4322] http package support for safe interps (nash,nijtmans) - -2017-04-28 (bug)[f34cf8] [file join a //b] => /b (neumann,porter) - -2017-05-01 (bug)[8bd13f] Windows threads and pipes (sebres,nijtmans) - -2017-05-01 (bug)[f9fe90] [file join //a b] EIAS violation (aspect,porter) - -2017-05-04 (bug) Make test filesystem-1.52 pass on Windows (nijtmans) - -2017-05-05 (bug)[601522] [binary] field spec overflow -> segfault (porter) - -2017-05-08 (bug)[6ca52a] http memleak handling keep-alive (aspect,nijtmans) -=> http 2.8.11 - -2017-05-29 (bug)[a3fb33] crash in [lsort] on long lists (sebres) - -2017-06-05 (bug)[67aa9a] Tcl_UtfToUniChar() revised handling invalid UTF-8 (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2017-06-08 (bug)[2738427] Tcl_NumUtfChars() corner case utf-4.9 (nijtmans) - -2017-06-22 (update) Update Unicode data to 10.0 (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2017-06-22 (TIP 473) Let [oo::copy] specify target namespace (fellows) - -2017-06-26 (bug)[46f801] Repair autoloader fragility (porter) - -2017-07-06 (bug)[adb198] Plug memleak in TclJoinPath (sebres,porter) - -2017-07-17 (bug)[fb2208] Repeatable tclIndex generation (wiedemann,nijtmans) - ---- Released 8.6.7, August 9, 2017 --- https://core.tcl-lang.org/tcl/ for details - -Changes to 8.7a1 include all changes to the 8.6 line through 8.6.7, -plus the following, which focuses on the high-level feature changes -in this changeset (new minor version) rather than bug fixes: - -2016-03-17 (bug)[0b8c38] socket accept callbacks always in global ns (porter) - *** POTENTIAL INCOMPATIBILITY *** - -2016-07-01 Hack accommodations for legacy Itcl 3 disabled (porter) - -2016-07-12 Make TCL_HASH_TYPE build-time configurable (nijtmans) - -2016-07-19 (bug)[0363f0] Partial array search ID reform (porter) - -2016-07-19 (feature removed) Tcl_ObjType "array search" unregistered (porter) - *** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("array search") *** - -2016-10-04 Server socket on port 0 chooses port supporting IPv4 * IPv6 (max) - -2016-11-25 [array names -regexp] supports backrefs (goth) - -2017-01-04 (TIP 456) New routine Tcl_OpenTcpServerEx() (limeboy) - -2017-01-04 (TIP 459) New subcommand [package files] (nijtmans) - -2017-01-16 threaded allocator initialization repair (vasiljevic,nijtmans) - -2017-01-30 Add to Win shell builtins: assoc ftype move (ashok) - -2017-03-31 TCL_MEM_DEBUG facilities better support 64-bit memory (nijtmans) - -2017-04-13 \u escaped content in msg files converted to true utf-8 (nijtmans) - -2017-05-18 (TIP 458) New epoll or kqueue notifiers are default (alborboz) - -2017-05-31 Purge build support for SunOS-4.* (stu) - -2017-06-22 (TIP 463) New option [regsub ... -command ...] (fellows) - -2017-06-22 (TIP 470) Tcl_GetDefineContextObject();[oo::define [self]] (fellows) -=> TclOO 1.2.0 - -2017-06-23 (TIP 472) Support 0d as prefix of decimal numbers (iyer,griffin) - -2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann) - -2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter) - ---- Released 8.7a1, September 8, 2017 --- https://core.tcl-lang.org/tcl/ for details - -2017-08-10 [array names -regexp] supports backrefs (goth) - -2017-08-10 Fix gcc build failures due to #pragma placement (cassoff,fellows) - -2017-08-29 (bug)[b50fb2] exec redir append stdout and stderr to file (coulter) - -2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann) -=> http 2.8.12 - -2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter) - -2017-10-19 (bug)[1a5655] [info * methods] includes mixins (fellows) - -2017-10-23 tzdata updated to Olson's tzdata2017c (jima) - -2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows) - -2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS (werner) - -2017-11-08 (bug)[3298012] Stop crash when hash tables overflow 32 bits (porter) - -2017-11-14 (bug)[5d6de6] Close failing case of [package prefer stable] (kupries) - -2017-11-17 (bug)[fab924] Fix misleading [load] message on Windows (oehlmann) - -2017-12-05 (bug)[4f6a1e] Crash when ensemble map and list are same (sebres) - -2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter) - -2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni) - -2017-12-19 (bug)[586e71] EvalObjv exception handling at level #0 (sebres,porter) - ---- Released 8.6.8, December 22, 2017 --- https://core.tcl-lang.org/tcl/ for details - -2018-02-11 (enhance) stop blocking conversion of object to/from class (coulter) - -2018-02-12 (enhance) NR-enable [package require] (coulter) - -2018-02-14 (bug)[9fd5c6] crash in object deletion, test oo-11.5 (coulter) - -2018-02-14 (bug)[3c32a3] crash deleting object with class mixed in (coulter) - -2018-02-15 (platform) stop using -lieee, removed from glibc-2.27 (porter) -***POTENTIAL INCOMPATIBILITY for math programs that embed Tcl*** - -2018-02-23 (bug)[8e6a9a] bad binary [string match], test string-11.55 (porter) - -2018-03-05 (bug)[1873ea] repair multi-thread std channel init (sebres) - -2018-03-09 (bug)[db36fa] broken bytecode for index values (porter) - -2018-03-13 (bug) broken compiled [string replace], test string-14.19 (porter) - -2018-03-14 (bug) [string trim*] engine crashed on invalid UTF (sebres) - -2018-04-17 (bug) missing trace in compiled [array set], test var-20.11 (porter) - -2018-04-22 (bug)[46a241] crash in unset array with search, var-13.[23] (goth) - -2018-04-30 (bug)[27b682] race made [file delete] raise "no such file" (sebres) - -2018-06-04 (bug)[925643] 32/64 cleanup of filesystem DIR operations (sebres) - -2018-06-18 (bug) leaks in TclSetEnv and env cache (coulter) - -2018-06-24 (bug)[3592747] [yieldto] dying namespace, tailcall-14.1 (coulter) - -2018-07-09 (bug)[270f78] race in [file mkdir] (sebres) - -2018-07-12 (bug)[3f7af0] [file delete] raised "permission denied" (sebres) - -2018-07-26 (bug)[d051b7] overflow crash in [format] (sebres) - -2018-08-29 revised quoting of [exec] args in generated command line (sebres) -***POTENTIAL INCOMPATIBILITY*** - -2018-09-20 HTTP Keep-Alive with pipelined requests (nash) -=> http 2.9.0 - -2018-09-27 (new)[TIP 505] [lreplace] accepts all out of range indices (porter) - -2018-10-04 (bug) Prevent crash from NULL keyName (nijtmans) -=> registry 1.3.3 - -2018-10-26 (enhance) advance dde version (nijtmans) -=> dde 1.4.1 - -2018-10-27 tzdata updated to Olson's tzdata2018g (jima) - -2018-10-29 Update tcltest package for Travis support (fellows) -=> tcltest 2.5.0 - -2018-11-09 (bug)[35a8f1] overlong string length of some lists (owens) - -2018-11-16 (bug)[00d04c] Repair [binary encode base64] (sebres) - -- Released 8.6.9, November 16, 2018 - details at https://core.tcl-lang.org/tcl/ - - -2018-11-22 (bug)[7a9dc5] [file normalize ~/~foo] segfault (sebres) - -2018-12-30 (bug)[3cf3a9] variable 'timezone' deprecated in vc2017 (nijtmans) - -2019-01-09 (bug)[cc1e91] [list [list {*}[set a " "]]] regression (sebres) - -2019-02-01 (bug)[e3f481] tests var-1.2[01] (sebres) - -2019-03-01 (new) Update to Unicode 12.0 (nijtmans) - -2019-03-05 (new)[TIP 527] New command [timerate] (sebres) - -2019-03-08 (bug)[39fed4] [package require] memory validity (hume,porter) - -2019-04-23 (new) New command tcl::unsupported::corotype (fellows) - -2019-05-04 (bug) memlink when namespace deletion kills linked var (porter) - -2019-05-28 (new) README file converted to README.md in Markdown (nijtmans) - -2019-06-17 (bug)[8b9854] [info level 0] regression with ensembles (porter) - -2019-06-20 (bug)[6bdadf] crash multi-arg write-traced [lappend] (fellows,porter) - -2019-06-21 (bug)[f8a33c] crash Tcl_Exit before init (brooks,sebres) - -2019-08-27 (bug)[fa6bf3] Bytecode fails epoch recovery at numLevel=0 (sebres) - -2019-08-29 (bug)[fec0c1] C stack overflow compiling bytecode (ade,sebres) - -2019-09-12 tzdata updated to Olson's tzdata2019c (jima) - -2019-09-20 (new) registry/dde no longer need -DUNICODE (nijtmans) -=> registry 1.3.4 -=> dde 1.4.2 - -2019-10-02 (bug)[16768d] Fix [info hostname] on NetBSD (rytaro) - -2019-10-23 (new) libtommath updated to release 1.2.0 (nijtmans) - -2019-10-25 OSX: system Tcl deprecated. End default use of its packages. (walzer) - -2019-10-28 (bug)[bcd100] bad fs cache when system encoding changes (coulter) - -2019-11-15 (bug)[135804] segfault in [next] after destroy (coulter,sebres) - -2019-11-18 (bug)[13657a] application/json us text, not binary (noe,nijtmans) -=> http 2.9.1 - -- Released 8.6.10, Nov 21, 2019 - details at https://core.tcl-lang.org/tcl/ - - -Changes to 8.7a3 include all changes to the 8.6 line through 8.6.10, -plus the following, which focuses on the high-level feature changes -in this changeset (new minor version) rather than bug fixes: - -2017-11-01 (bug)[3c32a3] crash deleting class mixed into instance (coulter) - -2017-11-03 [TIP 345] eliminate the encoding 'identity' (porter) - -2017-11-04 (bug)[0d902e] [string first] on ASCII stored as Unicode (fellows) - -2017-11-17 [TIP 422] Mark all Tcl_*VA() routines deprecated. (nijtmans) - -2017-11-20 (support) Ended use of the obsolete values.h header (culler) - -2017-11-30 (bug)[8e1e31] [lsort] ordering of U+0000 (nijtmans) - -2017-12-07 [TIP 487] Terminate support for pre-XP Windows (nijtmans) - -2017-12-08 [TIP 477] Reform of nmake build (nadkarni) - -2017-12-20 (bug)[ba1419] Crash: complex ensemble delete, namespace-7.8 (coulter) - -2018-01-17 [TIP 485] Removal of many deprecated features (nijtmans) - -2018-01-27 (bug) Crash in [join $l $l], join-4.1 (porter) - -2018-02-06 [TIP 493] Cease Distribution of http 1.0 (porter) - -2018-02-06 [TIP 484] internal rep for native ints are all 64-bit (nijtmans) - -2018-02-14 [TIP 476] Scan/Printf consistency (nijtmans) - -2018-03-05 [TIP 351] [lsearch] striding - -2018-03-05 [TIPs 330,336] tighten access to Interp fields (porter) - -2018-03-12 [TIP 462] [::tcl::process] - -2018-03-12 [TIP 490] add oo support for msgcat => msgcat 1.7.0 (oehlmann) - -2018-03-12 [TIP 499] custom locale preference list (oehlmann) -=> msgcat 1.7.0 - -2018-03-20 [TIP 503] End CONST84 support for Tcl 8.3 (porter) - -2018-03-30 Refactored [lrange] (spjuth) - -2018-04-20 [TIP 389] Unicode beyond BMP (nijtmans) - -2018-04-20 [TIP 421] [array for] - -2018-05-11 [TIP 425] Windows panic callback use of UTF-8 - -2018-05-17 [TIP 491] Phase out --disable-threads support - -2018-06-03 [TIP 500] TclOO Private Methods and Variables - -2018-07-26 (bug)[ba921a] [string cat] of bytearrays (coulter,porter) - -2018-09-02 [TIP 478] Many new features in TclOO (lester,fellows) - -2018-09-04 (bug)[540bed] [binary format w] from bignum (nijtmans) - -2018-09-12 [TIP 430] zipfs and embedded script library (woods) - -2018-09-26 [TIP 508] [array default] (bonnet,fellows) - -2018-09-27 [TIP 515] level value reform (nijtmans) - -2018-09-27 [TIP 516] More OO slot operations (fellows) - -2018-09-27 [TIP 426] [info cmdtype] (fellows) - -2018-09-28 [TIP 509] Cross platform reentrant mutex - -2018-10-08 [TIP 514] native integers are 64-bit - -2018-10-12 [TIP 502] index value reform (porter) - -2018-11-06 [TIP 406] http cookies (fellows) - -2018-11-06 [TIP 445] Tcl_ObjType utilities (migrate to Tcl 9) (porter) - -2018-11-06 [TIP 501] [string is dict] - -2018-11-06 [TIP 519] inline export/unexport option for [oo::define] - -2018-11-06 [TIP 523] [lpop] - -2018-11-06 [TIP 524] TclOO custom dialects - -2018-11-06 [TIP 506] Tcl_(Incr|Decr)RefCount macros -> functions (porter) - -2018-11-15 [TIP 512] No stub for Tcl_SetExitProc() - -2019-04-08 (bug)[45b9fa] crash in [try] (coulter) - -2019-04-14 [TIP 160] terminal and serial channel controls - -2019-04-14 [TIP 312] more types for Tcl_LinkVar - -2019-04-14 [TIP 367] [lremove] - -2019-04-14 [TIP 504] [string insert] - -2019-04-16 [TIP 342] [dict getwithdefault] - -2019-04-23 (bug)[67a5ea] make [chan postevent] asynchronous - *** POTENTIAL INCOMPATIBILITY *** - -2019-05-25 [TIP 431] [file tempdir] - -2019-05-25 [TIP 383] [coroinject], [coroprobe] - -2019-05-31 [TIP 544] Tcl_GetIntForIndex() - -2019-06-12 Replace TclOffset() with offsetof() - -2019-06-15 [TIP 461] string compare operators for [expr] - -2019-06-16 [TIP 521] floating point classification functions for [expr] - -2019-06-20 (bug)[6bdadf] crash multi-arg traced [lappend] (fellows) - -2019-06-28 [TIP 547] New encodings utf-16, ucs-2 - -2019-09-14 [TIP 414] Tcl_InitSubsystems() - -2019-09-14 [TIP 548] wchar_t conversion functions - -- Released 8.7a3, Nov 21, 2019 --- https://core.tcl-lang.org/tcl/ for details - - -2019-12-03 (bug)[3cd9be] Corner case in surrogate handling (nijtmans) - -2019-12-09 (new) Add tcltest::(Setup|Eval|Cleanup|)Test (coulter,sebres) -=> tcltest 2.5.2 - -2019-12-12 (new) Add 3 libtommath functions to stub table (nijtmans) - -2019-12-23 (bug)[ce3b9f] compilation errors with clang, windows msys2 (nijtmans) - -2019-12-27 (bug)[1de6b0] [expr 1e2147483648] => 0.0 (kbk) - -2020-01-04 (bug)[912886] tis-620 encoding fails to load (coulter) - -2020-01-13 (bug)[0b9332] Win: support system encoding init to utf-8 (jedlička) - -2020-01-17 (bug)[8cd2fe] [unload] corrupted list of loaded packages (berc) - -2020-01-17 (bug)[5d989f] segfault in lsort for large list length (sebres) - -2020-01-30 (bug) Reset WSAGetLastError()/errno in channel close (nijtmans) - -2020-02-17 (bug) Win: avoid create of legacy error-vars on init phase (sebres) - -2020-02-25 (bug) release refs when setting class's superclasses fails (dkf) - -2020-02-26 (bug) C++ compiler compatibility for registry and dde (nijtmans) -=> registry 1.3.5 -=> dde 1.4.3 - -2020-03-05 (new) Update to Unicode-13 (nijtmans) - -2020-03-16 (bug)[8f89e2] Win: env var encoding, env-2.5 (sebres, nijtmans) - -2020-03-27 (bug)[767e07] Tcl_Get(Range|UniChar) validate index inputs (nijtmans) - -2020-03-28 (bug)[8edfce] [binary encode base64] & multi-byte wrapchars (dgp) - -2020-03-28 (bug)[ffeb20] [binary decode base64] ignore invalid chars (dgp) -See RFC 2045 - *** POTENTIAL INCOMPATIBILITY *** - -2020-03-31 (bug)[b8e82d] some -maxlen values break uuencode round trip (dgp) - *** POTENTIAL INCOMPATIBILITY *** - -2020-04-01 (bug)[f58371] Fileevent run in proper thread (bron,sebres) - -2020-04-13 (bug)[afa4b2] TclNeedSpace bug; tests util-8.5 .. util-8.11 (dgp) - -2020-04-13 (bug)[085913] Tcl_DStringAppendElement # quoting precision (dgp) - *** POTENTIAL INCOMPATIBILITY *** - -2020-04-13 (bug)[a7f685] test util-5.52 (dgp) - -2020-04-13 (bug)[c61818] Tcl_UtfPrev regression (dgp) - -2020-04-15 (bug)[8af92d] zlib transform issue, bad inflate (sebres) - -2020-04-16 (bug)[5e6346] Tcl_UtfPrev handling of overlong sequences (dgp) - -2020-04-27 (bug)[45ca23] [string tolower] inconsistency (dgp) - -2020-04-30 (bug)[da2352] init [info hostname] with DNS, not NetBIOS (nadkarni) - -2020-05-11 (bug)[d402ff] Win32 potential crash when using main() (werner) - -2020-05-13 (bug)[81242a] revised documentation for Tcl_UtfAtIndex() (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2020-05-13 (bug)[ed2980] Tcl_UtfToUniChar reads > TCL_UTF_MAX bytes (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2020-06-02 (bug) prevent segfault in parser (sebres) - -2020-06-21 (bug)[f81bec] http POST a binary file (alakendu,nash) -=> http 2.9.2 - -2020-06-23 (bug)[41c985] auto_path nonsense in Safe Base (nash) - -2020-06-24 (bug)[f70ce1] zlib multi-stream inflate acts only on first (sebres) - -2020-07-09 (bug)[a1bd37] [clock scan] new ISO format (clock-34.(19-24)) (sebres) - *** POTENTIAL INCOMPATIBILITY *** - -2020-07-10 (bug)[501974] [clock scan] +time zone (clock-34.(53-68)) (sebres) - *** POTENTIAL INCOMPATIBILITY *** - -2020-07-15 (bug)[3c6e47] compiled [lappend] performance, avoid copy (sebres) - -2020-07-16 (bug)[5bbd04] Fix index underflow (schwab) - -2020-07-27 (bug)[cb0373] http::geturl -keepalive fixes (nash) -=> http 2.9.3 - -2020-08-10 (bug)[29e884] cmd resolution cycle (namespace-57.0) (coulter,sebres) - -2020-08-12 (bug)[e87000] Tcl_BadChannelOption tolerate NULL (werner,nijtmans) - -2020-08-31 (TIP #581) disfavor Master/Slave terminology (nijtmans) -=> opt 0.4.8 - -2020-09-11 (bug)[3bc0f4] UBSan complains about body.chars[] usage (nijtmans) - -2020-09-17 (bug)[835c93] Support TIP 525 exit code for -singleproc 1 (nijtmans) -=> tcltest 2.5.3 - -2020-09-25 (new) force -eofchar \x1A when evaluating library scripts (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2020-09-29 (bug)[0063cb] http::geturl -headers must be dict (oehlmann,nijtmans) - -2020-10-19 (bug)[cb4582] Update install-sh script (stu,nijtmans) - -2020-10-22 (bug)[c97593] Usage of gnu_printf in latest mingw-w64 (nijtmans) - -2020-10-26 (new)[48898a] improve error message consistency (stu) - *** POTENTIAL INCOMPATIBILITY *** - -2020-11-06 (new) revised case of module names (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2020-12-10 (bug)[ed5be7] Win: recognize "comx:" as serial port (oehlmann) - -2020-12-11 (new) support for msys2, Big Sur (nijtmans) -=> platform 1.0.15 - -2020-12-23 tzdata updated to Olson's tzdata2020e (jima) - -- Released 8.6.11, Dec 31, 2020 - details at https://core.tcl-lang.org/tcl/ - - -Changes to 8.7a5 include all changes to the 8.6 line through 8.6.11, -plus the following, which focuses on the high-level feature changes -in this changeset (new minor version) rather than bug fixes: - -2019-12-13 [TIP 538] Externalize libtommath - -2020-01-20 [TIP 542] Support for switchable Full Unicode support - -2020-01-21 [TIP 543] Eliminate `TCL_INTERP_DESTROYED` flag value - -2020-01-24 [TIP 559] Eliminate public routine `Tcl_FreeResult - -2020-01-31 (new) Implement 64-bit seek on Zip channels. (nijtmans) - -2020-02-28 [TIP 557] C++ support for Tcl - -2020-02-28 [TIP 562] Deprecate channel types 1-4 - -2020-03-11 (bug)[234d6c] Segfault in [set l {}; lpop l] (sebres) - -2020-03-12 (bug) Crash in tests binary-79.[12] (porter) - -2020-03-13 [TIP 569] Eliminate Comments That Serve Lint - -2020-04-06 (bug)[dd010c] [string trim*] on astral characters (porter,nijtmans) - -2020-05-30 [TIP 551] Permit underscore in numerical literals in source code - -2020-07-03 [TIP 578] Death to TCL_DBGX - -2020-08-11 (bug)[e87000] Win32 crash in [fconfigure stdout] (werner,nijtmans) - -2020-09-06 (bug)[c1a376] deletion trace on imported ensemble (coulter) - -2020-09-13 [TIP 585] Promote the INDEX_TEMP_TABLE flag of Tcl_GetIndexFromObj*() to the public interface - -2020-09-15 (bug)[b5777d] crash in [string index abcd 0-0x10000000000000000] - -2020-09-19 [b9ecf3] revised stork mgmt [uplevel [list $cmd ...]] (coulter) - -2020-10-23 [TIP 587] Default utf-8 for source command - -2020-10-27 (bug)[11229b] test string-31.26.* (porter) - -2020-11-08 [TIP 582] Comments in Expressions - -2020-11-16 [TIP 586] C String Parsing Support for binary scan - -2020-12-07 [TIP 590] Recommend lowercase Package Names - -2021-01-06 Bump to tcltest 2.5.4 - -2021-01-15 [TIP 481] `Tcl_GetStringFromObj()` with `size_t` length parameter - -2021-01-15 [TIP 592] End support: Windows XP, Server 2003, Vista, Server 2008 - -2021-01-25 tzdata updated to Olson's tzdata2021a (nijtmans) - -2021-01-29 (bug)[113be1] zipfs on mac - -2021-03-15 [TIP 575] Switchable Tcl_UtfCharComplete()/Tcl_UtfNext()/Tcl_UtfPrev() - -2021-03-19 (new)[0221b9] Drop TCL_WINDOW_EVENTS from Tcl's [update idletasks] - -2021-03-30 (new)[4b4830] [chan truncate] for reflected channels - -2021-04-30 [TIP 597] "string is unicode" and better utf-8/utf-16/cesu-8 encodings - -2021-04-09 [TIP 598] export TclWinConvertError - -2021-05-15 (bug)[463b7a] segfault from Tcl_Unload (coulter) - -2021-05-15 (bug)[fb2a41] tclZipfs.c free all memory (coulter) - -2021-05-18 (bug)[688fcc,28027d] namespace teardown reform (coulter) - -- Released 8.7a5, Jun 18, 2021 --- https://core.tcl-lang.org/tcl/ for details - - -2021-02-02 (new) support for MacOS Big Sur updates (nijtmans) -=> platform 1.0.17 - -2021-02-15 (bug)[d43f96] [string trim*] broken for Emoji (werner) - -2021-02-16 (bug)[22324b] [string reverse] broken for Emoji (werner) - -2021-02-19 (bug)[1dab71,7c64aa] BRE broken by uninitialized value use (lane) - -2021-03-09 (bug)[8419c5] Unix tty channels tolerate EINTR (nijtmans) - *** POTENTIAL INCOMPATIBILITY *** - -2021-03-10 (bug)[4c591f] [string compare] EIAS violation (nijtmans) - -2021-04-08 (new) dde package installation compatible with Tcl 9 (nijtmans) -=> dde 1.4.4 - -2021-04-14 (bug)[266494] [concat foo [list #]] EIAS violation (porter) - -2021-05-03 (bug)[24b918] Save IO buffers from modern optimizers (rupprecht) - -2021-05-06 (new) support for POSIX error EILSEQ (nijtmans) - -2021-05-17 (bug)[688fcc] segfault during traced delete of alias (coulter) - -2021-06-22 (bug)[bad6cc] More secure build tool. CVE-2021-35331 (nijtmans) - -2021-07-17 (bug)[592a25] Win: segfault in Tcl_PutEnv() (danckaert,nijtmans) - -2021-09-02 (bug)[ccc448] segfault in ensemble rewrite machinery (coulter) - -2021-09-14 (new) Update to Unicode-14 (nijtmans) - -2021-10-08 (bug)[a8579d] failed proc argument spec processing (russell,coulter) - -2021-10-27 (new) support for MacOS Monterey (nijtmans) -=> platform 1.0.18 - -2021-10-27 tzdata updated to Olson's tzdata2021e (nijtmans) - -- Released 8.6.12, Nov 5, 2021 - details at https://core.tcl-lang.org/tcl/ - - -2021-12-08 (update) tcltest package to version 2.5.4 - -2022-01-13 (bug)[26f132] Crash when sizeof(int) < sizeof(void *) (Plan 9 port) - -2022-01-19 (TIP 623)[e9a271] Tcl_GetRange index args < 0 (petasis,nijtmans) - -2022-03-08 (bug) test string-5.22 (porter) - -2022-03-11 (bug)[8a7ec8] fat binary compile on Mac M1 (davis, nijtmans) - -2022-04-04 (bug)[e5ed1b] numeric IPv6 in URLs (nijtmans) -=> http 2.9.6 - -2022-04-26 (bug)[27520c] test error-9.6 (goth,sebres) - -2022-05-04 (bug)[8eb64b] http package tolerant again invalid reply header - -2022-05-11 (bug)[6898f9] http package failed detection of shiftjis charset - -2022-05-25 (bug)[76ad7a] tests string-6.13[23] (mistachkin, nijtmans) - -2022-06-20 (bug)[55bf73] Avoid connection reuse after response code 101. -=> http 2.9.8 - -2022-07-22 (bug)[713653] FP rounding exposed by x86 musl (rubicon,sebres) - -2022-07-22 More portable notation of microseconds in verbose output (sebres) -=> tcltest 2.5.5 - -2022-07-27 (bug)[b3977d] Process CR-LF split across packets (nadkarni,sebres) - -2022-07-29 (bug)[4eb3a1] crash due to undetected bytecode invalidity (nadkarni) - -2022-08-23 (new)[371080] Portability to CHERI-enabled Morello processor (jrtc27) - -2022-09-06 (bug)[55a02f] Fallback init env(HOME) from USERPROFILE (nadkarni) - -2022-09-13 (bug)[1073da] crash writing invalid utf-8 (nijtmans) - -2022-09-14 (new) Update to Unicode-15 (nijtmans) - -2022-10-14 tzdata updated to Olson's tzdata2022e (nijtmans) - -Update bundled zlib to 1.2.13 - -Update bundled libtommath - -Many code fixes to avoid overflow or undefined behavior. Thanks chrstphrchvz. - -- Released 8.6.13, Nov 22, 2022 - details at https://core.tcl-lang.org/tcl/ - - -2022-12-01 Backport TIP #402: path name starting with '//' not - replaced by '/' also on Cygwin and QNX (nijtmans) - -2022-12-12 Windows binaries licence metadata changed to University of - California to match licence (nadkarni) - -2022-12-16 check mknod, tcdrain and uname in build script for VxWorks or others - (nijtmans) - -2022-12-16 32-bit cygwin is dead, so --enable-64bit in a Cygwin build no longer - needed (nijtmans) - -2023-01-01 (bug)[8e811b] Wrong formatting of arguments in man page (nijtmans) - -2023-01-06 (bug) [0f19ed]: Windows 11 not reported in tcl_platform(osVersion) - (nijtmans) - -2023-01-15 (bug) [8f7fde] string compare failing on big endian (coulter) - -2023-01-22 (bug) [3e8074] y2k38 problem in [interp limit time -seconds] - (nijtmans) - -2023-01-22 (bug) [e3dcab] crash with tcl_precision equal 15..18 (kenny) - -2023-02-22 (bug) [d19fe0] output replacement character on incomplete sequences - in unicode encoding (nijtmans) - -2023-02-22 (bug) [534172] sporadic crash in memchan thread cleanup. - (neumann,nijtmans) - -2023-02-28 (bug) [f9eafc] throw error in zip command when file comment/filename - to long or not iso-latin-1 (nijtmans) - -2023-03-04 (bug) [1b8df1] fix usec on windows returned by Tcl_GetTime (nadkarni) - -2023-03-05 (bug) [9c5a00]. Fix ~ and ~user path prefix on Windows (nadkarni) - -2023-03-13 (bug)[183a1a] Prevent BO by Tcl_UtfToExternal (nadkarni) - -2023-03-14 (bug) [ea69b0], crash when using a channel transformation on TCP - client socket (coulter) - -2023-03-22 (bug)[026575] Prevent invalid read in Tcl_UtfToUniChar (nijtmans) - -2023-03-30 (rfe) Allow empty mode in [chan create] to allow refchan version of - [socket -server] (max) - -2023-03-30 [0cb355] macOS 13 SDK deprecates sprintf() (chavez) - -2023-05-02 (bug) [ab123c] argument position overflow in [scan %num$mode] - (nadkarni) - -2023-05-02 (bug) [784bef] tailcall crash (nadkarni) - -2023-06-03 (bug) [af3ebc] clock scan and clock add bugs in error cases / with - abbreviated options (ade) - -2023-07-05 (bug) [66ffaf] incomplete double byte encoding sequences ignored like - in [encoding convertfrom gb12345 x] (nadkarni) - -2023-07-26 (rfe) [c54e4a] fork multithreading performance by using vfork/spawn - when supported (neumann) - -2023-08-29 Update zlib to version 1.3 (nijtmans) - -2023-09-04 Update libtommath to version 1.2.1 (nijtmans) - -2023-09-05 (bug) [60cacf] Fix tclvfs tkt Segmentation Fault at interpreter exit - when tclvfs loaded. -2023-09-05 (bug) [b5ac3e] Tcl_GetUniChar reads beyond string length for ASCII - strings (nadkarni) - -2023-09-06 (bug) [d3465c] Update install-sh to version 2020-11-14.01 (nijtmans) - -2023-09-08 Unicode 15.1 (nijtmans) - -2023-09-12 Remove option utf16 from win/makefile.vc (nijtmans) - -2023-09-13 (bug) [43b065] MS Windows: files with emojis are found by glob but - not recognized by file exists or open (nijtmans) - -2023-09-13 (bug) [a1f11d] VC6 compilation error of core-8-6-branch: error C2065: - 'int16_t' : undeclared identifier (nijtmans) - -2023-09-14 (bug) [00655c] ClockGetdatefieldsObjCmd(): avoid signed integer - overflow and platform-dependent behavior (nijtmans) - -2023-09-28 TIP #662: Tcl_VarEval is not depreciated any more (nijtmans) - -2023-10-01 (bug) [7b3167] tclOO.c: initialize fakeObject.refCount (nijtmans) - -2023-10-04 (bug) [7371b6] AddressSanitizer use-after-return detection breaks NRE - tests, coroutines (nijtmans) - -2023-11-20 (bug)[32b889] prevent spurious errors from [clock format] (gahr) - -2023-11-30 (bug) [fb2fa9],[21b062] reallow [exec %var%] on MS-Windows. It was - forbidden in 8.6.13 (brester) - -2023-12-30 (rfe) [0ac9d0] Don't call getsockname(2) in Tcl_MakeFileChannel(3) - unless absolutely necessary. Permits better constraining of Tcl/tclsh - via OpenBSD's pledge(2) or similar mechanisms. Minor rewrite. - -2024-01-09 (feature) Adapt tcltest to support Tcl 9. -=> tcltest 2.5.7 - -2024-01-11 (bug) [fd27ad] doc change of Tcl_PkgRequire & friends: version string - specification refers to "package require". - -2024-01-27 (bug) [16e25e] error for [tcl_startOfPreviousWord string end-1] - (nijtmans) - -2024-01-29 Update to zlib 1.3.1 (nijtmans) - -2024-01-29 [db4f28] segfault when Tcl_ReadChars is called with unicode object - (brester) - -2024-02-04 tzdata updated to Olson's tzdata2024a (nijtmans) - -2024-02-05 fix/document Tcl_ObjPrintf with "ll" modifier (nijtmans) - -2024-02-06 [8e666d] endless loop when redefining proc ::history (nash) - -2024-02-06 [86b3c1] endless loop when ::unknown is moved into a namespace (nash) - -- Released 8.6.14, Feb 28, 2024 - details at https://core.tcl-lang.org/tcl/ - diff --git a/changes.md b/changes.md new file mode 100644 index 0000000..30404ce --- /dev/null +++ b/changes.md @@ -0,0 +1 @@ +TODO \ No newline at end of file -- cgit v0.12 From a29edba9d99d840edebd02a927a8f79e3bec29d4 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 17 Apr 2024 13:06:53 +0000 Subject: Fix "make dist" --- macosx/Tcl.xcodeproj/project.pbxproj | 4 ++-- unix/Makefile.in | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/macosx/Tcl.xcodeproj/project.pbxproj b/macosx/Tcl.xcodeproj/project.pbxproj index ebc614a..5a6bc01 100644 --- a/macosx/Tcl.xcodeproj/project.pbxproj +++ b/macosx/Tcl.xcodeproj/project.pbxproj @@ -223,7 +223,7 @@ F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = ""; }; F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; - F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = ""; }; + F96D3DFB08F272A4004A47F5 /* changes.md */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes.md; sourceTree = ""; }; F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = ""; }; F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = ""; }; F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = ""; }; @@ -948,7 +948,7 @@ F96D3DFC08F272A4004A47F5 /* doc */, F96D43D008F272B8004A47F5 /* tools */, F9183E690EFC81560030B814 /* pkgs */, - F96D3DFB08F272A4004A47F5 /* changes */, + F96D3DFB08F272A4004A47F5 /* changes.md */, F96D434308F272B5004A47F5 /* README.md */, F96D432B08F272B4004A47F5 /* license.terms */, ); diff --git a/unix/Makefile.in b/unix/Makefile.in index 9249178..1d7c0cc 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -2294,7 +2294,7 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in gen $(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.decls $(DISTDIR)/generic $(DIST_INSTALL_DATA) $(GENERIC_DIR)/README $(DISTDIR)/generic $(DIST_INSTALL_DATA) $(GENERIC_DIR)/tclGetDate.y $(DISTDIR)/generic - $(DIST_INSTALL_DATA) $(TOP_DIR)/changes $(TOP_DIR)/README.md \ + $(DIST_INSTALL_DATA) $(TOP_DIR)/changes.md $(TOP_DIR)/README.md \ $(TOP_DIR)/license.terms $(DISTDIR) $(INSTALL_DATA_DIR) $(DISTDIR)/library $(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \ -- cgit v0.12 From 1e3aa26eff8e0529a7cd7f5afdb05b25f554cb92 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 17 Apr 2024 14:55:31 +0000 Subject: restore backwards compatibility (see clock-44.3) - spaces between tokens are optional, repaired greedy search (minLen), which find start next token or space now; it is also more consistent than old engine now (covered by clock-44.4) --- generic/tclClockFmt.c | 60 ++++++++++++++++++++++++++++++++++----------------- tests/clock.test | 8 ++++++- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index ac5bb84..a616074 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -28,6 +28,10 @@ TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */ static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss); static void ClockFrmScnFinalize(void *); +#ifndef TCL_CLOCK_FULL_COMPAT +#define TCL_CLOCK_FULL_COMPAT 1 +#endif + /* * Derivation of tclStringHashKeyType with another allocEntryProc */ @@ -1018,7 +1022,8 @@ static const char * FindTokenBegin( const char *p, const char *end, - ClockScanToken *tok) + ClockScanToken *tok, + int flags) { if (p < end) { char c; @@ -1027,15 +1032,19 @@ FindTokenBegin( switch (tok->map->type) { case CTOKT_INT: case CTOKT_WIDE: - /* should match at least one digit */ - while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} + if (!(flags & CLF_STRICT)) { + /* should match at least one digit or space */ + while (!isdigit(UCHAR(*p)) && !isspace(UCHAR(*p)) && + (p = Tcl_UtfNext(p)) < end) {} + } else { + /* should match at least one digit */ + while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} + } return p; case CTOKT_WORD: c = *(tok->tokWord.start); - /* should match at least to the first char of this word */ - while (*p != c && (p = Tcl_UtfNext(p)) < end) {} - return p; + goto findChar; case CTOKT_SPACE: while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} @@ -1043,7 +1052,15 @@ FindTokenBegin( case CTOKT_CHAR: c = *((char *)tok->map->data); - while (*p != c && (p = Tcl_UtfNext(p)) < end) {} +findChar: + if (!(flags & CLF_STRICT)) { + /* should match the char or space */ + while (*p != c && !isspace(UCHAR(*p)) && + (p = Tcl_UtfNext(p)) < end) {} + } else { + /* should match the char */ + while (*p != c && (p = Tcl_UtfNext(p)) < end) {} + } return p; } } @@ -1068,6 +1085,7 @@ FindTokenBegin( static void DetermineGreedySearchLen( + ClockFmtScnCmdArgs *opts, DateInfo *info, ClockScanToken *tok, int *minLenPtr, @@ -1082,7 +1100,8 @@ DetermineGreedySearchLen( if ((tok + 1)->map) { end -= tok->endDistance + yySpaceCount; /* find position of next known token */ - p = FindTokenBegin(p, end, tok + 1); + p = FindTokenBegin(p, end, tok + 1, + TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT); if (p < end) { minLen = p - yyInput; } @@ -1133,7 +1152,8 @@ DetermineGreedySearchLen( /* try to find laTok between [lookAhMin, lookAhMax] */ while (minLen < maxLen) { - const char *f = FindTokenBegin(p, end, laTok); + const char *f = FindTokenBegin(p, end, laTok, + TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT); /* if found (not below lookAhMax) */ if (f < end) { break; @@ -1517,7 +1537,7 @@ ClockScnToken_Month_Proc( int minLen, maxLen; TclStrIdxTree *idxTree; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); /* get or create tree in msgcat dict */ @@ -1549,7 +1569,7 @@ ClockScnToken_DayOfWeek_Proc( char curTok = *tok->tokWord.start; TclStrIdxTree *idxTree; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); /* %u %w %Ou %Ow */ if (curTok != 'a' && curTok != 'A' @@ -1620,7 +1640,7 @@ ClockScnToken_amPmInd_Proc( int minLen, maxLen; Tcl_Obj *amPmObj[2]; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); amPmObj[0] = ClockMCGet(opts, MCLIT_AM); amPmObj[1] = ClockMCGet(opts, MCLIT_PM); @@ -1655,7 +1675,7 @@ ClockScnToken_LocaleERA_Proc( int minLen, maxLen; Tcl_Obj *eraObj[6]; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); eraObj[0] = ClockMCGet(opts, MCLIT_BCE); eraObj[1] = ClockMCGet(opts, MCLIT_CE); @@ -1692,7 +1712,7 @@ ClockScnToken_LocaleListMatcher_Proc( int minLen, maxLen; TclStrIdxTree *idxTree; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); /* get or create tree in msgcat dict */ @@ -1715,7 +1735,7 @@ ClockScnToken_LocaleListMatcher_Proc( static int ClockScnToken_JDN_Proc( - TCL_UNUSED(ClockFmtScnCmdArgs *), + ClockFmtScnCmdArgs *opts, DateInfo *info, ClockScanToken *tok) { @@ -1724,7 +1744,7 @@ ClockScnToken_JDN_Proc( Tcl_WideInt intJD; int fractJD = 0, fractJDDiv = 1; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); end = yyInput + maxLen; @@ -1795,7 +1815,7 @@ ClockScnToken_TimeZone_Proc( const char *p = yyInput; Tcl_Obj *tzObjStor = NULL; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); /* numeric timezone */ if (*p == '+' || *p == '-') { @@ -1878,7 +1898,7 @@ ClockScnToken_TimeZone_Proc( static int ClockScnToken_StarDate_Proc( - TCL_UNUSED(ClockFmtScnCmdArgs *), + ClockFmtScnCmdArgs *opts, DateInfo *info, ClockScanToken *tok) { @@ -1887,7 +1907,7 @@ ClockScnToken_StarDate_Proc( int year, fractYear, fractDayDiv, fractDay; static const char *stardatePref = "stardate "; - DetermineGreedySearchLen(info, tok, &minLen, &maxLen); + DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen); end = yyInput + maxLen; @@ -2435,7 +2455,7 @@ ClockScan( } } - DetermineGreedySearchLen(info, tok, &minLen, &size); + DetermineGreedySearchLen(opts, info, tok, &minLen, &size); if (size < map->minSize) { /* missing input -> error */ diff --git a/tests/clock.test b/tests/clock.test index dec7b87..8072a68 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -37039,12 +37039,18 @@ test clock-44.2 {regression test - time zone containing only two digits} \ } \ -result 482134530 -test clock-44.3 {regression test - spaces between some scan tokens are optional} \ +test clock-44.3 {regression test - spaces between some scan tokens are optional (TCL_CLOCK_FULL_COMPAT, no-strict only)} \ -body { list [clock scan {9 Apr 2024} -format {%d %b%Y} -gmt 1] \ [clock scan {Tue, 9 Apr 2024 00:00:00 +0000} -format {%a, %d %b%Y %H:%M:%S %Z} -gmt 1] } \ -result {1712620800 1712620800} +test clock-44.4 {regression test - spaces between all scan tokens are optional (TCL_CLOCK_FULL_COMPAT, no-strict only)} \ + -body { + list [clock scan {9 Apr 2024} -format {%d%b%Y} -gmt 1] \ + [clock scan {Tue, 9 Apr 2024 00:00:00 +0000} -format {%a,%d%b%Y%H:%M:%S%Z} -gmt 1] + } \ + -result {1712620800 1712620800} test clock-45.1 {compat: scan regression on spaces (multiple spaces in format)} \ -body { -- cgit v0.12 From def527584228071c5ed89db69899100fa35440f0 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 17 Apr 2024 15:13:00 +0000 Subject: cherrypick [b73516f7cfccbc9f] to 8.7 - closes [167e0635db]: solves leaks, valgrind test, etc --- generic/tclClock.c | 52 ++++++++++++++++++++++++++++++++++++++++----------- generic/tclClockFmt.c | 14 +++++++------- generic/tclDate.h | 1 + 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 64bf57f..667cfbe 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -115,6 +115,7 @@ static struct tm * ThreadSafeLocalTime(const time_t *); static size_t TzsetIfNecessary(void); static void ClockDeleteCmdProc(void *); static Tcl_ObjCmdProc ClockSafeCatchCmd; +static void ClockFinalize(void *); /* * Structure containing description of "native" clock commands to create. */ @@ -180,6 +181,15 @@ TclClockInit( ClockClientData *data; int i; + static int initialized = 0; /* global clock engine initialized (in process) */ + /* + * Register handler to finalize clock on exit. + */ + if (!initialized) { + Tcl_CreateExitHandler(ClockFinalize, NULL); + initialized = 1; + } + /* * Safe interps get [::clock] as alias to a parent, so do not need their * own copies of the support routines. @@ -352,12 +362,14 @@ ClockDeleteCmdProc( for (i = 0; i < MCLIT__END; ++i) { Tcl_DecrRefCount(data->mcLiterals[i]); } + ckfree(data->mcLiterals); data->mcLiterals = NULL; } if (data->mcLitIdxs != NULL) { for (i = 0; i < MCLIT__END; ++i) { Tcl_DecrRefCount(data->mcLitIdxs[i]); } + ckfree(data->mcLitIdxs); data->mcLitIdxs = NULL; } @@ -4638,20 +4650,25 @@ ClockSafeCatchCmd( #endif #define TZ_INIT_MARKER ((WCHAR *) INT2PTR(-1)) +typedef struct ClockTzStatic { + WCHAR *was; /* Previous value of TZ. */ +#if TCL_MAJOR_VERSION > 8 + long long lastRefresh; /* Used for latency before next refresh. */ +#else + long lastRefresh; /* Used for latency before next refresh. */ +#endif + size_t epoch; /* Epoch, signals that TZ changed. */ + size_t envEpoch; /* Last env epoch, for faster signaling, + * that TZ changed via TCL */ +} ClockTzStatic; +static ClockTzStatic tz = { /* Global timezone info; protected by + * clockMutex.*/ + TZ_INIT_MARKER, 0, 0, 0 +}; + static size_t TzsetIfNecessary(void) { - typedef struct ClockTzStatic { - WCHAR *was; /* Previous value of TZ. */ - long lastRefresh; /* Used for latency before next refresh. */ - size_t epoch; /* Epoch, signals that TZ changed. */ - size_t envEpoch; /* Last env epoch, for faster signaling, - * that TZ changed via TCL */ - } ClockTzStatic; - static ClockTzStatic tz = { /* Global timezone info; protected by - * clockMutex.*/ - TZ_INIT_MARKER, 0, 0, 0 - }; const WCHAR *tzNow; /* Current value of TZ. */ Tcl_Time now; /* Current time. */ size_t epoch; /* The tz.epoch that the TZ was read at. */ @@ -4701,6 +4718,19 @@ TzsetIfNecessary(void) return epoch; } +static void +ClockFinalize( + TCL_UNUSED(void *)) +{ + ClockFrmScnFinalize(); + + if (tz.was && tz.was != TZ_INIT_MARKER) { + ckfree(tz.was); + } + + Tcl_MutexFinalize(&clockMutex); +} + /* * Local Variables: * mode: c diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index a616074..154c8ee 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -26,7 +26,6 @@ static void ClockFmtObj_UpdateString(Tcl_Obj *objPtr); TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */ static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss); -static void ClockFrmScnFinalize(void *); #ifndef TCL_CLOCK_FULL_COMPAT #define TCL_CLOCK_FULL_COMPAT 1 @@ -681,7 +680,7 @@ ClockFmtObj_FreeInternalRep( Tcl_Obj *objPtr) { ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr); - if (fss != NULL) { + if (fss != NULL && initialized) { Tcl_MutexLock(&ClockFmtMutex); /* decrement object reference count of format/scan storage */ if (--fss->objRefCount <= 0) { @@ -835,7 +834,6 @@ FindOrCreateFmtScnStorage( &ClockFmtScnStorageHashKeyType); initialized = 1; - Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL); } /* get or create entry (and alocate storage) */ @@ -3560,10 +3558,12 @@ ClockFrmScnClearCaches(void) Tcl_MutexUnlock(&ClockFmtMutex); } -static void -ClockFrmScnFinalize( - TCL_UNUSED(void *)) +void +ClockFrmScnFinalize() { + if (!initialized) { + return; + } Tcl_MutexLock(&ClockFmtMutex); #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 /* clear GC */ @@ -3572,8 +3572,8 @@ ClockFrmScnFinalize( ClockFmtScnStorage_GC.count = 0; #endif if (initialized) { - Tcl_DeleteHashTable(&FmtScnHashTable); initialized = 0; + Tcl_DeleteHashTable(&FmtScnHashTable); } Tcl_MutexUnlock(&ClockFmtMutex); Tcl_MutexFinalize(&ClockFmtMutex); diff --git a/generic/tclDate.h b/generic/tclDate.h index 1657528..fea7cbd 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -560,5 +560,6 @@ MODULE_SCOPE int ClockScan(DateInfo *info, Tcl_Obj *strObj, MODULE_SCOPE int ClockFormat(DateFormat *dateFmt, ClockFmtScnCmdArgs *opts); MODULE_SCOPE void ClockFrmScnClearCaches(void); +MODULE_SCOPE void ClockFrmScnFinalize(); #endif /* _TCLCLOCK_H */ -- cgit v0.12 From 035c656deee62635905513440a2f92a17539f911 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 17 Apr 2024 15:35:10 +0000 Subject: This fits on a single line (as in 9.0) --- generic/tclClock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 667cfbe..c0fe59a 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -4699,8 +4699,7 @@ TzsetIfNecessary(void) if (tz.was != NULL && tz.was != TZ_INIT_MARKER) { ckfree(tz.was); } - tz.was = (WCHAR *) - ckalloc(sizeof(WCHAR) * (wcslen(tzNow) + 1)); + tz.was = (WCHAR *)ckalloc(sizeof(WCHAR) * (wcslen(tzNow) + 1)); wcscpy(tz.was, tzNow); epoch = ++tz.epoch; } else if (tzNow == NULL && tz.was != NULL) { -- cgit v0.12 From c328fea7bcbb0f03db0df119e301586847bf3250 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 17 Apr 2024 15:42:12 +0000 Subject: Add pkgs8 directories to git/fossil ignore files --- .fossil-settings/ignore-glob | 2 ++ .gitignore | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.fossil-settings/ignore-glob b/.fossil-settings/ignore-glob index 656e184..1fa4a73 100644 --- a/.fossil-settings/ignore-glob +++ b/.fossil-settings/ignore-glob @@ -60,10 +60,12 @@ unix/tcl.pc unix/tclIndex unix/Tcl-Info.plist unix/Tclsh-Info.plist +unix/pkgs8/* unix/pkgs/* win/Debug* win/Release* win/*.manifest +win/pkgs8/* win/pkgs/* win/coffbase.txt win/tcl.hpj diff --git a/.gitignore b/.gitignore index d55ab1c..ef1bc06 100644 --- a/.gitignore +++ b/.gitignore @@ -56,10 +56,12 @@ unix/dltest.marker unix/dltest/embtest unix/tcl.pc unix/tclIndex +unix/pkgs8/* unix/pkgs/* win/Debug* win/Release* win/*.manifest +win/pkgs8/* win/pkgs/* win/coffbase.txt win/tcl.hpj -- cgit v0.12 From 33fe1e9e5691eb43a528e31b51cab682bd8e2118 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 17 Apr 2024 16:19:32 +0000 Subject: Few additions to release notes --- changes.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/changes.md b/changes.md index 415eff7..d9d2d56 100644 --- a/changes.md +++ b/changes.md @@ -70,7 +70,7 @@ Tcl 9: * Internationalization of text - Full Unicode range of codepoints - - New encodings: utf-16(le|be), ucs-2(le|be), CESU-8, etc. + - New encodings: utf-16/utf-32/ucs-2(le|be), CESU-8, etc. - [encoding] options -profile, -failindex manage encoding of I/O. - [msgcat] supports custom locale search list - [source] defaults to -encoding utf-8 @@ -90,6 +90,8 @@ Tcl 9: - $::tcl_precision no longer controls string generation of doubles - Removed Tcl 7 legacies: [case], [puts] [read] variant syntaxes - Removed subcommands [trace variable|vdelete|vinfo] + - No -eofchar option for channels anymore for writing. + - On Windows 10+ (Version 1903 or higher), system encoding is always utf-8. * Incompatibilities in C public interface - Many arguments expanded type from int to Tcl_Size @@ -117,10 +119,12 @@ Tcl 9: - [package files] - [string insert], [string is dict] - [tcl::process] + - [*::build-info] * New command options - [regsub ... -command ...] - [lsearch ... -stride ...] + - [clock scan ... -validate ...] - [socket ... -nodelay ... -keepalive ...] - [vwait] controlled by several new options @@ -153,6 +157,7 @@ Tk 9: - [$frame ... -backgroundimage $img -tile $bool] - [$menu id], [$menu add|insert ... ?$id? ...] - [$image get ... -withalpha ...] + - All indices now accept the forms "end", "end-int", "int+|-int" * Improved widget appearance - ttk::notebook with nondefault tab positions -- cgit v0.12 From 48ccb7e2bc1b9268ec7b910fecaaa255a1845b3d Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 18 Apr 2024 14:41:20 +0000 Subject: Tcl_DuplicateObj can't return NULL --- generic/tclStrIdxTree.c | 52 ++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index 3e02bf0..21be447 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -61,12 +61,12 @@ static void StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr); static void StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr); static const Tcl_ObjType StrIdxTreeObjType = { - "str-idx-tree", /* name */ - StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */ - StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */ - StrIdxTreeObj_UpdateStringProc, /* updateStringProc */ - NULL, /* setFromAnyProc */ - TCL_OBJTYPE_V0 + "str-idx-tree", /* name */ + StrIdxTreeObj_FreeIntRepProc, /* freeIntRepProc */ + StrIdxTreeObj_DupIntRepProc, /* dupIntRepProc */ + StrIdxTreeObj_UpdateStringProc, /* updateStringProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* @@ -87,14 +87,13 @@ static const Tcl_ObjType StrIdxTreeObjType = { * *---------------------------------------------------------------------- */ - const char * TclStrIdxTreeSearch( - TclStrIdxTree **foundParent, /* Return value of found sub tree (used for tree build) */ - TclStrIdx **foundItem, /* Return value of found item */ - TclStrIdxTree *tree, /* Index tree will be browsed */ - const char *start, /* UTF string to find in tree */ - const char *end) /* End of string */ + TclStrIdxTree **foundParent,/* Return value of found sub tree (used for tree build) */ + TclStrIdx **foundItem, /* Return value of found item */ + TclStrIdxTree *tree, /* Index tree will be browsed */ + const char *start, /* UTF string to find in tree */ + const char *end) /* End of string */ { TclStrIdxTree *parent = tree, *prevParent = tree; TclStrIdx *item = tree->firstPtr, *prevItem = NULL; @@ -116,9 +115,11 @@ TclStrIdxTreeSearch( start = f; goto done; } + /* set new offset and shift start string */ offs += cinf - cin; s = f; + /* if match item, go deeper as long as possible */ if (offs >= item->length && item->childTree.firstPtr) { /* save previuosly found item (if not ambigous) for @@ -132,6 +133,7 @@ TclStrIdxTreeSearch( item = item->childTree.firstPtr; continue; } + /* no children - return this item and current chars found */ start = f; goto done; @@ -176,6 +178,7 @@ TclStrIdxTreeFree( /* * Several bidirectional list primitives */ + static inline void TclStrIdxTreeInsertBranch( TclStrIdxTree *parent, @@ -236,7 +239,6 @@ TclStrIdxTreeAppend( * *---------------------------------------------------------------------- */ - int TclStrIdxTreeBuildFromList( TclStrIdxTree *idxTree, @@ -253,15 +255,12 @@ TclStrIdxTreeBuildFromList( /* create lowercase reflection of the list keys */ - lwrv = (Tcl_Obj **)Tcl_AttemptAlloc(sizeof(Tcl_Obj*) * lstc); + lwrv = (Tcl_Obj **) Tcl_AttemptAlloc(sizeof(Tcl_Obj*) * lstc); if (lwrv == NULL) { return TCL_ERROR; } for (i = 0; i < lstc; i++) { lwrv[i] = Tcl_DuplicateObj(lstv[i]); - if (lwrv[i] == NULL) { - return TCL_ERROR; - } Tcl_IncrRefCount(lwrv[i]); lwrv[i]->length = Tcl_UtfToLower(TclGetString(lwrv[i])); } @@ -283,36 +282,39 @@ TclStrIdxTreeBuildFromList( if (idxTree->firstPtr != NULL) { TclStrIdx *foundItem; - f = TclStrIdxTreeSearch(&foundParent, &foundItem, - idxTree, s, e); + f = TclStrIdxTreeSearch(&foundParent, &foundItem, idxTree, s, e); /* if common prefix was found */ if (f > s) { /* ignore element if fulfilled or ambigous */ if (f == e) { continue; } + /* if shortest key was found with the same value, * just replace its current key with longest key */ if (foundItem->value == val && foundItem->length <= lwrv[i]->length - && foundItem->length <= (f - s) /* only if found item is covered in full */ + && foundItem->length <= (f - s) // only if found item is covered in full && foundItem->childTree.firstPtr == NULL) { TclSetObjRef(foundItem->key, lwrv[i]); foundItem->length = lwrv[i]->length; continue; } + /* split tree (e. g. j->(jan,jun) + jul == j->(jan,ju->(jun,jul)) ) * but don't split by fulfilled child of found item ( ii->iii->iiii ) */ if (foundItem->length != (f - s)) { /* first split found item (insert one between parent and found + new one) */ - item = (TclStrIdx *)Tcl_AttemptAlloc(sizeof(TclStrIdx)); + item = (TclStrIdx *) Tcl_AttemptAlloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } TclInitObjRef(item->key, foundItem->key); item->length = f - s; + /* set value or mark as ambigous if not the same value of both */ item->value = (foundItem->value == val) ? val : NULL; + /* insert group item between foundParent and foundItem */ TclStrIdxTreeInsertBranch(foundParent, item, foundItem); foundParent = &item->childTree; @@ -322,8 +324,9 @@ TclStrIdxTreeBuildFromList( } } } + /* append item at end of found parent */ - item = (TclStrIdx *)Tcl_AttemptAlloc(sizeof(TclStrIdx)); + item = (TclStrIdx *) Tcl_AttemptAlloc(sizeof(TclStrIdx)); if (item == NULL) { goto done; } @@ -398,6 +401,7 @@ StrIdxTreeObj_DupIntRepProc( { /* follow links (smart pointers) */ srcPtr = FollowPossibleLink(srcPtr); + /* create smart pointer to it (ptr1 != NULL, ptr2 = NULL) */ TclInitObjRef(*((Tcl_Obj **) ©Ptr->internalRep.twoPtrValue.ptr1), srcPtr); @@ -442,8 +446,10 @@ TclStrIdxTreeGetFromObj( if (objPtr->typePtr != &StrIdxTreeObjType) { return NULL; } + /* follow links (smart pointers) */ objPtr = FollowPossibleLink(objPtr); + /* return tree root in internal representation */ return (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue; } @@ -503,6 +509,7 @@ TclStrIdxTreeTestObjCmd( TclGetString(objv[1]), (char *)NULL); return TCL_ERROR; } + switch (optionIndex) { case O_FINDEQUAL: if (objc < 4) { @@ -515,6 +522,7 @@ TclStrIdxTreeTestObjCmd( cs, cs + objv[1]->length, cin, cin + objv[2]->length); Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs)); break; + case O_INDEX: case O_PUTS_INDEX: { Tcl_Obj **lstv; -- cgit v0.12 From adc00697fb61715324a8be9401e5d13508215448 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 19 Apr 2024 08:00:18 +0000 Subject: Fix indenting --- generic/tclIO.c | 5 +- generic/tclIORChan.c | 286 +++++++++++++++++++++++++-------------------------- 2 files changed, 145 insertions(+), 146 deletions(-) diff --git a/generic/tclIO.c b/generic/tclIO.c index 6dbf5d9..44d4f7d 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -3152,8 +3152,8 @@ CloseChannel( /* * Cancel any outstanding timer. */ - DeleteTimerHandler(statePtr); + DeleteTimerHandler(statePtr); /* * Mark the channel as deleted by clearing the type structure. @@ -7544,7 +7544,6 @@ Tcl_Eof( return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0; } - /* *---------------------------------------------------------------------- * @@ -7570,7 +7569,7 @@ TclChannelGetBlockingMode( return GotFlag(statePtr, CHANNEL_NONBLOCKING) ? 0 : 1; } - + /* *---------------------------------------------------------------------- * diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 5417730..fe54f65 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -78,7 +78,7 @@ static const Tcl_ChannelType tclRChannelType = { NULL, /* Handle events. NULL'able */ ReflectSeekWide, /* Move access point (64 bit). NULL'able */ #if TCL_THREADS - ReflectThread, /* thread action, tracking owner */ + ReflectThread, /* thread action, tracking owner */ #else NULL, /* thread action */ #endif @@ -100,7 +100,7 @@ typedef struct { */ #if TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */ - Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ + Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ #endif Tcl_Obj *cmd; /* Callback command prefix */ Tcl_Obj *methods; /* Methods to append to command prefix */ @@ -117,12 +117,12 @@ typedef struct { A token for the timer that is scheduled in order to call Tcl_NotifyChannel when the channel is readable - */ + */ Tcl_TimerToken writeTimer; /* A token for the timer that is scheduled in order to call Tcl_NotifyChannel when the channel is writable - */ + */ /* * Note regarding the usage of timers. @@ -613,9 +613,9 @@ TclChanCreateObjCmd( */ if (TclListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s initialize\" returned non-list: %s", - TclGetString(cmdObj), TclGetString(resObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s initialize\" returned non-list: %s", + TclGetString(cmdObj), TclGetString(resObj))); Tcl_DecrRefCount(resObj); goto error; } @@ -639,37 +639,37 @@ TclChanCreateObjCmd( Tcl_DecrRefCount(resObj); if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" does not support all required methods", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" does not support all required methods", + TclGetString(cmdObj))); goto error; } if ((mode & TCL_READABLE) && !HAS(methods, METH_READ)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" lacks a \"read\" method", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" lacks a \"read\" method", + TclGetString(cmdObj))); goto error; } if ((mode & TCL_WRITABLE) && !HAS(methods, METH_WRITE)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" lacks a \"write\" method", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" lacks a \"write\" method", + TclGetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_CGET), HAS(methods, METH_CGETALL))) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" supports \"cget\" but not \"cgetall\"", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" supports \"cget\" but not \"cgetall\"", + TclGetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_CGETALL), HAS(methods, METH_CGET))) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" supports \"cgetall\" but not \"cget\"", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" supports \"cgetall\" but not \"cget\"", + TclGetString(cmdObj))); goto error; } @@ -742,7 +742,7 @@ TclChanCreateObjCmd( */ Tcl_SetObjResult(interp, - Tcl_NewStringObj(chanPtr->state->channelName, -1)); + Tcl_NewStringObj(chanPtr->state->channelName, -1)); return TCL_OK; error: @@ -814,7 +814,7 @@ ReflectEventDelete( ReflectEvent *e = (ReflectEvent *) ev; if ((ev->proc != ReflectEventRun) || ((cd != NULL) && (cd != e->rcPtr))) { - return 0; + return 0; } return 1; } @@ -873,7 +873,7 @@ TclChanPostEventObjCmd( if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can not find reflected channel named \"%s\"", chanId)); + "can not find reflected channel named \"%s\"", chanId)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, (char *)NULL); return TCL_ERROR; } @@ -937,8 +937,8 @@ TclChanPostEventObjCmd( if (events & ~rcPtr->interest) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "tried to post events channel \"%s\" is not interested in", - chanId)); + "tried to post events channel \"%s\" is not interested in", + chanId)); return TCL_ERROR; } @@ -963,36 +963,36 @@ TclChanPostEventObjCmd( } #if TCL_THREADS } else { - ReflectEvent *ev = (ReflectEvent *)Tcl_Alloc(sizeof(ReflectEvent)); - - ev->header.proc = ReflectEventRun; - ev->events = events; - ev->rcPtr = rcPtr; - - /* - * We are not preserving the structure here. When the channel is - * closed any pending events are deleted, see ReflectClose(), and - * ReflectEventDelete(). Trying to preserve and later release when the - * event is run may generate a situation where the channel structure - * is deleted but not our structure, crashing in - * FreeReflectedChannel(). - * - * Force creation of the RCM, for proper cleanup on thread teardown. - * The teardown of unprocessed events is currently coupled to the - * thread reflected channel map - */ - - (void) GetThreadReflectedChannelMap(); - - /* - * XXX Race condition !! - * XXX The destination thread may not exist anymore already. - * XXX (Delayed postevent executed after channel got removed). - * XXX Can we detect this ? (check the validity of the owner threadid ?) - * XXX Actually, in that case the channel should be dead also ! - */ - - Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, + ReflectEvent *ev = (ReflectEvent *)Tcl_Alloc(sizeof(ReflectEvent)); + + ev->header.proc = ReflectEventRun; + ev->events = events; + ev->rcPtr = rcPtr; + + /* + * We are not preserving the structure here. When the channel is + * closed any pending events are deleted, see ReflectClose(), and + * ReflectEventDelete(). Trying to preserve and later release when the + * event is run may generate a situation where the channel structure + * is deleted but not our structure, crashing in + * FreeReflectedChannel(). + * + * Force creation of the RCM, for proper cleanup on thread teardown. + * The teardown of unprocessed events is currently coupled to the + * thread reflected channel map + */ + + (void) GetThreadReflectedChannelMap(); + + /* + * XXX Race condition !! + * XXX The destination thread may not exist anymore already. + * XXX (Delayed postevent executed after channel got removed). + * XXX Can we detect this ? (check the validity of the owner threadid ?) + * XXX Actually, in that case the channel should be dead also ! + */ + + Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY); } #endif @@ -1207,11 +1207,11 @@ ReflectClose( ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p); result = p.base.code; - /* - * Now squash the pending reflection events for this channel. - */ + /* + * Now squash the pending reflection events for this channel. + */ - Tcl_DeleteEvents(ReflectEventDelete, rcPtr); + Tcl_DeleteEvents(ReflectEventDelete, rcPtr); if (result != TCL_OK) { FreeReceivedError(&p); @@ -1245,11 +1245,11 @@ ReflectClose( ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p); result = p.base.code; - /* - * Now squash the pending reflection events for this channel. - */ + /* + * Now squash the pending reflection events for this channel. + */ - Tcl_DeleteEvents(ReflectEventDelete, rcPtr); + Tcl_DeleteEvents(ReflectEventDelete, rcPtr); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); @@ -1384,11 +1384,11 @@ ReflectInput( if (code < 0) { *errorCodePtr = -code; - goto error; + goto error; } Tcl_SetChannelError(rcPtr->chan, resObj); - goto invalid; + goto invalid; } bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec); @@ -1468,9 +1468,9 @@ ReflectOutput( *errorCodePtr = -p.base.code; } else { - PassReceivedError(rcPtr->chan, &p); - *errorCodePtr = EINVAL; - } + PassReceivedError(rcPtr->chan, &p); + *errorCodePtr = EINVAL; + } p.output.toWrite = -1; } else { *errorCodePtr = EOK; @@ -1494,11 +1494,11 @@ ReflectOutput( if (code < 0) { *errorCodePtr = -code; - goto error; + goto error; } Tcl_SetChannelError(rcPtr->chan, resObj); - goto invalid; + goto invalid; } if (Tcl_InterpDeleted(rcPtr->interp)) { @@ -1507,11 +1507,11 @@ ReflectOutput( */ SetChannelErrorStr(rcPtr->chan, msg_send_dstlost); - goto invalid; + goto invalid; } if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); - goto invalid; + goto invalid; } if ((written == 0) && (toWrite > 0)) { @@ -1521,7 +1521,7 @@ ReflectOutput( */ SetChannelErrorStr(rcPtr->chan, msg_write_nothing); - goto invalid; + goto invalid; } if (toWrite < written) { /* @@ -1531,7 +1531,7 @@ ReflectOutput( */ SetChannelErrorStr(rcPtr->chan, msg_write_toomuch); - goto invalid; + goto invalid; } *errorCodePtr = EOK; @@ -1607,24 +1607,24 @@ ReflectSeekWide( TclNewIntObj(offObj, offset); baseObj = Tcl_NewStringObj( - (seekMode == SEEK_SET) ? "start" : - (seekMode == SEEK_CUR) ? "current" : "end", -1); + (seekMode == SEEK_SET) ? "start" : + (seekMode == SEEK_CUR) ? "current" : "end", -1); Tcl_IncrRefCount(offObj); Tcl_IncrRefCount(baseObj); if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) { Tcl_SetChannelError(rcPtr->chan, resObj); - goto invalid; + goto invalid; } if (TclGetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); - goto invalid; + goto invalid; } if (newLoc < 0) { SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart); - goto invalid; + goto invalid; } *errorCodePtr = EOK; @@ -1805,14 +1805,14 @@ ReflectThread( switch (action) { case TCL_CHANNEL_THREAD_INSERT: - rcPtr->owner = Tcl_GetCurrentThread(); - break; + rcPtr->owner = Tcl_GetCurrentThread(); + break; case TCL_CHANNEL_THREAD_REMOVE: - rcPtr->owner = NULL; - break; + rcPtr->owner = NULL; + break; default: - Tcl_Panic("Unknown thread action code."); - break; + Tcl_Panic("Unknown thread action code."); + break; } } @@ -1971,14 +1971,14 @@ ReflectGetOption( method = METH_CGET; optionObj = Tcl_NewStringObj(optionName, -1); - Tcl_IncrRefCount(optionObj); + Tcl_IncrRefCount(optionObj); } Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, method, optionObj, NULL, &resObj)!=TCL_OK) { UnmarshallErrorResult(interp, resObj); - goto error; + goto error; } /* @@ -1988,7 +1988,7 @@ ReflectGetOption( if (optionObj != NULL) { TclDStringAppendObj(dsPtr, resObj); - goto ok; + goto ok; } /* @@ -2003,7 +2003,7 @@ ReflectGetOption( */ if (TclListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) { - goto error; + goto error; } if ((listc % 2) == 1) { @@ -2016,7 +2016,7 @@ ReflectGetOption( "Expected list with even number of " "elements, got %" TCL_SIZE_MODIFIER "d element%s instead", listc, (listc == 1 ? "" : "s"))); - goto error; + goto error; } else { Tcl_Size len; const char *str = TclGetStringFromObj(resObj, &len); @@ -2025,14 +2025,14 @@ ReflectGetOption( TclDStringAppendLiteral(dsPtr, " "); Tcl_DStringAppend(dsPtr, str, len); } - goto ok; + goto ok; } ok: result = TCL_OK; stop: if (optionObj) { - Tcl_DecrRefCount(optionObj); + Tcl_DecrRefCount(optionObj); } Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); @@ -2386,10 +2386,10 @@ InvokeTclMethod( Tcl_IncrRefCount(resObj); } - /* - * Not touching argOneObj, argTwoObj, they have not been used. - * See the contract as well. - */ + /* + * Not touching argOneObj, argTwoObj, they have not been used. + * See the contract as well. + */ return TCL_ERROR; } @@ -2685,11 +2685,11 @@ DeleteReflectedChannelMap( /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. - * - * Attention: Results may have been detached already, by either the - * receiver, or this thread, as part of other parts in the thread - * teardown. Such results are ignored. See ticket [b47b176adf] for the - * identical race condition in Tcl 8.6 IORTrans. + * + * Attention: Results may have been detached already, by either the + * receiver, or this thread, as part of other parts in the thread + * teardown. Such results are ignored. See ticket [b47b176adf] for the + * identical race condition in Tcl 8.6 IORTrans. */ evPtr = resultPtr->evPtr; @@ -2838,11 +2838,11 @@ DeleteThreadReflectedChannelMap( /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. - * - * Attention: Results may have been detached already, by either the - * receiver, or this thread, as part of other parts in the thread - * teardown. Such results are ignored. See ticket [b47b176adf] for the - * identical race condition in Tcl 8.6 IORTrans. + * + * Attention: Results may have been detached already, by either the + * receiver, or this thread, as part of other parts in the thread + * teardown. Such results are ignored. See ticket [b47b176adf] for the + * identical race condition in Tcl 8.6 IORTrans. */ evPtr = resultPtr->evPtr; @@ -3051,7 +3051,7 @@ ForwardProc( ForwardParam *paramPtr = evPtr->param; Tcl_Obj *resObj = NULL; /* Interp result of InvokeTclMethod */ ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in - * this interp. */ + * this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ /* @@ -3094,12 +3094,12 @@ ForwardProc( rcmPtr = GetReflectedChannelMap(interp); hPtr = Tcl_FindHashEntry(&rcmPtr->map, - Tcl_GetChannelName(rcPtr->chan)); + Tcl_GetChannelName(rcPtr->chan)); Tcl_DeleteHashEntry(hPtr); rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_FindHashEntry(&rcmPtr->map, - Tcl_GetChannelName(rcPtr->chan)); + Tcl_GetChannelName(rcPtr->chan)); Tcl_DeleteHashEntry(hPtr); MarkDead(rcPtr); break; @@ -3144,17 +3144,17 @@ ForwardProc( paramPtr->input.toRead = bytec; } } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(toReadObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(toReadObj); break; } case ForwardedOutput: { Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *) - paramPtr->output.buf, paramPtr->output.toWrite); - Tcl_IncrRefCount(bufObj); + paramPtr->output.buf, paramPtr->output.toWrite); + Tcl_IncrRefCount(bufObj); - Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) { int code = ErrnoReturn(rcPtr, resObj); @@ -3183,8 +3183,8 @@ ForwardProc( paramPtr->output.toWrite = written; } } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(bufObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(bufObj); break; } @@ -3226,35 +3226,35 @@ ForwardProc( paramPtr->seek.offset = -1; } } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(offObj); - Tcl_DecrRefCount(baseObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(offObj); + Tcl_DecrRefCount(baseObj); break; } case ForwardedWatch: { Tcl_Obj *maskObj = DecodeEventMask(paramPtr->watch.mask); - /* assert maskObj.refCount == 1 */ + /* assert maskObj.refCount == 1 */ - Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr); rcPtr->interest = paramPtr->watch.mask; (void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL); Tcl_DecrRefCount(maskObj); - Tcl_Release(rcPtr); + Tcl_Release(rcPtr); break; } case ForwardedBlock: { Tcl_Obj *blockObj = Tcl_NewBooleanObj(!paramPtr->block.nonblocking); - Tcl_IncrRefCount(blockObj); - Tcl_Preserve(rcPtr); + Tcl_IncrRefCount(blockObj); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_BLOCKING, blockObj, NULL, - &resObj) != TCL_OK) { + &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(blockObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(blockObj); break; } @@ -3262,16 +3262,16 @@ ForwardProc( Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->setOpt.name, -1); Tcl_Obj *valueObj = Tcl_NewStringObj(paramPtr->setOpt.value, -1); - Tcl_IncrRefCount(optionObj); - Tcl_IncrRefCount(valueObj); - Tcl_Preserve(rcPtr); + Tcl_IncrRefCount(optionObj); + Tcl_IncrRefCount(valueObj); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CONFIGURE, optionObj, valueObj, - &resObj) != TCL_OK) { + &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(optionObj); - Tcl_DecrRefCount(valueObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(optionObj); + Tcl_DecrRefCount(valueObj); break; } @@ -3282,15 +3282,15 @@ ForwardProc( Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->getOpt.name, -1); - Tcl_IncrRefCount(optionObj); - Tcl_Preserve(rcPtr); + Tcl_IncrRefCount(optionObj); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CGET, optionObj, NULL, &resObj)!=TCL_OK){ ForwardSetObjError(paramPtr, resObj); } else { TclDStringAppendObj(paramPtr->getOpt.value, resObj); } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(optionObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(optionObj); break; } @@ -3299,7 +3299,7 @@ ForwardProc( * Retrieve all options. */ - Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CGETALL, NULL, NULL, &resObj) != TCL_OK){ ForwardSetObjError(paramPtr, resObj); } else { @@ -3312,7 +3312,7 @@ ForwardProc( Tcl_Obj **listv; if (TclListObjGetElements(interp, resObj, &listc, - &listv) != TCL_OK) { + &listv) != TCL_OK) { Tcl_DecrRefCount(resObj); resObj = MarshallError(interp); ForwardSetObjError(paramPtr, resObj); @@ -3337,7 +3337,7 @@ ForwardProc( } } } - Tcl_Release(rcPtr); + Tcl_Release(rcPtr); break; case ForwardedTruncate: { -- cgit v0.12 From bf119934a2bbf23dc728d9ee87c200d6fc76abc0 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 19 Apr 2024 08:12:21 +0000 Subject: (backport) Fix indenting --- generic/tclIO.c | 5 +- generic/tclIORChan.c | 226 +++++++++++++++++++++++++-------------------------- 2 files changed, 115 insertions(+), 116 deletions(-) diff --git a/generic/tclIO.c b/generic/tclIO.c index 0d8d4db..4c60171 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -3194,8 +3194,8 @@ CloseChannel( /* * Cancel any outstanding timer. */ - DeleteTimerHandler(statePtr); + DeleteTimerHandler(statePtr); /* * Mark the channel as deleted by clearing the type structure. @@ -7626,7 +7626,6 @@ Tcl_Eof( return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0; } - /* *---------------------------------------------------------------------- * @@ -7652,7 +7651,7 @@ TclChannelGetBlockingMode( return GotFlag(statePtr, CHANNEL_NONBLOCKING) ? 0 : 1; } - + /* *---------------------------------------------------------------------- * diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 4e938ae..ef731fc 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -86,7 +86,7 @@ static const Tcl_ChannelType tclRChannelType = { NULL, /* Handle events. NULL'able */ ReflectSeekWide, /* Move access point (64 bit). NULL'able */ #if TCL_THREADS - ReflectThread, /* thread action, tracking owner */ + ReflectThread, /* thread action, tracking owner */ #else NULL, /* thread action */ #endif @@ -108,7 +108,7 @@ typedef struct { */ #if TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */ - Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ + Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ #endif Tcl_Obj *cmd; /* Callback command prefix */ Tcl_Obj *methods; /* Methods to append to command prefix */ @@ -125,12 +125,12 @@ typedef struct { A token for the timer that is scheduled in order to call Tcl_NotifyChannel when the channel is readable - */ + */ Tcl_TimerToken writeTimer; /* A token for the timer that is scheduled in order to call Tcl_NotifyChannel when the channel is writable - */ + */ /* * Note regarding the usage of timers. @@ -620,9 +620,9 @@ TclChanCreateObjCmd( */ if (TclListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s initialize\" returned non-list: %s", - TclGetString(cmdObj), TclGetString(resObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s initialize\" returned non-list: %s", + TclGetString(cmdObj), TclGetString(resObj))); Tcl_DecrRefCount(resObj); goto error; } @@ -646,37 +646,37 @@ TclChanCreateObjCmd( Tcl_DecrRefCount(resObj); if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" does not support all required methods", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" does not support all required methods", + TclGetString(cmdObj))); goto error; } if ((mode & TCL_READABLE) && !HAS(methods, METH_READ)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" lacks a \"read\" method", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" lacks a \"read\" method", + TclGetString(cmdObj))); goto error; } if ((mode & TCL_WRITABLE) && !HAS(methods, METH_WRITE)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" lacks a \"write\" method", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" lacks a \"write\" method", + TclGetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_CGET), HAS(methods, METH_CGETALL))) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" supports \"cget\" but not \"cgetall\"", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" supports \"cget\" but not \"cgetall\"", + TclGetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_CGETALL), HAS(methods, METH_CGET))) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "chan handler \"%s\" supports \"cgetall\" but not \"cget\"", - TclGetString(cmdObj))); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "chan handler \"%s\" supports \"cgetall\" but not \"cget\"", + TclGetString(cmdObj))); goto error; } @@ -752,7 +752,7 @@ TclChanCreateObjCmd( */ Tcl_SetObjResult(interp, - Tcl_NewStringObj(chanPtr->state->channelName, -1)); + Tcl_NewStringObj(chanPtr->state->channelName, -1)); return TCL_OK; error: @@ -824,7 +824,7 @@ ReflectEventDelete( ReflectEvent *e = (ReflectEvent *) ev; if ((ev->proc != ReflectEventRun) || ((cd != NULL) && (cd != e->rcPtr))) { - return 0; + return 0; } return 1; } @@ -883,7 +883,7 @@ TclChanPostEventObjCmd( if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can not find reflected channel named \"%s\"", chanId)); + "can not find reflected channel named \"%s\"", chanId)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, (char *)NULL); return TCL_ERROR; } @@ -947,8 +947,8 @@ TclChanPostEventObjCmd( if (events & ~rcPtr->interest) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "tried to post events channel \"%s\" is not interested in", - chanId)); + "tried to post events channel \"%s\" is not interested in", + chanId)); return TCL_ERROR; } @@ -1217,11 +1217,11 @@ ReflectClose( ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p); result = p.base.code; - /* - * Now squash the pending reflection events for this channel. - */ + /* + * Now squash the pending reflection events for this channel. + */ - Tcl_DeleteEvents(ReflectEventDelete, rcPtr); + Tcl_DeleteEvents(ReflectEventDelete, rcPtr); if (result != TCL_OK) { FreeReceivedError(&p); @@ -1255,11 +1255,11 @@ ReflectClose( ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p); result = p.base.code; - /* - * Now squash the pending reflection events for this channel. - */ + /* + * Now squash the pending reflection events for this channel. + */ - Tcl_DeleteEvents(ReflectEventDelete, rcPtr); + Tcl_DeleteEvents(ReflectEventDelete, rcPtr); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); @@ -1394,11 +1394,11 @@ ReflectInput( if (code < 0) { *errorCodePtr = -code; - goto error; + goto error; } Tcl_SetChannelError(rcPtr->chan, resObj); - goto invalid; + goto invalid; } bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); @@ -1475,9 +1475,9 @@ ReflectOutput( *errorCodePtr = -p.base.code; } else { - PassReceivedError(rcPtr->chan, &p); - *errorCodePtr = EINVAL; - } + PassReceivedError(rcPtr->chan, &p); + *errorCodePtr = EINVAL; + } p.output.toWrite = -1; } else { *errorCodePtr = EOK; @@ -1501,11 +1501,11 @@ ReflectOutput( if (code < 0) { *errorCodePtr = -code; - goto error; + goto error; } Tcl_SetChannelError(rcPtr->chan, resObj); - goto invalid; + goto invalid; } if (Tcl_InterpDeleted(rcPtr->interp)) { @@ -1514,11 +1514,11 @@ ReflectOutput( */ SetChannelErrorStr(rcPtr->chan, msg_send_dstlost); - goto invalid; + goto invalid; } if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); - goto invalid; + goto invalid; } if ((written == 0) && (toWrite > 0)) { @@ -1528,7 +1528,7 @@ ReflectOutput( */ SetChannelErrorStr(rcPtr->chan, msg_write_nothing); - goto invalid; + goto invalid; } if (toWrite < written) { /* @@ -1538,7 +1538,7 @@ ReflectOutput( */ SetChannelErrorStr(rcPtr->chan, msg_write_toomuch); - goto invalid; + goto invalid; } *errorCodePtr = EOK; @@ -1614,24 +1614,24 @@ ReflectSeekWide( TclNewIntObj(offObj, offset); baseObj = Tcl_NewStringObj( - (seekMode == SEEK_SET) ? "start" : - (seekMode == SEEK_CUR) ? "current" : "end", -1); + (seekMode == SEEK_SET) ? "start" : + (seekMode == SEEK_CUR) ? "current" : "end", -1); Tcl_IncrRefCount(offObj); Tcl_IncrRefCount(baseObj); if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) { Tcl_SetChannelError(rcPtr->chan, resObj); - goto invalid; + goto invalid; } if (Tcl_GetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); - goto invalid; + goto invalid; } if (newLoc < 0) { SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart); - goto invalid; + goto invalid; } *errorCodePtr = EOK; @@ -1832,14 +1832,14 @@ ReflectThread( switch (action) { case TCL_CHANNEL_THREAD_INSERT: - rcPtr->owner = Tcl_GetCurrentThread(); - break; + rcPtr->owner = Tcl_GetCurrentThread(); + break; case TCL_CHANNEL_THREAD_REMOVE: - rcPtr->owner = NULL; - break; + rcPtr->owner = NULL; + break; default: - Tcl_Panic("Unknown thread action code."); - break; + Tcl_Panic("Unknown thread action code."); + break; } } @@ -1998,14 +1998,14 @@ ReflectGetOption( method = METH_CGET; optionObj = Tcl_NewStringObj(optionName, -1); - Tcl_IncrRefCount(optionObj); + Tcl_IncrRefCount(optionObj); } Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, method, optionObj, NULL, &resObj)!=TCL_OK) { UnmarshallErrorResult(interp, resObj); - goto error; + goto error; } /* @@ -2015,7 +2015,7 @@ ReflectGetOption( if (optionObj != NULL) { TclDStringAppendObj(dsPtr, resObj); - goto ok; + goto ok; } /* @@ -2030,7 +2030,7 @@ ReflectGetOption( */ if (TclListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) { - goto error; + goto error; } if ((listc % 2) == 1) { @@ -2043,7 +2043,7 @@ ReflectGetOption( "Expected list with even number of " "elements, got %" TCL_SIZE_MODIFIER "d element%s instead", listc, (listc == 1 ? "" : "s"))); - goto error; + goto error; } else { Tcl_Size len; const char *str = TclGetStringFromObj(resObj, &len); @@ -2052,14 +2052,14 @@ ReflectGetOption( TclDStringAppendLiteral(dsPtr, " "); Tcl_DStringAppend(dsPtr, str, len); } - goto ok; + goto ok; } ok: result = TCL_OK; stop: if (optionObj) { - Tcl_DecrRefCount(optionObj); + Tcl_DecrRefCount(optionObj); } Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); @@ -2413,10 +2413,10 @@ InvokeTclMethod( Tcl_IncrRefCount(resObj); } - /* - * Not touching argOneObj, argTwoObj, they have not been used. - * See the contract as well. - */ + /* + * Not touching argOneObj, argTwoObj, they have not been used. + * See the contract as well. + */ return TCL_ERROR; } @@ -2712,11 +2712,11 @@ DeleteReflectedChannelMap( /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. - * - * Attention: Results may have been detached already, by either the - * receiver, or this thread, as part of other parts in the thread - * teardown. Such results are ignored. See ticket [b47b176adf] for the - * identical race condition in Tcl 8.6 IORTrans. + * + * Attention: Results may have been detached already, by either the + * receiver, or this thread, as part of other parts in the thread + * teardown. Such results are ignored. See ticket [b47b176adf] for the + * identical race condition in Tcl 8.6 IORTrans. */ evPtr = resultPtr->evPtr; @@ -2865,11 +2865,11 @@ DeleteThreadReflectedChannelMap( /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. - * - * Attention: Results may have been detached already, by either the - * receiver, or this thread, as part of other parts in the thread - * teardown. Such results are ignored. See ticket [b47b176adf] for the - * identical race condition in Tcl 8.6 IORTrans. + * + * Attention: Results may have been detached already, by either the + * receiver, or this thread, as part of other parts in the thread + * teardown. Such results are ignored. See ticket [b47b176adf] for the + * identical race condition in Tcl 8.6 IORTrans. */ evPtr = resultPtr->evPtr; @@ -3078,7 +3078,7 @@ ForwardProc( ForwardParam *paramPtr = evPtr->param; Tcl_Obj *resObj = NULL; /* Interp result of InvokeTclMethod */ ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in - * this interp. */ + * this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ /* @@ -3121,12 +3121,12 @@ ForwardProc( rcmPtr = GetReflectedChannelMap(interp); hPtr = Tcl_FindHashEntry(&rcmPtr->map, - Tcl_GetChannelName(rcPtr->chan)); + Tcl_GetChannelName(rcPtr->chan)); Tcl_DeleteHashEntry(hPtr); rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_FindHashEntry(&rcmPtr->map, - Tcl_GetChannelName(rcPtr->chan)); + Tcl_GetChannelName(rcPtr->chan)); Tcl_DeleteHashEntry(hPtr); MarkDead(rcPtr); break; @@ -3168,17 +3168,17 @@ ForwardProc( paramPtr->input.toRead = bytec; } } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(toReadObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(toReadObj); break; } case ForwardedOutput: { Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *) - paramPtr->output.buf, paramPtr->output.toWrite); - Tcl_IncrRefCount(bufObj); + paramPtr->output.buf, paramPtr->output.toWrite); + Tcl_IncrRefCount(bufObj); - Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) { int code = ErrnoReturn(rcPtr, resObj); @@ -3207,8 +3207,8 @@ ForwardProc( paramPtr->output.toWrite = written; } } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(bufObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(bufObj); break; } @@ -3250,35 +3250,35 @@ ForwardProc( paramPtr->seek.offset = -1; } } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(offObj); - Tcl_DecrRefCount(baseObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(offObj); + Tcl_DecrRefCount(baseObj); break; } case ForwardedWatch: { Tcl_Obj *maskObj = DecodeEventMask(paramPtr->watch.mask); - /* assert maskObj.refCount == 1 */ + /* assert maskObj.refCount == 1 */ - Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr); rcPtr->interest = paramPtr->watch.mask; (void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL); Tcl_DecrRefCount(maskObj); - Tcl_Release(rcPtr); + Tcl_Release(rcPtr); break; } case ForwardedBlock: { Tcl_Obj *blockObj = Tcl_NewBooleanObj(!paramPtr->block.nonblocking); - Tcl_IncrRefCount(blockObj); - Tcl_Preserve(rcPtr); + Tcl_IncrRefCount(blockObj); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_BLOCKING, blockObj, NULL, - &resObj) != TCL_OK) { + &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(blockObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(blockObj); break; } @@ -3286,16 +3286,16 @@ ForwardProc( Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->setOpt.name, -1); Tcl_Obj *valueObj = Tcl_NewStringObj(paramPtr->setOpt.value, -1); - Tcl_IncrRefCount(optionObj); - Tcl_IncrRefCount(valueObj); - Tcl_Preserve(rcPtr); + Tcl_IncrRefCount(optionObj); + Tcl_IncrRefCount(valueObj); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CONFIGURE, optionObj, valueObj, - &resObj) != TCL_OK) { + &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(optionObj); - Tcl_DecrRefCount(valueObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(optionObj); + Tcl_DecrRefCount(valueObj); break; } @@ -3306,15 +3306,15 @@ ForwardProc( Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->getOpt.name, -1); - Tcl_IncrRefCount(optionObj); - Tcl_Preserve(rcPtr); + Tcl_IncrRefCount(optionObj); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CGET, optionObj, NULL, &resObj)!=TCL_OK){ ForwardSetObjError(paramPtr, resObj); } else { TclDStringAppendObj(paramPtr->getOpt.value, resObj); } - Tcl_Release(rcPtr); - Tcl_DecrRefCount(optionObj); + Tcl_Release(rcPtr); + Tcl_DecrRefCount(optionObj); break; } @@ -3323,7 +3323,7 @@ ForwardProc( * Retrieve all options. */ - Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CGETALL, NULL, NULL, &resObj) != TCL_OK){ ForwardSetObjError(paramPtr, resObj); } else { @@ -3336,7 +3336,7 @@ ForwardProc( Tcl_Obj **listv; if (TclListObjGetElements(interp, resObj, &listc, - &listv) != TCL_OK) { + &listv) != TCL_OK) { Tcl_DecrRefCount(resObj); resObj = MarshallError(interp); ForwardSetObjError(paramPtr, resObj); @@ -3361,7 +3361,7 @@ ForwardProc( } } } - Tcl_Release(rcPtr); + Tcl_Release(rcPtr); break; case ForwardedTruncate: { -- cgit v0.12 From 072c5b11392289eeeb1813fa9deecd946db1e916 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 19 Apr 2024 08:15:29 +0000 Subject: More indenting --- generic/tclIO.c | 170 +++++++++++++++++++++++++-------------------------- generic/tclIORChan.c | 60 +++++++++--------- 2 files changed, 115 insertions(+), 115 deletions(-) diff --git a/generic/tclIO.c b/generic/tclIO.c index 4c60171..7ed6993 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -105,7 +105,7 @@ typedef struct CopyState { Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */ Tcl_Size bufSize; /* Size of appended buffer. */ char buffer[TCLFLEXARRAY]; /* Copy buffer, this must be the last - * field. */ + * field. */ } CopyState; /* @@ -228,7 +228,7 @@ static Tcl_Size Write(Channel *chanPtr, const char *src, static Tcl_Obj * FixLevelCode(Tcl_Obj *msg); static void SpliceChannel(Tcl_Channel chan); static void CutChannel(Tcl_Channel chan); -static int WillRead(Channel *chanPtr); +static int WillRead(Channel *chanPtr); #define WriteChars(chanPtr, src, srcLen) \ Write(chanPtr, src, srcLen, chanPtr->state->encoding) @@ -430,12 +430,12 @@ ChanRead( */ if (GotFlag(chanPtr->state, CHANNEL_EOF)) { - chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START; + chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF); chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END; if (WillRead(chanPtr) < 0) { - return -1; + return -1; } bytesRead = chanPtr->typePtr->inputProc(chanPtr->instanceData, @@ -446,7 +446,7 @@ ChanRead( */ if (GotFlag(chanPtr->state, CHANNEL_EOF)) { - chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START; + chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF); chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END; @@ -597,14 +597,14 @@ TclFinalizeIOSubsystem(void) */ { - const char *s; - Tcl_DString ds; + const char *s; + Tcl_DString ds; - s = TclGetEnv("TCL_FLUSH_NONBLOCKING_ON_EXIT", &ds); - doflushnb = ((s != NULL) && strcmp(s, "0")); - if (s != NULL) { - Tcl_DStringFree(&ds); - } + s = TclGetEnv("TCL_FLUSH_NONBLOCKING_ON_EXIT", &ds); + doflushnb = ((s != NULL) && strcmp(s, "0")); + if (s != NULL) { + Tcl_DStringFree(&ds); + } } /* @@ -624,12 +624,12 @@ TclFinalizeIOSubsystem(void) statePtr != NULL; statePtr = statePtr->nextCSPtr) { chanPtr = statePtr->topChanPtr; - if (GotFlag(statePtr, CHANNEL_DEAD)) { - continue; - } + if (GotFlag(statePtr, CHANNEL_DEAD)) { + continue; + } if (!GotFlag(statePtr, CHANNEL_INCLOSE | CHANNEL_CLOSED ) || GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { - ResetFlag(statePtr, BG_FLUSH_SCHEDULED); + ResetFlag(statePtr, BG_FLUSH_SCHEDULED); active = 1; break; } @@ -644,20 +644,20 @@ TclFinalizeIOSubsystem(void) /* * TIP #398: by default, we no longer set the channel back into - * blocking mode. To restore the old blocking behavior, the - * environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT must be set - * and not be "0". + * blocking mode. To restore the old blocking behavior, the + * environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT must be set + * and not be "0". */ - if (doflushnb) { - /* - * Set the channel back into blocking mode to ensure that we - * wait for all data to flush out. - */ + if (doflushnb) { + /* + * Set the channel back into blocking mode to ensure that we + * wait for all data to flush out. + */ - (void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr, - "-blocking", "on"); - } + (void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr, + "-blocking", "on"); + } if ((chanPtr == (Channel *) tsdPtr->stdinChannel) || (chanPtr == (Channel *) tsdPtr->stdoutChannel) || @@ -1240,8 +1240,8 @@ Tcl_UnregisterChannel( if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "illegal recursive call to close through close-handler" - " of channel", -1)); + "illegal recursive call to close through close-handler" + " of channel", -1)); } return TCL_ERROR; } @@ -1468,7 +1468,7 @@ Tcl_GetChannel( hPtr = Tcl_FindHashEntry(hTblPtr, name); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can not find channel named \"%s\"", chanName)); + "can not find channel named \"%s\"", chanName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanName, (char *)NULL); return NULL; } @@ -1671,9 +1671,9 @@ Tcl_CreateChannel( unsigned len = strlen(chanName) + 1; /* - * Make sure we allocate at least 7 bytes, so it fits for "stdout" - * later. - */ + * Make sure we allocate at least 7 bytes, so it fits for "stdout" + * later. + */ tmp = (char *)ckalloc((len < 7) ? 7 : len); strcpy(tmp, chanName); @@ -1865,7 +1865,7 @@ Tcl_StackChannel( if (statePtr == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't find state for channel \"%s\"", + "couldn't find state for channel \"%s\"", Tcl_GetChannelName(prevChan))); } return NULL; @@ -1916,7 +1916,7 @@ Tcl_StackChannel( statePtr->csPtrW = csPtrW; if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "could not flush channel \"%s\"", + "could not flush channel \"%s\"", Tcl_GetChannelName(prevChan))); } return NULL; @@ -2111,7 +2111,7 @@ Tcl_UnstackChannel( if (!TclChanCaughtErrorBypass(interp, chan) && interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "could not flush channel \"%s\"", + "could not flush channel \"%s\"", Tcl_GetChannelName((Tcl_Channel) chanPtr))); } return TCL_ERROR; @@ -2444,9 +2444,9 @@ Tcl_GetChannelHandle( chanPtr = ((Channel *) chan)->state->bottomChanPtr; if (!chanPtr->typePtr->getHandleProc) { - Tcl_SetChannelError(chan, Tcl_ObjPrintf( - "channel \"%s\" does not support OS handles", - Tcl_GetChannelName(chan))); + Tcl_SetChannelError(chan, Tcl_ObjPrintf( + "channel \"%s\" does not support OS handles", + Tcl_GetChannelName(chan))); return TCL_ERROR; } result = chanPtr->typePtr->getHandleProc(chanPtr->instanceData, direction, @@ -2476,7 +2476,7 @@ Tcl_GetChannelHandle( int Tcl_RemoveChannelMode( - Tcl_Interp *interp, /* The interp for an error message. Allowed to be NULL. */ + Tcl_Interp *interp, /* The interp for an error message. Allowed to be NULL. */ Tcl_Channel chan, /* The channel which is modified. */ int mode) /* The access mode to drop from the channel */ { @@ -2485,11 +2485,11 @@ Tcl_RemoveChannelMode( /* State of actual channel. */ if ((mode != TCL_READABLE) && (mode != TCL_WRITABLE)) { - emsg = "Illegal mode value."; + emsg = "Illegal mode value."; goto error; } if (0 == (GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE) & ~mode)) { - emsg = "Bad mode, would make channel inacessible"; + emsg = "Bad mode, would make channel inacessible"; goto error; } @@ -2727,7 +2727,7 @@ CheckForDeadChannel( Tcl_SetErrno(EINVAL); if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "unable to access channel: invalid channel", -1)); + "unable to access channel: invalid channel", -1)); } return 1; } @@ -3038,7 +3038,7 @@ FlushChannel( ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { errorCode = CloseChannelPart(interp, chanPtr, errorCode, - TCL_CLOSE_WRITE); + TCL_CLOSE_WRITE); goto done; } @@ -3499,8 +3499,8 @@ Tcl_Close( if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "illegal recursive call to close through close-handler" - " of channel", -1)); + "illegal recursive call to close through close-handler" + " of channel", -1)); } return TCL_ERROR; } @@ -3722,8 +3722,8 @@ Tcl_CloseEx( msg = "write"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "Half-close of %s-side not possible, side not opened or" - " already closed", msg)); + "Half-close of %s-side not possible, side not opened or" + " already closed", msg)); return TCL_ERROR; } @@ -3735,8 +3735,8 @@ Tcl_CloseEx( if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "illegal recursive call to close through close-handler" - " of channel", -1)); + "illegal recursive call to close through close-handler" + " of channel", -1)); } return TCL_ERROR; } @@ -3797,8 +3797,8 @@ static int CloseWrite( Tcl_Interp *interp, /* Interpreter for errors. */ Channel *chanPtr) /* The channel whose write side is being - * closed. May still be used by some - * interpreter */ + * closed. May still be used by some + * interpreter */ { /* * Notes: clear-channel-handlers - write side only ? or keep around, just @@ -3808,7 +3808,7 @@ CloseWrite( */ ChannelState *statePtr = chanPtr->state; - /* State of real IO channel. */ + /* State of real IO channel. */ int flushcode; int result = 0; @@ -4387,7 +4387,7 @@ static Tcl_Size Write( Channel *chanPtr, /* The channel to buffer output for. */ const char *src, /* UTF-8 string to write. */ - Tcl_Size srcLen, /* Length of UTF-8 string in bytes. */ + Tcl_Size srcLen, /* Length of UTF-8 string in bytes. */ Tcl_Encoding encoding) { ChannelState *statePtr = chanPtr->state; @@ -4399,7 +4399,7 @@ Write( int encodingError = 0; if (srcLen) { - WillWrite(chanPtr); + WillWrite(chanPtr); } /* @@ -5181,7 +5181,7 @@ TclGetsObjBinary( * coming back here. When we are not dealing with * CHANNEL_STICKY_EOF, a CHANNEL_EOF implies an empty buffer. * Here the buffer is non-empty so we know we're a non-EOF. - */ + */ assert(!GotFlag(statePtr, CHANNEL_STICKY_EOF)); assert(!GotFlag(statePtr, CHANNEL_EOF)); @@ -5478,7 +5478,7 @@ FilterInputBytes( * coming back here. When we are not dealing with CHANNEL_STICKY_EOF, * a CHANNEL_EOF implies an empty buffer. Here the buffer is * non-empty so we know we're a non-EOF. - */ + */ assert(!GotFlag(statePtr, CHANNEL_STICKY_EOF)); assert(!GotFlag(statePtr, CHANNEL_EOF)); @@ -5840,8 +5840,8 @@ Tcl_ReadRaw( bytesToRead -= toCopy; /* - * If the current buffer is empty recycle it. - */ + * If the current buffer is empty recycle it. + */ if (IsBufferEmpty(bufPtr)) { chanPtr->inQueueHead = bufPtr->nextPtr; @@ -6177,7 +6177,7 @@ finish: || GotFlag(statePtr, CHANNEL_ENCODING_ERROR) || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0); assert(!(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED) - == (CHANNEL_EOF|CHANNEL_BLOCKED))); + == (CHANNEL_EOF|CHANNEL_BLOCKED))); UpdateInterest(chanPtr); /* This must comes after UpdateInterest(), which may set errno */ @@ -7128,7 +7128,7 @@ GetInput( * Check the actual buffersize against the requested buffersize. * Saved buffers of the wrong size are squashed. This is done to honor * dynamic changes of the buffersize made by the user. - * + * * TODO: Tests to cover this. */ @@ -7493,7 +7493,7 @@ Tcl_TruncateChannel( WillWrite(chanPtr); if (WillRead(chanPtr) < 0) { - return TCL_ERROR; + return TCL_ERROR; } /* @@ -7927,7 +7927,7 @@ Tcl_BadChannelOption( const char **argv; Tcl_Size argc, i; Tcl_DString ds; - Tcl_Obj *errObj; + Tcl_Obj *errObj; Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, genericopt, -1); @@ -7941,13 +7941,13 @@ Tcl_BadChannelOption( } Tcl_ResetResult(interp); errObj = Tcl_ObjPrintf("bad option \"%s\": should be one of ", - optionName ? optionName : ""); + optionName ? optionName : ""); argc--; for (i = 0; i < argc; i++) { Tcl_AppendPrintfToObj(errObj, "-%s, ", argv[i]); } Tcl_AppendPrintfToObj(errObj, "or -%s", argv[i]); - Tcl_SetObjResult(interp, errObj); + Tcl_SetObjResult(interp, errObj); Tcl_DStringFree(&ds); ckfree(argv); } @@ -8245,8 +8245,8 @@ Tcl_SetChannelOption( if (statePtr->csPtrR || statePtr->csPtrW) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "unable to set channel options: background copy in" - " progress", -1)); + "unable to set channel options: background copy in" + " progress", -1)); } return TCL_ERROR; } @@ -8295,10 +8295,10 @@ Tcl_SetChannelOption( ResetFlag(statePtr, CHANNEL_LINEBUFFERED); SetFlag(statePtr, CHANNEL_UNBUFFERED); } else if (interp) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "bad value for -buffering: must be one of" - " full, line, or none", -1)); - return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "bad value for -buffering: must be one of" + " full, line, or none", -1)); + return TCL_ERROR; } return TCL_OK; } else if (HaveOpt(7, "-buffersize")) { @@ -8363,8 +8363,8 @@ Tcl_SetChannelOption( if (inValue & 0x80 || outValue & 0x80) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "bad value for -eofchar: must be non-NUL ASCII" - " character", TCL_INDEX_NONE)); + "bad value for -eofchar: must be non-NUL ASCII" + " character", TCL_INDEX_NONE)); } ckfree(argv); return TCL_ERROR; @@ -8456,7 +8456,7 @@ Tcl_SetChannelOption( if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -translation: must be one of " - "auto, binary, cr, lf, crlf, or platform", -1)); + "auto, binary, cr, lf, crlf, or platform", -1)); } ckfree(argv); return TCL_ERROR; @@ -8506,7 +8506,7 @@ Tcl_SetChannelOption( if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -translation: must be one of " - "auto, binary, cr, lf, crlf, or platform", -1)); + "auto, binary, cr, lf, crlf, or platform", -1)); } ckfree(argv); return TCL_ERROR; @@ -9456,7 +9456,7 @@ TclCopyChannelOld( Tcl_Obj *cmdPtr) /* Pointer to script to execute or NULL. */ { return TclCopyChannel(interp, inChan, outChan, (Tcl_WideInt) toRead, - cmdPtr); + cmdPtr); } #endif @@ -9482,14 +9482,14 @@ TclCopyChannel( if (BUSY_STATE(inStatePtr, TCL_READABLE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "channel \"%s\" is busy", Tcl_GetChannelName(inChan))); + "channel \"%s\" is busy", Tcl_GetChannelName(inChan))); } return TCL_ERROR; } if (BUSY_STATE(outStatePtr, TCL_WRITABLE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "channel \"%s\" is busy", Tcl_GetChannelName(outChan))); + "channel \"%s\" is busy", Tcl_GetChannelName(outChan))); } return TCL_ERROR; } @@ -9571,8 +9571,8 @@ TclCopyChannel( */ if ((nonBlocking == CHANNEL_NONBLOCKING) && (toRead == 0)) { - Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr); - return 0; + Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr); + return 0; } /* @@ -9914,7 +9914,7 @@ CopyData( */ if ((csPtr->toRead == (Tcl_WideInt) -1) - || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) { + || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) { sizeb = csPtr->bufSize; } else { sizeb = (int) csPtr->toRead; @@ -9922,7 +9922,7 @@ CopyData( if (inBinary || sameEncoding) { size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb, - !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); + !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); } else { size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, !GotFlag(inStatePtr, CHANNEL_NONBLOCKING) @@ -10605,7 +10605,7 @@ SetBlockMode( if (!TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "error setting blocking mode: %s", + "error setting blocking mode: %s", Tcl_PosixError(interp))); } } else { @@ -11320,7 +11320,7 @@ Tcl_SetChannelErrorInterp( } if (disposePtr != NULL) { - TclDecrRefCount(disposePtr); + TclDecrRefCount(disposePtr); } return; } @@ -11358,7 +11358,7 @@ Tcl_SetChannelError( } if (disposePtr != NULL) { - TclDecrRefCount(disposePtr); + TclDecrRefCount(disposePtr); } return; } diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index ef731fc..383d74a 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -973,36 +973,36 @@ TclChanPostEventObjCmd( } #if TCL_THREADS } else { - ReflectEvent *ev = (ReflectEvent *)ckalloc(sizeof(ReflectEvent)); - - ev->header.proc = ReflectEventRun; - ev->events = events; - ev->rcPtr = rcPtr; - - /* - * We are not preserving the structure here. When the channel is - * closed any pending events are deleted, see ReflectClose(), and - * ReflectEventDelete(). Trying to preserve and later release when the - * event is run may generate a situation where the channel structure - * is deleted but not our structure, crashing in - * FreeReflectedChannel(). - * - * Force creation of the RCM, for proper cleanup on thread teardown. - * The teardown of unprocessed events is currently coupled to the - * thread reflected channel map - */ - - (void) GetThreadReflectedChannelMap(); - - /* - * XXX Race condition !! - * XXX The destination thread may not exist anymore already. - * XXX (Delayed postevent executed after channel got removed). - * XXX Can we detect this ? (check the validity of the owner threadid ?) - * XXX Actually, in that case the channel should be dead also ! - */ - - Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, + ReflectEvent *ev = (ReflectEvent *)ckalloc(sizeof(ReflectEvent)); + + ev->header.proc = ReflectEventRun; + ev->events = events; + ev->rcPtr = rcPtr; + + /* + * We are not preserving the structure here. When the channel is + * closed any pending events are deleted, see ReflectClose(), and + * ReflectEventDelete(). Trying to preserve and later release when the + * event is run may generate a situation where the channel structure + * is deleted but not our structure, crashing in + * FreeReflectedChannel(). + * + * Force creation of the RCM, for proper cleanup on thread teardown. + * The teardown of unprocessed events is currently coupled to the + * thread reflected channel map + */ + + (void) GetThreadReflectedChannelMap(); + + /* + * XXX Race condition !! + * XXX The destination thread may not exist anymore already. + * XXX (Delayed postevent executed after channel got removed). + * XXX Can we detect this ? (check the validity of the owner threadid ?) + * XXX Actually, in that case the channel should be dead also ! + */ + + Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY); } #endif -- cgit v0.12 From f7eefdfa9fd664b9bd0679c15a99340284c9bec6 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 21 Apr 2024 10:11:04 +0000 Subject: No need for Tcl_TomMath_InitStubs() any more, due to TIP #648 --- generic/tclTest.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/generic/tclTest.c b/generic/tclTest.c index 3731b3a..4312a08 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -556,11 +556,6 @@ Tcltest_Init( if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } -#ifndef TCL_WITH_EXTERNAL_TOMMATH - if (Tcl_TomMath_InitStubs(interp, "8.5-") == NULL) { - return TCL_ERROR; - } -#endif if (Tcl_OOInitStubs(interp) == NULL) { return TCL_ERROR; } -- cgit v0.12 From 4fe247a03a93f80fb12b2155e62d515578b4a906 Mon Sep 17 00:00:00 2001 From: griffin Date: Mon, 22 Apr 2024 01:49:29 +0000 Subject: Remove abstractlist extension from dict objtype. --- generic/tclDictObj.c | 182 +++------------------------------------------------ tests/dict.test | 5 -- 2 files changed, 8 insertions(+), 179 deletions(-) diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index c9ef68d..8c34bb8 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -61,8 +61,6 @@ static Tcl_ObjCmdProc DictForNRCmd; static Tcl_ObjCmdProc DictMapNRCmd; static Tcl_NRPostProc DictForLoopCallback; static Tcl_NRPostProc DictMapLoopCallback; -static Tcl_ObjTypeLengthProc DictAsListLength; -/* static Tcl_ObjTypeIndexProc DictAsListIndex; Needs rewrite */ /* * Table of dict subcommand names and implementations. @@ -131,7 +129,7 @@ typedef struct Dict { * the dictionary. Used for doing traversal of * the entries in the order that they are * created. */ - size_t epoch; /* Epoch counter */ + size_t epoch; /* Epoch counter */ size_t refCount; /* Reference counter (see above) */ Tcl_Obj *chain; /* Linked list used for invalidating the * string representations of updated nested @@ -149,33 +147,22 @@ const Tcl_ObjType tclDictType = { DupDictInternalRep, /* dupIntRepProc */ UpdateStringOfDict, /* updateStringProc */ SetDictFromAny, /* setFromAnyProc */ - TCL_OBJTYPE_V2( /* Extended type for AbstractLists */ - DictAsListLength, /* return "list" length of dict value w/o - * shimmering */ - NULL, /* return key or value at "list" index - * location. (keysare at even indicies, - * values at odd indicies) */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL) + TCL_OBJTYPE_V0 }; #define DictSetInternalRep(objPtr, dictRepPtr) \ do { \ - Tcl_ObjInternalRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (dictRepPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreInternalRep((objPtr), &tclDictType, &ir); \ + Tcl_StoreInternalRep((objPtr), &tclDictType, &ir); \ } while (0) #define DictGetInternalRep(objPtr, dictRepPtr) \ do { \ - const Tcl_ObjInternalRep *irPtr; \ - irPtr = TclFetchInternalRep((objPtr), &tclDictType); \ - (dictRepPtr) = irPtr ? (Dict *)irPtr->twoPtrValue.ptr1 : NULL; \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &tclDictType); \ + (dictRepPtr) = irPtr ? (Dict *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* @@ -2058,7 +2045,7 @@ DictSizeCmd( Tcl_Obj *const *objv) { int result; - Tcl_Size size; + Tcl_Size size; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary"); @@ -3854,159 +3841,6 @@ TclInitDictCmd( { return TclMakeEnsemble(interp, "dict", implementationMap); } - -/* - *---------------------------------------------------------------------- - * - * DictAsListLength -- - * - * Compute the length of a list as if the dict value were converted to a - * list. - * - * Note: the list length may not match the dict size * 2. This occurs when - * there are duplicate keys in the original string representation. - * - * Side Effects -- - * - * The intent is to have no side effects. - */ - -static Tcl_Size -DictAsListLength( - Tcl_Obj *objPtr) -{ - Tcl_Size estCount, length, llen; - const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length); - Tcl_Obj *elemPtr; - - /* - * Allocate enough space to hold a (Tcl_Obj *) for each - * (possible) list element. - */ - - estCount = TclMaxListLength(nextElem, length, &limit); - estCount += (estCount == 0); /* Smallest list struct holds 1 - * element. */ - elemPtr = Tcl_NewObj(); - - llen = 0; - - while (nextElem < limit) { - const char *elemStart; - char *check; - Tcl_Size elemSize; - int literal; - - if (TCL_OK != TclFindElement(NULL, nextElem, limit - nextElem, - &elemStart, &nextElem, &elemSize, &literal)) { - Tcl_DecrRefCount(elemPtr); - return 0; - } - if (elemStart == limit) { - break; - } - - TclInvalidateStringRep(elemPtr); - check = Tcl_InitStringRep(elemPtr, literal ? elemStart : NULL, - elemSize); - if (elemSize && check == NULL) { - Tcl_DecrRefCount(elemPtr); - return 0; - } - if (!literal) { - Tcl_InitStringRep(elemPtr, NULL, - TclCopyAndCollapse(elemSize, elemStart, check)); - } - llen++; - } - Tcl_DecrRefCount(elemPtr); - return llen; -} - - -/* - *---------------------------------------------------------------------- - * - * DictAsListIndex -- - * - * Return the key or value at the given "list" index, i.e., as if the string - * value where treated as a list. The intent is to support this list - * operation w/o causing the Obj value to shimmer into a List. - * - * Side Effects -- - * - * The intent is to have no side effects. - * - */ -#if 0 /* Needs rewrite */ -static int -DictAsListIndex( - Tcl_Interp *interp, - struct Tcl_Obj *objPtr, - Tcl_Size index, - Tcl_Obj** elemObjPtr) -{ - Tcl_Size /*estCount,*/ length, llen; - const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length); - Tcl_Obj *elemPtr; - - /* - * Compute limit of the list string - */ - - TclMaxListLength(nextElem, length, &limit); - elemPtr = Tcl_NewObj(); - - llen = 0; - - /* - * parse out each element until reaching the "index"th element. - * Sure this is slow, but shimmering is slower. - */ - while (nextElem < limit) { - const char *elemStart; - char *check; - Tcl_Size elemSize; - int literal; - - if (TCL_OK != TclFindElement(NULL, nextElem, limit - nextElem, - &elemStart, &nextElem, &elemSize, &literal)) { - Tcl_DecrRefCount(elemPtr); - return 0; - } - if (elemStart == limit) { - break; - } - - TclInvalidateStringRep(elemPtr); - check = Tcl_InitStringRep(elemPtr, literal ? elemStart : NULL, - elemSize); - if (elemSize && check == NULL) { - Tcl_DecrRefCount(elemPtr); - if (interp) { - // Need error message here - } - return TCL_ERROR; - } - if (!literal) { - Tcl_InitStringRep(elemPtr, NULL, - TclCopyAndCollapse(elemSize, elemStart, check)); - } - if (llen == index) { - *elemObjPtr = elemPtr; - return TCL_OK; - } - llen++; - } - - /* - * Index is beyond end of list - return empty - */ - Tcl_InitStringRep(elemPtr, NULL, 0); - *elemObjPtr = elemPtr; - return TCL_OK; -} -#endif /* * Local Variables: diff --git a/tests/dict.test b/tests/dict.test index 59b600e..9bbd417 100644 --- a/tests/dict.test +++ b/tests/dict.test @@ -151,11 +151,6 @@ test dict-3.16 {dict/list shimmering - Bug 3004007} testobj { dict get $l q list $l [testobj objtype $l] } {{p 1 p 2 q 3} dict} -test dict-3.17 {dict/list shimmering - Bug 3004007} testobj { - set l [list p 1 p 2 q 3] - dict get $l q - list [llength $l] [testobj objtype $l] -} {6 dict} test dict-4.1 {dict replace command} { dict replace {a b c d} -- cgit v0.12 From 3b30cec8b9d68c41584531341f3a9ee8d0393aa9 Mon Sep 17 00:00:00 2001 From: oehhar Date: Mon, 22 Apr 2024 07:00:47 +0000 Subject: Ticket [00b3e5dea8]: "info comdtype" return value "native" created by "Tcl_CreateObjCommand", not "Tcl_CreateObjProc" --- doc/info.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/info.n b/doc/info.n index b84b2c7..028a772 100644 --- a/doc/info.n +++ b/doc/info.n @@ -54,7 +54,7 @@ target are visible. .IP \fBimport\fR \fIcommandName\fR was created by \fBnamespace import\fR. .IP \fBnative\fR -\fIcommandName\fR was created by the \fBTcl_CreateObjProc\fR +\fIcommandName\fR was created by the \fBTcl_CreateObjCommand\fR interface directly without further registration of the type of command. .IP \fBobject\fR \fIcommandName\fR is the public command that represents an -- cgit v0.12 From 1f51f9e619ce207bf8d4508809c3d3eb6c8c98c2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 22 Apr 2024 17:41:34 +0000 Subject: Only use Tcl_TomMath_InitStubs() when TCL_WITH_EXTERNAL_TOMMATH is not defined --- generic/tclTestObj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 4a23369..26f07d8 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -109,9 +109,11 @@ TclObjTest_Init( */ Tcl_Obj **varPtr; +#ifndef TCL_WITH_EXTERNAL_TOMMATH if (Tcl_TomMath_InitStubs(interp, "8.5-") == NULL) { return TCL_ERROR; } +#endif varPtr = (Tcl_Obj **)ckalloc(NUMBER_OF_OBJECT_VARS *sizeof(varPtr[0])); if (!varPtr) { return TCL_ERROR; -- cgit v0.12 From 8b5f712b6628bde4df926a2d11618c7f7bd7d7fe Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 23 Apr 2024 20:11:45 +0000 Subject: Possible fix for [ef23a85ac6]: Tcl_PanicProc - Tcl9 & NaviServer --- generic/tcl.decls | 4 ++-- generic/tcl.h | 6 +++--- generic/tclEvent.c | 4 ++-- generic/tclPanic.c | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/generic/tcl.decls b/generic/tcl.decls index 41fe5f3..20b6cba 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -2417,10 +2417,10 @@ export { Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc) } export { - const char *Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) + const char *Tcl_SetPanicProc(Tcl_PanicProc *panicProc) } export { - Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc) + Tcl_ExitProc *Tcl_SetExitProc(Tcl_ExitProc *proc) } export { const char *Tcl_FindExecutable(const char *argv0) diff --git a/generic/tcl.h b/generic/tcl.h index d339b8f..774ac18 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -597,7 +597,7 @@ typedef void (Tcl_FreeProc) (char *blockPtr); #endif typedef int (Tcl_LibraryInitProc) (Tcl_Interp *interp); typedef int (Tcl_LibraryUnloadProc) (Tcl_Interp *interp, int flags); -typedef void (Tcl_PanicProc) (const char *format, ...); +typedef TCL_NORETURN1 void (Tcl_PanicProc) (const char *format, ...); typedef void (Tcl_TcpAcceptProc) (void *callbackData, Tcl_Channel chan, char *address, int port); typedef void (Tcl_TimerProc) (void *clientData); @@ -2371,7 +2371,7 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); EXTERN const char * Tcl_FindExecutable(const char *argv0); EXTERN const char * Tcl_SetPreInitScript(const char *string); EXTERN const char * Tcl_SetPanicProc( - TCL_NORETURN1 Tcl_PanicProc *panicProc); + Tcl_PanicProc *panicProc); EXTERN void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, @@ -2379,7 +2379,7 @@ EXTERN void Tcl_StaticLibrary(Tcl_Interp *interp, #ifndef TCL_NO_DEPRECATED # define Tcl_StaticPackage Tcl_StaticLibrary #endif -EXTERN Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc); +EXTERN Tcl_ExitProc *Tcl_SetExitProc(Tcl_ExitProc *proc); #ifdef _WIN32 EXTERN const char *TclZipfs_AppHook(int *argc, wchar_t ***argv); #else diff --git a/generic/tclEvent.c b/generic/tclEvent.c index 69c3c27..ad0f820 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -105,7 +105,7 @@ static const char ENCODING_ERROR[] = "\n\t(encoding error in stderr)"; * non-NULL value. */ -static TCL_NORETURN1 Tcl_ExitProc *appExitPtr = NULL; +static Tcl_ExitProc *appExitPtr = NULL; typedef struct ThreadSpecificData { ExitHandler *firstExitPtr; /* First in list of all exit handlers for this @@ -958,7 +958,7 @@ Tcl_Exit( int status) /* Exit status for application; typically 0 * for normal return, 1 for error return. */ { - TCL_NORETURN1 Tcl_ExitProc *currentAppExitPtr; + Tcl_ExitProc *currentAppExitPtr; Tcl_MutexLock(&exitMutex); currentAppExitPtr = appExitPtr; diff --git a/generic/tclPanic.c b/generic/tclPanic.c index 5a05c24..2dd33d2 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -23,7 +23,7 @@ * procedure. */ -static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL; +static Tcl_PanicProc *panicProc = NULL; /* *---------------------------------------------------------------------- @@ -43,7 +43,7 @@ static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL; const char * Tcl_SetPanicProc( - TCL_NORETURN1 Tcl_PanicProc *proc) + Tcl_PanicProc *proc) { panicProc = proc; return Tcl_InitSubsystems(); -- cgit v0.12 From cf03773499c65e0d3f41f9b73991911bbe76d358 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 23 Apr 2024 20:17:26 +0000 Subject: Still one TCL_NORETURN1 too much --- generic/tclEvent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclEvent.c b/generic/tclEvent.c index ad0f820..49467c8 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -877,7 +877,7 @@ Tcl_DeleteThreadExitHandler( Tcl_ExitProc * Tcl_SetExitProc( - TCL_NORETURN1 Tcl_ExitProc *proc) /* New exit handler for app or NULL */ + Tcl_ExitProc *proc) /* New exit handler for app or NULL */ { Tcl_ExitProc *prevExitProc; -- cgit v0.12 From 5a5cfe0be03b5d889080d9a701f89107a70d7a29 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 23 Apr 2024 20:36:04 +0000 Subject: Missing "_" in __declspec --- generic/tcl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tcl.h b/generic/tcl.h index 774ac18..90bc0c1 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -117,7 +117,7 @@ extern "C" { #else # define TCL_FORMAT_PRINTF(a,b) # if defined(_MSC_VER) -# define TCL_NORETURN _declspec(noreturn) +# define TCL_NORETURN __declspec(noreturn) # define TCL_NOINLINE __declspec(noinline) # else # define TCL_NORETURN /* nothing */ -- cgit v0.12 From 69ed03bc06bf1afd409d4cc9e4f0b9895474acfa Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 24 Apr 2024 19:16:12 +0000 Subject: Improve use of TCL_NORETURN, so no unnecessary warnings are produced any more --- generic/tcl.h | 4 ++-- generic/tclPanic.c | 26 +++++++++++++------------- win/tclWinPanic.c | 16 +--------------- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 90bc0c1..52288ab 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -597,7 +597,7 @@ typedef void (Tcl_FreeProc) (char *blockPtr); #endif typedef int (Tcl_LibraryInitProc) (Tcl_Interp *interp); typedef int (Tcl_LibraryUnloadProc) (Tcl_Interp *interp, int flags); -typedef TCL_NORETURN1 void (Tcl_PanicProc) (const char *format, ...); +typedef void (Tcl_PanicProc) (const char *format, ...); typedef void (Tcl_TcpAcceptProc) (void *callbackData, Tcl_Channel chan, char *address, int port); typedef void (Tcl_TimerProc) (void *clientData); @@ -2312,7 +2312,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char * TclInitStubTable(const char *version); void * TclStubCall(void *arg); #if defined(_WIN32) - TCL_NORETURN1 void Tcl_ConsolePanic(const char *format, ...); + void Tcl_ConsolePanic(const char *format, ...); #else # define Tcl_ConsolePanic NULL #endif diff --git a/generic/tclPanic.c b/generic/tclPanic.c index 2dd33d2..dcceb25 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -71,7 +71,7 @@ Tcl_SetPanicProc( */ /* coverity[+kill] */ -void +TCL_NORETURN void Tcl_Panic( const char *format, ...) @@ -104,21 +104,21 @@ Tcl_Panic( fprintf(stderr, "\n"); fflush(stderr); #endif -# if defined(__GNUC__) - __builtin_trap(); -# elif defined(_WIN64) - __debugbreak(); -# elif defined(_MSC_VER) && defined (_M_IX86) - _asm {int 3} -# elif defined(_WIN32) - DebugBreak(); -# endif + } +#if defined(__GNUC__) + __builtin_trap(); +#elif defined(_WIN64) + __debugbreak(); +#elif defined(_MSC_VER) && defined (_M_IX86) + _asm {int 3} +#elif defined(_WIN32) + DebugBreak(); +#endif #if defined(_WIN32) - ExitProcess(1); + ExitProcess(1); #else - abort(); + abort(); #endif - } } /* diff --git a/win/tclWinPanic.c b/win/tclWinPanic.c index 7928dcd..02bd767 100644 --- a/win/tclWinPanic.c +++ b/win/tclWinPanic.c @@ -28,7 +28,7 @@ *---------------------------------------------------------------------- */ -TCL_NORETURN1 void +void Tcl_ConsolePanic( const char *format, ...) { @@ -63,20 +63,6 @@ Tcl_ConsolePanic( WriteFile(handle, "\n", 1, &dummy, 0); FlushFileBuffers(handle); } -# if defined(__GNUC__) - __builtin_trap(); -# elif defined(_WIN64) - __debugbreak(); -# elif defined(_MSC_VER) - _asm {int 3} -# else - DebugBreak(); -# endif -#if defined(_WIN32) - ExitProcess(1); -#else - abort(); -#endif } /* * Local Variables: -- cgit v0.12 From 1abff90ead8c13fee3de05eb1f7bb31cde01a159 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 24 Apr 2024 19:41:08 +0000 Subject: Better keep Tcl_ConsolePanic as it was (with TCL_NORETURN) --- generic/tcl.h | 2 +- win/tclWinPanic.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 52288ab..d5951c4 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2312,7 +2312,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char * TclInitStubTable(const char *version); void * TclStubCall(void *arg); #if defined(_WIN32) - void Tcl_ConsolePanic(const char *format, ...); + TCL_NORETURN void Tcl_ConsolePanic(const char *format, ...); #else # define Tcl_ConsolePanic NULL #endif diff --git a/win/tclWinPanic.c b/win/tclWinPanic.c index 02bd767..65527f7 100644 --- a/win/tclWinPanic.c +++ b/win/tclWinPanic.c @@ -28,7 +28,7 @@ *---------------------------------------------------------------------- */ -void +TCL_NORETURN void Tcl_ConsolePanic( const char *format, ...) { @@ -63,6 +63,20 @@ Tcl_ConsolePanic( WriteFile(handle, "\n", 1, &dummy, 0); FlushFileBuffers(handle); } +# if defined(__GNUC__) + __builtin_trap(); +# elif defined(_WIN64) + __debugbreak(); +# elif defined(_MSC_VER) + _asm {int 3} +# else + DebugBreak(); +# endif +#if defined(_WIN32) + ExitProcess(1); +#else + abort(); +#endif } /* * Local Variables: -- cgit v0.12 From 050612f80d48c8a4a0b8c303eb21eb9a73a23ce6 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Thu, 25 Apr 2024 04:47:13 +0000 Subject: Fix building of libtclzip for out-of-source builds --- win/makefile.vc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/win/makefile.vc b/win/makefile.vc index 152fc1e..13b5396 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -464,7 +464,8 @@ TCLSTUBOBJS = \ TOMMATHDIR = $(ROOT)\libtommath PKGSDIR = $(ROOT)\pkgs -LIBTCLVFS = $(OUT_DIR)\libtcl.vfs +LIBTCLVFSSUBDIR = libtcl.vfs +LIBTCLVFS = $(OUT_DIR)\$(LIBTCLVFSSUBDIR) # Additional include and C macro definitions for the implicit rules # defined in rules.vc @@ -664,9 +665,10 @@ $(TCLSCRIPTZIP): $(TCLLIB) $(TCLSH) dlls @$(COPY) $(TCLDDELIB) "$(LIBTCLVFS)\tcl_library\dde @$(COPY) $(TCLREGLIB) "$(LIBTCLVFS)\tcl_library\registry !endif - @echo file delete -force {$@} > "$(OUT_DIR)\zipper.tcl" - @echo zipfs mkzip {$@} {$(LIBTCLVFS)} {$(LIBTCLVFS)} >> "$(OUT_DIR)\zipper.tcl" - @cd "$(OUT_DIR)" && $(TCLSH_NATIVE) zipper.tcl + @echo cd {$(OUT_DIR)} > "$(OUT_DIR)\zipper.tcl" + @echo file delete -force {$(@F)} >> "$(OUT_DIR)\zipper.tcl" + @echo zipfs mkzip {$(@F)} {$(LIBTCLVFSSUBDIR)} {$(LIBTCLVFSSUBDIR)} >> "$(OUT_DIR)\zipper.tcl" + @$(TCLSH_NATIVE) "$(OUT_DIR)/zipper.tcl" pkgs: @for /d %d in ($(PKGSDIR)\*) do \ -- cgit v0.12 From a9a53e870a12e2cfda6c5e46a9245f1dc6e7313e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 25 Apr 2024 08:24:05 +0000 Subject: (cherry-pick): Fix building of libtclzip for out-of-source builds --- win/makefile.vc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/win/makefile.vc b/win/makefile.vc index d2b2a69..b79e8ee 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -463,7 +463,8 @@ TCLSTUBOBJS = \ TOMMATHDIR = $(ROOT)\libtommath PKGSDIR = $(ROOT)\pkgs -LIBTCLVFS = $(OUT_DIR)\libtcl.vfs +LIBTCLVFSSUBDIR = libtcl.vfs +LIBTCLVFS = $(OUT_DIR)\$(LIBTCLVFSSUBDIR) # Additional include and C macro definitions for the implicit rules # defined in rules.vc @@ -663,9 +664,10 @@ $(TCLSCRIPTZIP): $(TCLLIB) $(TCLSH) dlls @$(COPY) $(TCLDDELIB) "$(LIBTCLVFS)\tcl_library\dde @$(COPY) $(TCLREGLIB) "$(LIBTCLVFS)\tcl_library\registry !endif - @echo file delete -force {$@} > "$(OUT_DIR)\zipper.tcl" - @echo zipfs mkzip {$@} {$(LIBTCLVFS)} {$(LIBTCLVFS)} >> "$(OUT_DIR)\zipper.tcl" - @cd "$(OUT_DIR)" && $(TCLSH_NATIVE) zipper.tcl + @echo cd {$(OUT_DIR)} > "$(OUT_DIR)\zipper.tcl" + @echo file delete -force {$(@F)} >> "$(OUT_DIR)\zipper.tcl" + @echo zipfs mkzip {$(@F)} {$(LIBTCLVFSSUBDIR)} {$(LIBTCLVFSSUBDIR)} >> "$(OUT_DIR)\zipper.tcl" + @$(TCLSH_NATIVE) "$(OUT_DIR)/zipper.tcl" pkgs: @for /d %d in ($(PKGSDIR)\*) do \ -- cgit v0.12 From 8c22d4c4632c6ed63d207e449ebaaf4f2e79ca61 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 25 Apr 2024 09:40:46 +0000 Subject: Make it more clear that TclpThreadExit() and Tcl_ExitThread() are TCL_NORETURN too. --- generic/tclThread.c | 2 +- unix/tclUnixThrd.c | 2 +- win/tclWinThrd.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/generic/tclThread.c b/generic/tclThread.c index de9fac9..233e380 100644 --- a/generic/tclThread.c +++ b/generic/tclThread.c @@ -457,7 +457,7 @@ TclFinalizeSynchronization(void) *---------------------------------------------------------------------- */ -void +TCL_NORETURN void Tcl_ExitThread( int status) { diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 9587590..3b2d7b4 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -342,7 +342,7 @@ Tcl_JoinThread( *---------------------------------------------------------------------- */ -void +TCL_NORETURN void TclpThreadExit( int status) { diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index e8d4d4d..d265821 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -291,7 +291,7 @@ Tcl_JoinThread( *---------------------------------------------------------------------- */ -void +TCL_NORETURN void TclpThreadExit( int status) { -- cgit v0.12 From 027af2ef3b26ace97d5ed0baaace75337aec2a4b Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 26 Apr 2024 11:27:58 +0000 Subject: Proposed fix for [1e48483c8b]: Use of non-standard C code in TCLBOOLWARNING --- generic/tclDecls.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index c786392..2135911 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4032,7 +4032,9 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_GetIndexFromObjStruct #undef Tcl_GetBooleanFromObj #undef Tcl_GetBoolean -#ifdef __GNUC__ +#if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) +# define TCLBOOLWARNING(boolPtr) (int)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})*0) + +#elif defined(__GNUC__) /* If this gives: "error: size of array ‘_bool_Var’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */ # define TCLBOOLWARNING(boolPtr) ({__attribute__((unused)) char _bool_Var[sizeof(*(boolPtr)) > sizeof(int) ? -1 : 1];}), #else -- cgit v0.12 From 239c968265b6015537c20d905e33717fc36ca73a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 26 Apr 2024 12:29:23 +0000 Subject: Slightly better --- generic/tclDecls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 2135911..69489de 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4033,7 +4033,7 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_GetBooleanFromObj #undef Tcl_GetBoolean #if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) -# define TCLBOOLWARNING(boolPtr) (int)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})*0) + +# define TCLBOOLWARNING(boolPtr) (void)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})), #elif defined(__GNUC__) /* If this gives: "error: size of array ‘_bool_Var’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */ # define TCLBOOLWARNING(boolPtr) ({__attribute__((unused)) char _bool_Var[sizeof(*(boolPtr)) > sizeof(int) ? -1 : 1];}), -- cgit v0.12 From 7748093580be5cc1b4af1f763d92c72e1b71472f Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Fri, 26 Apr 2024 17:02:05 +0000 Subject: Fix test for [9a8ce8af3d] --- tests/io.test | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/io.test b/tests/io.test index 5c0e5aa..2ed97d2 100644 --- a/tests/io.test +++ b/tests/io.test @@ -2479,13 +2479,25 @@ test io-28.6 { Should not produce a segmentation fault in a Tcl built with --enable-symbols and -DPURIFY -} debugpurify { +} -body { variable done variable res after 0 [list coroutine c1 apply [list {} { variable done - set chan [chan create w {apply {args { - list initialize finalize watch write configure blocking + set chan [chan create w {apply {{cmd chan args} { + switch $cmd { + blocking - finalize { + } + watch { + chan postevent $chan write + } + initialize { + list initialize finalize watch read write configure blocking + } + default { + error [list {unexpected command} $cmd] + } + } }}}] chan configure $chan -blocking 0 while 1 { @@ -2497,16 +2509,15 @@ test io-28.6 { } } [namespace current]]] vwait [namespace current]::done -return success -} success - + return success +} -result success test io-28.7 { close channel in read event handler Should not produce a segmentation fault in a Tcl built with --enable-symbols and -DPURIFY -} debugpurify { +} -body { variable done variable res after 0 [list coroutine c1 apply [list {} { @@ -2536,10 +2547,8 @@ test io-28.7 { } } [namespace current]]] vwait [namespace current]::done -return success -} success - - + return success +} -result success test io-29.1 {Tcl_WriteChars, channel not writable} { list [catch {puts stdin hello} msg] $msg -- cgit v0.12 From 1280f323661e060473600138ea6464e6de75eec1 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sat, 27 Apr 2024 11:58:12 +0000 Subject: This construct doens't work on MSVC --- generic/tclDecls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index b03e114..82bcfb1 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4349,7 +4349,7 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_GetIndexFromObjStruct #undef Tcl_GetBooleanFromObj #undef Tcl_GetBoolean -#if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) +#if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) && !defined(_MSC_VER) # define TCLBOOLWARNING(boolPtr) (void)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})), #elif defined(__GNUC__) /* If this gives: "error: size of array ‘_boolVar’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */ -- cgit v0.12 From 324230774110008bf8e07c39b10b399a7366c7d1 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 28 Apr 2024 17:18:29 +0000 Subject: Remove outdated comment --- generic/tclInt.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index 55391e0..7d2e848 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2420,10 +2420,6 @@ typedef struct Interp { * script in progress has been canceled thereby allowing * the evaluation stack for the interp to be fully * unwound. - * - * WARNING: For the sake of some extensions that have made use of former - * internal values, do not re-use the flag values 2 (formerly ERR_IN_PROGRESS) - * or 8 (formerly ERROR_CODE_SET). */ #define DELETED 1 -- cgit v0.12 From 04f69c9e2242a75f1a304974d4e7f4723f94d887 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 29 Apr 2024 11:51:43 +0000 Subject: Eliminate warnings in tclTest(Obj).c, caused by our -Wc++-compat flag. --- generic/tclTest.c | 2 ++ generic/tclTestObj.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/generic/tclTest.c b/generic/tclTest.c index 4312a08..ae55eaf 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -28,6 +28,8 @@ # define TCL_UTF_MAX 3 #endif #include "tclInt.h" +#undef TCLBOOLWARNING +#define TCLBOOLWARNING(boolPtr) /* needed here because we compile with -Wc++-compat */ #include "tclOO.h" #include diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 26f07d8..7e38e00 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -25,6 +25,8 @@ # include "tclTomMath.h" #endif #include "tclStringRep.h" +#undef TCLBOOLWARNING +#define TCLBOOLWARNING(boolPtr) /* needed here because we compile with -Wc++-compat */ #ifdef __GNUC__ /* -- cgit v0.12 From 92237847179354aba876b7908ecf77351b5ca6b6 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 30 Apr 2024 14:00:46 +0000 Subject: Check for C11 before using _Static_assert --- generic/tclDecls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 73ab405..5bec80e 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4032,7 +4032,7 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_GetIndexFromObjStruct #undef Tcl_GetBooleanFromObj #undef Tcl_GetBoolean -#if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) && !defined(_MSC_VER) +#if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) # define TCLBOOLWARNING(boolPtr) (void)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})), #elif defined(__GNUC__) /* If this gives: "error: size of array ‘_bool_Var’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */ -- cgit v0.12 From d99970d927187f3d341179fc56c4fe3fcb4cb899 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 2 May 2024 08:41:02 +0000 Subject: Add runtime PANIC when Tcl_GetBoolFromObj() violates size-restrictions, and compile-time checks are disabled with by using -std=c99 --- generic/tclDecls.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 5bec80e..7abb1c8 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4032,34 +4032,40 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_GetIndexFromObjStruct #undef Tcl_GetBooleanFromObj #undef Tcl_GetBoolean +#if !defined(TCLBOOLWARNING) #if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) # define TCLBOOLWARNING(boolPtr) (void)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})), -#elif defined(__GNUC__) +#elif defined(__GNUC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* If this gives: "error: size of array ‘_bool_Var’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */ # define TCLBOOLWARNING(boolPtr) ({__attribute__((unused)) char _bool_Var[sizeof(*(boolPtr)) > sizeof(int) ? -1 : 1];}), #else # define TCLBOOLWARNING(boolPtr) #endif +#endif /* !TCLBOOLWARNING */ #if defined(USE_TCL_STUBS) #define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \ (tclStubsPtr->tcl_GetIndexFromObjStruct((interp), (objPtr), (tablePtr), (offset), (msg), \ (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr))) #define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \ - (TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \ - Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr))) + ((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \ + ((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \ + (TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR))) #define Tcl_GetBoolean(interp, src, boolPtr) \ - (TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \ - Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr))) + ((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \ + ((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \ + (TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR))) #else #define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \ ((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), \ (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr))) #define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \ - (TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \ - Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr))) + ((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \ + ((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \ + (TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR))) #define Tcl_GetBoolean(interp, src, boolPtr) \ - (TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \ - Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr))) + ((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \ + ((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \ + (TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR))) #endif #ifdef TCL_MEM_DEBUG -- cgit v0.12 From 86166e1bf1f380fd197ce96246c9444dc49d0493 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 2 May 2024 09:10:06 +0000 Subject: Would checking for __STRICT_ANSI__ help? --- generic/tclDecls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 7abb1c8..ed95922 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4035,7 +4035,7 @@ extern const TclStubs *tclStubsPtr; #if !defined(TCLBOOLWARNING) #if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) # define TCLBOOLWARNING(boolPtr) (void)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})), -#elif defined(__GNUC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) /* If this gives: "error: size of array ‘_bool_Var’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */ # define TCLBOOLWARNING(boolPtr) ({__attribute__((unused)) char _bool_Var[sizeof(*(boolPtr)) > sizeof(int) ? -1 : 1];}), #else -- cgit v0.12 From e6b0159de2c46d5f5cd4899188728d7120f059ff Mon Sep 17 00:00:00 2001 From: oehhar Date: Thu, 2 May 2024 09:57:32 +0000 Subject: Ticket [cab08bbf04]: document "scan %llu" as valid --- doc/scan.n | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/scan.n b/doc/scan.n index 0c24fea..382abb8 100644 --- a/doc/scan.n +++ b/doc/scan.n @@ -117,9 +117,6 @@ The input substring must be a decimal integer. The integer value is truncated as required by the size modifier value, and the corresponding unsigned value for that truncated range is computed and stored in the variable as a decimal string. -The conversion makes no sense without reference to a truncation range, -so the size modifier \fBll\fR is not permitted in combination -with conversion character \fBu\fR. .TP \fBi\fR . -- cgit v0.12 From c7e0c0c16e0cedb793543a8b484a9b16cca290c6 Mon Sep 17 00:00:00 2001 From: mjanssen Date: Thu, 2 May 2024 21:29:19 +0000 Subject: [unknown] only calls shell command in interactive tclsh sessions --- doc/unknown.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/unknown.n b/doc/unknown.n index ee8a5be..8ea1e8e 100644 --- a/doc/unknown.n +++ b/doc/unknown.n @@ -47,7 +47,7 @@ The default implementation of \fBunknown\fR behaves as follows. It first calls the \fBauto_load\fR library procedure to load the command. If this succeeds, then it executes the original command with its original arguments. -If the auto-load fails then \fBunknown\fR calls \fBauto_execok\fR +If the auto-load fails and Tcl is run interactively then \fBunknown\fR calls \fBauto_execok\fR to see if there is an executable file by the name \fIcmd\fR. If so, it invokes the Tcl \fBexec\fR command with \fIcmd\fR and all the \fIargs\fR as arguments. -- cgit v0.12 From 08580d159a5b5112b72eecae5a1a7dff2abdfb3f Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Fri, 3 May 2024 16:23:22 +0000 Subject: Fix [a5f4a7aed8] - tcl::tm::path auto_index entry --- library/tclIndex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/tclIndex b/library/tclIndex index 2d4a957..871298f 100644 --- a/library/tclIndex +++ b/library/tclIndex @@ -95,7 +95,7 @@ set auto_index(::safe::RejectExcessColons) [list ::tcl::Pkg::source [file join $ set auto_index(::safe::VarName) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::Setup) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::setSyncMode) [list ::tcl::Pkg::source [file join $dir safe.tcl]] -set auto_index(::tcl::tmpath) [list ::tcl::Pkg::source [file join $dir tm.tcl]] +set auto_index(::tcl::tm::path) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::add) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::remove) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::list) [list ::tcl::Pkg::source [file join $dir tm.tcl]] -- cgit v0.12 From 9788573839698900297978ac52c242cf1403fd4e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sat, 4 May 2024 18:53:14 +0000 Subject: Possible solution for [3c26dec71e]: TCLX_y_TM_PATH - unspecified behaviour - change with 90b1rc --- library/tm.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/tm.tcl b/library/tm.tcl index 96bfe03..08afd4d 100644 --- a/library/tm.tcl +++ b/library/tm.tcl @@ -97,7 +97,7 @@ proc ::tcl::tm::add {args} { set newpaths $paths foreach p $args { - if {$p in $newpaths} { + if {($p eq "") || ($p in $newpaths)} { # Ignore a path already on the list. continue } -- cgit v0.12