diff options
-rw-r--r-- | ChangeLog | 63 | ||||
-rw-r--r-- | changes | 75 | ||||
-rw-r--r-- | generic/tclBasic.c | 5 | ||||
-rw-r--r-- | generic/tclExecute.c | 6 | ||||
-rw-r--r-- | generic/tclIOCmd.c | 2 | ||||
-rw-r--r-- | generic/tclInt.h | 31 | ||||
-rw-r--r-- | generic/tclLink.c | 8 | ||||
-rw-r--r-- | generic/tclListObj.c | 203 | ||||
-rw-r--r-- | generic/tclLiteral.c | 71 | ||||
-rwxr-xr-x | generic/tclStrToD.c | 2 | ||||
-rw-r--r-- | generic/tclStringObj.c | 19 | ||||
-rw-r--r-- | generic/tclTrace.c | 10 | ||||
-rw-r--r-- | generic/tclUtil.c | 25 | ||||
-rw-r--r-- | library/tcltest/tcltest.tcl | 4 | ||||
-rw-r--r-- | tests/fileSystem.test | 362 | ||||
-rw-r--r-- | tests/init.test | 2 | ||||
-rw-r--r-- | tests/namespace.test | 16 | ||||
-rw-r--r-- | tests/package.test | 2 | ||||
-rw-r--r-- | tests/socket.test | 4 |
19 files changed, 473 insertions, 437 deletions
@@ -1,10 +1,71 @@ -2011-05-27 Reinhard Max <max@suse.de> +2011-06-22 Reinhard Max <max@suse.de> + Merge from rmax-ipv6-branch: * unix/tclUnixSock.c: Fix [socket -async], so that all addresses returned by getaddrinfo() are tried, not just the first one. This requires the event loop to be running while the async connection is in progress. ***POTENTIAL INCOMPATIBILITY*** * tests/socket.test: Add a test for the above. + * doc/socket: Document the fact that -async needs the event loop + * generic/tclIOSock.c: AI_ADDRCONFIG is broken on HP-UX + +2011-06-21 Don Porter <dgp@users.sourceforge.net> + + * generic/tclLink.c: Prevent multiple links to a single Tcl + variable when calling Tcl_LinkVar(). [Bug 3317466] + +2011-06-13 Don Porter <dgp@users.sourceforge.net> + + * generic/tclStrToD.c: [Bug 3315098] Mem leak fix from Gustaf Neumann. + +2011-06-08 Andreas Kupries <andreask@activestate.com> + + * generic/tclExecute.c: Reverted the fix for [Bug 3274728] + committed on 2011-04-06 and replaced with one which is + 64bit-safe. The existing fix crashed tclsh on Windows 64bit. + +2011-06-08 Donal K. Fellows <dkf@users.sf.net> + + * tests/fileSystem.test: Reduce the amount of use of duplication of + complex code to perform common tests, and convert others to do the + test result check directly using Tcltest's own primitives. + +2011-06-06 Jan Nijtmans <nijtmans@users.sf.net> + + * tests/socket.test: Add test constraint, so 6.2 and 6.3 don't fail + when the machine does not have support for ip6. Follow-up to checkin + from 2011-05-11 by rmax. + +2011-06-02 Don Porter <dgp@users.sourceforge.net> + + * generic/tclBasic.c: Removed TclCleanupLiteralTable(), and old + * generic/tclInt.h: band-aid routine put in place while a fix + * generic/tclLiteral.c: for [Bug 994838] took shape. No longer needed. + +2011-06-02 Donal K. Fellows <dkf@users.sf.net> + + * generic/tclInt.h (TclInvalidateNsCmdLookup): [Bug 3185407]: Extend + the set of epochs that are potentially bumped when a command is + created, for a slight performance drop (in some circumstances) and + improved semantics. + +2011-06-01 Miguel Sofer <msofer@users.sf.net> + + * generic/tclBasic.c: Using the two free data elements in NRCommand to + store objc and objv - useful for debugging. + +2011-06-01 Jan Nijtmans <nijtmans@users.sf.net> + + * generic/tclUtil.c: Fix for [Bug 3309871]: Valgrind finds: + invalid read in TclMaxListLength() + +2011-05-31 Don Porter <dgp@users.sourceforge.net> + + * generic/tclInt.h: Use a complete growth algorithm for lists + * generic/tclListObj.c: so that length limits do not overconstrain + * generic/tclStringObj.c: by a factor of 2. [Bug 3293874]: + * generic/tclUtil.c: Fix includes rooting all growth routines + by default on a commone tunable parameter TCL_MIN_GROWTH. 2011-05-25 Don Porter <dgp@users.sourceforge.net> @@ -7867,4 +7867,77 @@ memory with buffer backup (ferrieux) 2010-11-09 (bug fix)[3105999] fixed memleak in OO var resolver (fellows) ---- Released 8.6b2, November 15, 2010 --- See ChangeLog for details --- +2010-11-15 (TIP 378)[3081184] improved TIP 280 performance (kupries) + +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-12 (platform) OpenBSD build improvements (cassoff) + +2010-12-17 (platform) Revisions to support rpm 4.4.2 (cassoff) + +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) + +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-24 tzdata updated to Olson's tzdata2011g (iyer) + +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) + +Many more Tcl built-in command errors now set an -errorcode. + +--- Released 8.6b2, XXX XX, 2011 --- See ChangeLog for details --- diff --git a/generic/tclBasic.c b/generic/tclBasic.c index d80731e..6791cbf 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -1428,7 +1428,6 @@ DeleteInterpProc( * table, as it will be freed later in this function without further use. */ - TclCleanupLiteralTable(interp, &iPtr->literalTable); TclHandleFree(iPtr->handle); TclTeardownNamespace(iPtr->globalNsPtr); @@ -4140,10 +4139,10 @@ TclNREvalObjv( */ if (iPtr->evalFlags & TCL_EVAL_REDIRECT) { - TclNRAddCallback(interp, NRCommand, NULL, INT2PTR(1), NULL, NULL); + TclNRAddCallback(interp, NRCommand, NULL, INT2PTR(1), objc, objv); iPtr->evalFlags &= ~TCL_EVAL_REDIRECT; } else { - TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); + TclNRAddCallback(interp, NRCommand, NULL, NULL, INT2PTR(objc), objv); } cmdPtrPtr = (Command **) &(TOP_CB(interp)->data[0]); diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 4fe65d7..84b0b63 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -172,7 +172,7 @@ typedef struct TEBCdata { ByteCode *codePtr; /* Constant until the BC returns */ /* -----------------------------------------*/ const unsigned char *pc; /* These fields are used on return TO this */ - unsigned long *catchTop; /* this level: they record the state when a */ + ptrdiff_t *catchTop; /* this level: they record the state when a */ int cleanup; /* new codePtr was received for NR */ Tcl_Obj *auxObjList; /* execution. */ int checkInterp; @@ -1917,7 +1917,7 @@ TclIncrObj( *---------------------------------------------------------------------- */ #define bcFramePtr (&TD->cmdFrame) -#define initCatchTop ((unsigned long *) (&TD->stack[-1])) +#define initCatchTop ((ptrdiff_t *) (&TD->stack[-1])) #define initTosPtr ((Tcl_Obj **) (initCatchTop+codePtr->maxExceptDepth)) #define esPtr (iPtr->execEnvPtr->execStackPtr) @@ -6265,7 +6265,7 @@ TEBCresume( while (auxObjList) { if ((catchTop != initCatchTop) && - (*catchTop>auxObjList->internalRep.ptrAndLongRep.value)) { + (*catchTop > ((ptrdiff_t) auxObjList->internalRep.ptrAndLongRep.value))) { break; } POP_TAUX_OBJ(); diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index 9294dd6..349814a 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -140,7 +140,7 @@ Tcl_PutsObjCmd( string = objv[3]; break; #if TCL_MAJOR_VERSION < 9 - } else if (strcmp(TclGetString(objv[2]), "nonewline") == 0) { + } else if (strcmp(TclGetString(objv[3]), "nonewline") == 0) { /* * The code below provides backwards compatibility with an old * form of the command that is no longer recommended or diff --git a/generic/tclInt.h b/generic/tclInt.h index 8f003be..ebc8bef 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2443,6 +2443,8 @@ typedef struct List { #define LIST_MAX \ (1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *))) +#define LIST_SIZE(numElems) \ + (unsigned)(sizeof(List) + (((numElems) - 1) * sizeof(Tcl_Obj *))) /* * Macro used to get the elements of a list object. @@ -2891,8 +2893,6 @@ MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp, MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd; MODULE_SCOPE int TclClearRootEnsemble(ClientData data[], Tcl_Interp *interp, int result); -MODULE_SCOPE void TclCleanupLiteralTable(Tcl_Interp *interp, - LiteralTable *tablePtr); MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, int num, int *loc); MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, @@ -4097,8 +4097,22 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, *---------------------------------------------------------------- */ +/* General tuning for minimum growth in Tcl growth algorithms */ +#ifndef TCL_MIN_GROWTH +# ifdef TCL_GROWTH_MIN_ALLOC + /* Support for any legacy tuners */ +# define TCL_MIN_GROWTH TCL_GROWTH_MIN_ALLOC +# else +# define TCL_MIN_GROWTH 1024 +# endif +#endif + +/* Token growth tuning, default to the general value. */ +#ifndef TCL_MIN_TOKEN_GROWTH +#define TCL_MIN_TOKEN_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Token) +#endif + #define TCL_MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token)) -#define TCL_MIN_TOKEN_GROWTH 50 #define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr) \ do { \ int needed = (used) + (append); \ @@ -4153,8 +4167,8 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, */ #define TclUtfToUniChar(str, chPtr) \ - ((((unsigned char) *(str)) < 0xC0) ? \ - ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \ + ((((unsigned char) *(str)) < 0xC0) ? \ + ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \ : Tcl_UtfToUniChar(str, chPtr)) /* @@ -4227,8 +4241,11 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, */ #define TclInvalidateNsCmdLookup(nsPtr) \ - if ((nsPtr)->numExportPatterns) { \ - (nsPtr)->exportLookupEpoch++; \ + if ((nsPtr)->numExportPatterns) { \ + (nsPtr)->exportLookupEpoch++; \ + } \ + if ((nsPtr)->commandPathLength) { \ + (nsPtr)->cmdRefEpoch++; \ } /* diff --git a/generic/tclLink.c b/generic/tclLink.c index 00010f3..a3b42bd 100644 --- a/generic/tclLink.c +++ b/generic/tclLink.c @@ -112,6 +112,14 @@ Tcl_LinkVar( Link *linkPtr; int code; + linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY, + LinkTraceProc, (ClientData) NULL); + if (linkPtr != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "variable '%s' is already linked", varName)); + return TCL_ERROR; + } + linkPtr = ckalloc(sizeof(Link)); linkPtr->interp = interp; linkPtr->varName = Tcl_NewStringObj(varName, -1); diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 506aa54..ac87628 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -45,6 +45,11 @@ const Tcl_ObjType tclListType = { UpdateStringOfList, /* updateStringProc */ SetListFromAny /* setFromAnyProc */ }; + +#ifndef TCL_MIN_ELEMENT_GROWTH +#define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *) +#endif + /* *---------------------------------------------------------------------- @@ -96,11 +101,11 @@ NewListIntRep( return NULL; } - listRepPtr = attemptckalloc(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj*))); + listRepPtr = attemptckalloc(LIST_SIZE(objc)); if (listRepPtr == NULL) { if (p) { Tcl_Panic("list creation failed: unable to alloc %u bytes", - (unsigned)(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *)))); + LIST_SIZE(objc)); } return NULL; } @@ -163,7 +168,7 @@ AttemptNewList( } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "list creation failed: unable to alloc %u bytes", - (unsigned)(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *))))); + LIST_SIZE(objc))); } Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } @@ -482,16 +487,13 @@ Tcl_ListObjGetElements( * * Tcl_ListObjAppendList -- * - * This function appends the objects in the list referenced by - * elemListPtr to the list object referenced by listPtr. If listPtr is - * not already a list object, an attempt will be made to convert it to - * one. + * This function appends the elements in the list value referenced by + * elemListPtr to the list value referenced by listPtr. * * Results: * The return value is normally TCL_OK. If listPtr or elemListPtr do not - * refer to list objects and they can not be converted to one, TCL_ERROR - * is returned and an error message is left in the interpreter's result - * if interp is not NULL. + * refer to list values, TCL_ERROR is returned and an error message is + * left in the interpreter's result if interp is not NULL. * * Side effects: * The reference counts of the elements in elemListPtr are incremented @@ -509,29 +511,24 @@ Tcl_ListObjAppendList( register Tcl_Obj *listPtr, /* List object to append elements to. */ Tcl_Obj *elemListPtr) /* List obj with elements to append. */ { - int listLen, objc, result; + int objc; Tcl_Obj **objv; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList"); } - result = TclListObjLength(interp, listPtr, &listLen); - if (result != TCL_OK) { - return result; - } - - result = TclListObjGetElements(interp, elemListPtr, &objc, &objv); - if (result != TCL_OK) { - return result; + /* Pull the elements to append from elemListPtr */ + if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) { + return TCL_ERROR; } /* - * Insert objc new elements starting after the lists's last element. + * Insert the new elements starting after the lists's last element. * Delete zero existing elements. */ - return Tcl_ListObjReplace(interp, listPtr, listLen, 0, objc, objv); + return Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv); } /* @@ -567,9 +564,8 @@ Tcl_ListObjAppendElement( Tcl_Obj *listPtr, /* List object to append objPtr to. */ Tcl_Obj *objPtr) /* Object to append to listPtr's list. */ { - register List *listRepPtr; - register Tcl_Obj **elemPtrs; - int numElems, numRequired, newMax, newSize, i; + register List *listRepPtr, *newPtr = NULL; + int numElems, numRequired, needGrow, isShared, attempt; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement"); @@ -590,41 +586,90 @@ Tcl_ListObjAppendElement( listRepPtr = ListRepPtr(listPtr); numElems = listRepPtr->elemCount; numRequired = numElems + 1 ; + needGrow = (numRequired > listRepPtr->maxElemCount); + isShared = (listRepPtr->refCount > 1); - /* - * If there is no room in the current array of element pointers, allocate - * a new, larger array and copy the pointers to it. If the List struct is - * shared, allocate a new one. - */ - - if (numRequired > listRepPtr->maxElemCount){ - newMax = 2 * numRequired; - newSize = sizeof(List) + ((newMax-1) * sizeof(Tcl_Obj *)); - } else { - newMax = listRepPtr->maxElemCount; - newSize = 0; + if (numRequired > LIST_MAX) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "max length of a Tcl list (%d elements) exceeded", + LIST_MAX)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + } + return TCL_ERROR; } - if (listRepPtr->refCount > 1) { - List *oldListRepPtr = listRepPtr; - Tcl_Obj **oldElems; + if (needGrow && !isShared) { + /* Need to grow + unshared intrep => try to realloc */ + attempt = 2 * numRequired; + if (attempt <= LIST_MAX) { + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr == NULL) { + attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; + if (attempt > LIST_MAX) { + attempt = LIST_MAX; + } + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr == NULL) { + attempt = numRequired; + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr) { + listRepPtr = newPtr; + listRepPtr->maxElemCount = attempt; + needGrow = 0; + } + } + if (isShared || needGrow) { + Tcl_Obj **dst, **src = &listRepPtr->elements; - listRepPtr = AttemptNewList(interp, newMax, NULL); - if (listRepPtr == NULL) { + /* + * Either we have a shared intrep and we must copy to write, + * or we need to grow and realloc attempts failed. + * Attempt intrep copy. + */ + attempt = 2 * numRequired; + newPtr = AttemptNewList(NULL, attempt, NULL); + if (newPtr == NULL) { + attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; + if (attempt > LIST_MAX) { + attempt = LIST_MAX; + } + newPtr = AttemptNewList(NULL, attempt, NULL); + } + if (newPtr == NULL) { + attempt = numRequired; + newPtr = AttemptNewList(interp, attempt, NULL); + } + if (newPtr == NULL) { + /* All growth attempts failed; throw the error */ return TCL_ERROR; } - oldElems = &oldListRepPtr->elements; - elemPtrs = &listRepPtr->elements; - for (i=0; i<numElems; i++) { - elemPtrs[i] = oldElems[i]; - Tcl_IncrRefCount(elemPtrs[i]); + + dst = &newPtr->elements; + newPtr->refCount++; + newPtr->canonicalFlag = listRepPtr->canonicalFlag; + newPtr->elemCount = listRepPtr->elemCount; + + if (isShared) { + /* + * The original intrep must remain undisturbed. + * Copy into the new one and bump refcounts + */ + while (numElems--) { + *dst = *src++; + Tcl_IncrRefCount(*dst++); + } + listRepPtr->refCount--; + } else { + /* Old intrep to be freed, re-use refCounts */ + memcpy(dst, src, (size_t) numElems * sizeof(Tcl_Obj *)); + + ckfree(listRepPtr); } - listRepPtr->elemCount = numElems; - listRepPtr->refCount++; - oldListRepPtr->refCount--; - } else if (newSize) { - listRepPtr = ckrealloc(listRepPtr, newSize); - listRepPtr->maxElemCount = newMax; + listRepPtr = newPtr; } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; @@ -633,8 +678,7 @@ Tcl_ListObjAppendElement( * the ref count for the (now shared) objPtr. */ - elemPtrs = &listRepPtr->elements; - elemPtrs[numElems] = objPtr; + *(&listRepPtr->elements + listRepPtr->elemCount) = objPtr; Tcl_IncrRefCount(objPtr); listRepPtr->elemCount++; @@ -898,9 +942,20 @@ Tcl_ListObjReplace( newMax = listRepPtr->maxElemCount; } - listRepPtr = AttemptNewList(interp, newMax, NULL); + listRepPtr = AttemptNewList(NULL, newMax, NULL); if (listRepPtr == NULL) { - return TCL_ERROR; + unsigned int limit = LIST_MAX - numRequired; + unsigned int extra = numRequired - numElems + + TCL_MIN_ELEMENT_GROWTH; + int growth = (int) ((extra > limit) ? limit : extra); + + listRepPtr = AttemptNewList(NULL, numRequired + growth, NULL); + if (listRepPtr == NULL) { + listRepPtr = AttemptNewList(interp, numRequired, NULL); + if (listRepPtr == NULL) { + return TCL_ERROR; + } + } } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; @@ -1544,7 +1599,6 @@ TclListObjSetElement( listRepPtr = ListRepPtr(listPtr); elemCount = listRepPtr->elemCount; - elemPtrs = &listRepPtr->elements; /* * Ensure that the index is in bounds. @@ -1565,25 +1619,30 @@ TclListObjSetElement( */ if (listRepPtr->refCount > 1) { - List *oldListRepPtr = listRepPtr; - Tcl_Obj **oldElemPtrs = elemPtrs; - int i; + Tcl_Obj **dst, **src = &listRepPtr->elements; + List *newPtr = AttemptNewList(NULL, listRepPtr->maxElemCount, NULL); - listRepPtr = AttemptNewList(interp, listRepPtr->maxElemCount, NULL); - if (listRepPtr == NULL) { - return TCL_ERROR; + if (newPtr == NULL) { + newPtr = AttemptNewList(interp, elemCount, NULL); + if (newPtr == NULL) { + return TCL_ERROR; + } } - listRepPtr->canonicalFlag = oldListRepPtr->canonicalFlag; - elemPtrs = &listRepPtr->elements; - for (i=0; i < elemCount; i++) { - elemPtrs[i] = oldElemPtrs[i]; - Tcl_IncrRefCount(elemPtrs[i]); + newPtr->refCount++; + newPtr->elemCount = elemCount; + newPtr->canonicalFlag = listRepPtr->canonicalFlag; + + dst = &newPtr->elements; + while (elemCount--) { + *dst = *src++; + Tcl_IncrRefCount(*dst++); } - listRepPtr->refCount++; - listRepPtr->elemCount = elemCount; - listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; - oldListRepPtr->refCount--; + + listRepPtr->refCount--; + + listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr = newPtr; } + elemPtrs = &listRepPtr->elements; /* * Add a reference to the new list element. diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c index 72c4577..3a9f8e1 100644 --- a/generic/tclLiteral.c +++ b/generic/tclLiteral.c @@ -75,77 +75,6 @@ TclInitLiteralTable( /* *---------------------------------------------------------------------- * - * TclCleanupLiteralTable -- - * - * This function frees the internal representation of every literal in a - * literal table. It is called prior to deleting an interp, so that - * variable refs will be cleaned up properly. - * - * Results: - * None. - * - * Side effects: - * Each literal in the table has its internal representation freed. - * - *---------------------------------------------------------------------- - */ - -void -TclCleanupLiteralTable( - Tcl_Interp *interp, /* Interpreter containing literals to purge */ - LiteralTable *tablePtr) /* Points to the literal table being - * cleaned. */ -{ - int i; - LiteralEntry *entryPtr; /* Pointer to the current entry in the hash - * table of literals. */ - LiteralEntry *nextPtr; /* Pointer to the next entry in the bucket. */ - Tcl_Obj *objPtr; /* Pointer to a literal object whose internal - * rep is being freed. */ - const Tcl_ObjType *typePtr; /* Pointer to the object's type. */ - int didOne; /* Flag for whether we've removed a literal in - * the current bucket. */ - -#ifdef TCL_COMPILE_DEBUG - TclVerifyGlobalLiteralTable((Interp *) interp); -#endif /* TCL_COMPILE_DEBUG */ - - for (i=0 ; i<tablePtr->numBuckets ; i++) { - /* - * It is tempting simply to walk each hash bucket once and delete the - * internal representations of each literal in turn. It's also wrong. - * The problem is that freeing a literal's internal representation can - * delete other literals to which it refers, making nextPtr invalid. - * So each time we free an internal rep, we start its bucket over - * again. - */ - - do { - didOne = 0; - entryPtr = tablePtr->buckets[i]; - while (entryPtr != NULL) { - objPtr = entryPtr->objPtr; - nextPtr = entryPtr->nextPtr; - typePtr = objPtr->typePtr; - if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { - if (objPtr->bytes == NULL) { - Tcl_Panic("%s: literal without a string rep", - "TclCleanupLiteralTable"); - } - objPtr->typePtr = NULL; - typePtr->freeIntRepProc(objPtr); - didOne = 1; - break; - } - entryPtr = nextPtr; - } - } while (didOne); - } -} - -/* - *---------------------------------------------------------------------- - * * TclDeleteLiteralTable -- * * This function frees up everything associated with a literal table diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 59192e9..16f11d2 100755 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -3820,7 +3820,7 @@ ShorteningBignumConversion( if (m2plus > m2minus) { mp_clear(&mplus); } - mp_clear_multi(&b, &mminus, &temp, NULL); + mp_clear_multi(&b, &mminus, &temp, &dig, &S, NULL); *s = '\0'; *decpt = k; if (endPtr) { diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 0f6eff7..ab62359 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -152,8 +152,7 @@ typedef struct String { * * Attempt to allocate 2 * (originalLength + appendLength) * On failure: - * attempt to allocate originalLength + 2*appendLength + - * TCL_GROWTH_MIN_ALLOC + * attempt to allocate originalLength + 2*appendLength + TCL_MIN_GROWTH * * This algorithm allows very good performance, as it rapidly increases the * memory allocated for a given string, which minimizes the number of @@ -166,20 +165,20 @@ typedef struct String { * cover the request, but which hopefully will be less than the total * available memory. * - * The addition of TCL_GROWTH_MIN_ALLOC allows for efficient handling of very + * The addition of TCL_MIN_GROWTH allows for efficient handling of very * small appends. Without this extra slush factor, a sequence of several small * appends would cause several memory allocations. As long as - * TCL_GROWTH_MIN_ALLOC is a reasonable size, we can avoid that behavior. + * TCL_MIN_GROWTH is a reasonable size, we can avoid that behavior. * * The growth algorithm can be tuned by adjusting the following parameters: * - * TCL_GROWTH_MIN_ALLOC Additional space, in bytes, to allocate when + * TCL_MIN_GROWTH Additional space, in bytes, to allocate when * the double allocation has failed. Default is - * 1024 (1 kilobyte). + * 1024 (1 kilobyte). See tclInt.h. */ -#ifndef TCL_GROWTH_MIN_ALLOC -#define TCL_GROWTH_MIN_ALLOC 1024 +#ifndef TCL_MIN_UNICHAR_GROWTH +#define TCL_MIN_UNICHAR_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_UniChar) #endif static void @@ -214,7 +213,7 @@ GrowStringBuffer( */ unsigned int limit = INT_MAX - needed; - unsigned int extra = needed - objPtr->length + TCL_GROWTH_MIN_ALLOC; + unsigned int extra = needed - objPtr->length + TCL_MIN_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); attempt = needed + growth; @@ -265,7 +264,7 @@ GrowUnicodeBuffer( unsigned int limit = STRING_MAXCHARS - needed; unsigned int extra = needed - stringPtr->numChars - + TCL_GROWTH_MIN_ALLOC/sizeof(Tcl_UniChar); + + TCL_MIN_UNICHAR_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); attempt = needed + growth; diff --git a/generic/tclTrace.c b/generic/tclTrace.c index a60a80b..13359ee 100644 --- a/generic/tclTrace.c +++ b/generic/tclTrace.c @@ -2883,6 +2883,16 @@ Tcl_UntraceVar2( * The code below makes it possible to delete traces while traces are * active: it makes sure that the deleted trace won't be processed by * TclCallVarTraces. + * + * Caveat (Bug 3062331): When an unset trace handler on a variable + * tries to delete a different unset trace handler on the same variable, + * the results may be surprising. When variable unset traces fire, the + * traced variable is already gone. So the TclLookupVar() call above + * will not find that variable, and not finding it will never reach here + * to perform the deletion. This means callers of Tcl_UntraceVar*() + * attempting to delete unset traces from within the handler of another + * unset trace have to account for the possibility that their call to + * Tcl_UntraceVar*() is a no-op. */ for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL; diff --git a/generic/tclUtil.c b/generic/tclUtil.c index f7f4bf4..6f36dad 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -409,7 +409,7 @@ TclMaxListLength( bytes++; numBytes -= (numBytes != -1); } while (numBytes && TclIsSpaceProc(*bytes)); - if (numBytes == 0) { + if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) { break; } /* (*bytes) is non-space; return to counting state */ @@ -1778,31 +1778,16 @@ Tcl_ConcatObj( } } if (i == objc) { - Tcl_Obj **listv; - int listc; - resPtr = NULL; for (i = 0; i < objc; i++) { - /* - * Tcl_ListObjAppendList could be used here, but this saves us a - * bit of type checking (since we've already done it). Use of - * INT_MAX tells us to always put the new stuff on the end. It - * will be set right in Tcl_ListObjReplace. - * Note that all objs at this point are either lists or have an - * empty string rep. - */ - objPtr = objv[i]; if (objPtr->bytes && objPtr->length == 0) { continue; } - TclListObjGetElements(NULL, objPtr, &listc, &listv); - if (listc) { - if (resPtr) { - Tcl_ListObjReplace(NULL, resPtr, INT_MAX, 0, listc, listv); - } else { - resPtr = TclListObjCopy(NULL, objPtr); - } + if (resPtr) { + Tcl_ListObjAppendList(NULL, resPtr, objPtr); + } else { + resPtr = TclListObjCopy(NULL, objPtr); } } if (!resPtr) { diff --git a/library/tcltest/tcltest.tcl b/library/tcltest/tcltest.tcl index ad61f9c..af809f6 100644 --- a/library/tcltest/tcltest.tcl +++ b/library/tcltest/tcltest.tcl @@ -797,8 +797,8 @@ namespace eval tcltest { proc loadIntoSlaveInterpreter {slave args} { variable Version - interp eval $slave [list set ::argv $args] - interp eval $slave [list package require tcltest $Version] + interp eval $slave [package ifneeded tcltest $Version] + interp eval $slave "tcltest::configure {*}{$args}" interp alias $slave ::tcltest::ReportToMaster \ {} ::tcltest::ReportedFromSlave } diff --git a/tests/fileSystem.test b/tests/fileSystem.test index 6ab554b..4191713 100644 --- a/tests/fileSystem.test +++ b/tests/fileSystem.test @@ -31,44 +31,39 @@ makeDirectory [file join dir.dir dirinside.dir] makeFile "test file in directory" [file join dir.dir inside.file] testConstraint unusedDrive 0 -set drive {} -if {[testConstraint win]} { - set vols [string map [list :/ {}] [file volumes]] - for {set i 0} {$i < 26} {incr i} { - set drive [format %c [expr {$i + 65}]] - if {$drive ni $vols} { - testConstraint unusedDrive 1 - break +testConstraint moreThanOneDrive 0 +apply {{} { + # The variables 'drive' and 'drives' will be used below. + variable drive {} drives {} + if {[testConstraint win]} { + set vols [string map [list :/ {}] [file volumes]] + for {set i 0} {$i < 26} {incr i} { + set drive [format %c [expr {$i + 65}]] + if {$drive ni $vols} { + testConstraint unusedDrive 1 + break + } } - } - unset i vols - # The variable 'drive' will be used below -} -testConstraint moreThanOneDrive 0 -set drives [list] -if {[testConstraint win]} { - set dir [pwd] - foreach vol [file volumes] { - if {![catch {cd $vol}]} { - lappend drives $vol - } - } - if {[llength $drives] > 1} { - testConstraint moreThanOneDrive 1 + set dir [pwd] + try { + foreach vol [file volumes] { + if {![catch {cd $vol}]} { + lappend drives $vol + } + } + testConstraint moreThanOneDrive [llength $drives] + } finally { + cd $dir + } } - # The variable 'drives' will be used below - unset vol - cd $dir - unset dir -} +} ::tcl::test::fileSystem} proc testPathEqual {one two} { if {$one eq $two} { - return 1 - } else { - return "not equal: $one $two" + return "ok" } + return "not equal: $one $two" } testConstraint hasLinks [expr {![catch { @@ -100,19 +95,19 @@ test filesystem-1.1 {link normalisation} {hasLinks} { test filesystem-1.2 {link normalisation} {hasLinks unix} { testPathEqual [file normalize [file join gorp.file foo]] \ [file normalize [file join link.file foo]] -} {1} +} ok test filesystem-1.3 {link normalisation} {hasLinks} { testPathEqual [file normalize [file join dir.dir foo]] \ [file normalize [file join dir.link foo]] -} {1} +} ok test filesystem-1.4 {link normalisation} {hasLinks} { testPathEqual [file normalize [file join dir.dir inside.file]] \ [file normalize [file join dir.link inside.file]] -} {1} +} ok test filesystem-1.5 {link normalisation} {hasLinks} { testPathEqual [file normalize [file join dir.dir linkinside.file]] \ [file normalize [file join dir.dir linkinside.file]] -} {1} +} ok test filesystem-1.6 {link normalisation} {hasLinks} { string equal [file normalize [file join dir.dir linkinside.file]] \ [file normalize [file join dir.link inside.file]] @@ -120,28 +115,29 @@ test filesystem-1.6 {link normalisation} {hasLinks} { test filesystem-1.7 {link normalisation} {hasLinks unix} { testPathEqual [file normalize [file join dir.link linkinside.file foo]] \ [file normalize [file join dir.dir inside.file foo]] -} {1} +} ok test filesystem-1.8 {link normalisation} {hasLinks} { string equal [file normalize [file join dir.dir linkinside.filefoo]] \ [file normalize [file join dir.link inside.filefoo]] } {0} -test filesystem-1.9 {link normalisation} {unix hasLinks} { +test filesystem-1.9 {link normalisation} -setup { file delete -force dir.link +} -constraints {unix hasLinks} -body { file link dir.link [file nativename dir.dir] testPathEqual [file normalize [file join dir.dir linkinside.file foo]] \ [file normalize [file join dir.link inside.file foo]] -} {1} +} -result ok test filesystem-1.10 {link normalisation: double link} {unix hasLinks} { file link dir2.link dir.link testPathEqual [file normalize [file join dir.dir linkinside.file foo]] \ [file normalize [file join dir2.link inside.file foo]] -} {1} +} ok makeDirectory dir2.file test filesystem-1.11 {link normalisation: double link, back in tree} {unix hasLinks} { file link [file join dir2.file dir2.link] [file join .. dir2.link] testPathEqual [file normalize [file join dir.dir linkinside.file foo]] \ [file normalize [file join dir2.file dir2.link inside.file foo]] -} {1} +} ok test filesystem-1.12 {file new native path} {} { for {set i 0} {$i < 10} {incr i} { foreach f [lsort [glob -nocomplain -type l *]] { @@ -198,39 +194,35 @@ test filesystem-1.25 {file normalisation} {win unusedDrive} { test filesystem-1.25.1 {file normalisation} {win unusedDrive} { file normalize ${drive}:/./.././..\\..\\a\\bb } "${drive}:/a/bb" -test filesystem-1.26 {link normalisation: link and ..} {hasLinks} { +test filesystem-1.26 {link normalisation: link and ..} -setup { file delete -force dir2.link +} -constraints {hasLinks} -body { set dir [file join dir2 foo bar] file mkdir $dir file link dir2.link [file join dir2 foo bar] - set res [list [file normalize [file join dir2 foo x]] \ - [file normalize [file join dir2.link .. x]]] - testPathEqual [lindex $res 0] [lindex $res 1] -} 1 + testPathEqual [file normalize [file join dir2 foo x]] \ + [file normalize [file join dir2.link .. x]] +} -result ok test filesystem-1.27 {file normalisation: up and down with ..} { set dir [file join dir2 foo bar] file mkdir $dir set dir2 [file join dir2 .. dir2 foo .. foo bar] - set res [list [file normalize $dir] [file normalize $dir2]] - set res2 [list [file exists $dir] [file exists $dir2]] - if {![string equal [lindex $res 0] [lindex $res 1]]} { - set res "exists: $res2, $res not equal" - } else { - set res "ok: $res2" - } -} {ok: 1 1} -test filesystem-1.28 {link normalisation: link with .. and ..} {hasLinks} { + list [testPathEqual [file normalize $dir] [file normalize $dir2]] \ + [file exists $dir] [file exists $dir2] +} {ok 1 1} +test filesystem-1.28 {link normalisation: link with .. and ..} -setup { file delete -force dir2.link +} -constraints {hasLinks} -body { set dir [file join dir2 foo bar] file mkdir $dir set to [file join dir2 .. dir2 foo .. foo bar] file link dir2.link $to - set res [list [file normalize [file join dir2 foo x]] \ - [file normalize [file join dir2.link .. x]]] - testPathEqual [lindex $res 0] [lindex $res 1] -} 1 -test filesystem-1.29 {link normalisation: link with ..} {hasLinks} { + testPathEqual [file normalize [file join dir2 foo x]] \ + [file normalize [file join dir2.link .. x]] +} -result ok +test filesystem-1.29 {link normalisation: link with ..} -setup { file delete -force dir2.link +} -constraints {hasLinks} -body { set dir [file join dir2 foo bar] file mkdir $dir set to [file join dir2 .. dir2 foo .. foo bar] @@ -240,11 +232,11 @@ test filesystem-1.29 {link normalisation: link with ..} {hasLinks} { return "$res must not contain '..'" } return "ok" -} {ok} +} -result {ok} test filesystem-1.29.1 {link normalisation with two consecutive links} {hasLinks} { testPathEqual [file normalize [file join dir.link dirinside.link abc]] \ [file normalize [file join dir.dir dirinside.dir abc]] -} {1} +} ok file delete -force dir2.file file delete -force dir2.link file delete -force link.file dir.link @@ -277,208 +269,96 @@ test filesystem-1.33 {link normalisation: link near filesystem root} {testsetpla if {[testConstraint testsetplatform]} { testsetplatform $platform } -test filesystem-1.34 {file normalisation with '/./'} { - set res [file normalize /foo/bar/anc/./.tml] - if {[string first "/./" $res] != -1} { - set res "normalization of /foo/bar/anc/./.tml is: $res" - } else { - set res "ok" - } - set res -} {ok} -test filesystem-1.35 {file normalisation with '/./'} { - set res [file normalize /ffo/bar/anc/./foo/.tml] - if {[string first "/./" $res] != -1 || ([regsub -all "foo" $res "" reg] == 2)} { - set res "normalization of /ffo/bar/anc/./foo/.tml is: $res" - } else { - set res "ok" - } - set res -} {ok} -test filesystem-1.36 {file normalisation with '/./'} { - set res [file normalize /foo/bar/anc/././asdasd/.tml] - if {[string first "/./" $res] != -1 || ([regsub -all "asdasd" $res "" reg] == 2) } { - set res "normalization of /foo/bar/anc/././asdasd/.tml is: $res" - } else { - set res "ok" - } - set res -} {ok} -test filesystem-1.37 {file normalisation with '/./'} { +test filesystem-1.34 {file normalisation with '/./'} -body { + file normalize /foo/bar/anc/./.tml +} -match regexp -result {^(?:(?!/\./).)*$} +test filesystem-1.35a {file normalisation with '/./'} -body { + file normalize /ffo/bar/anc/./foo/.tml +} -match regexp -result {^(?:(?!/\./).)*$} +test filesystem-1.35b {file normalisation with '/./'} { + llength [regexp -all foo [file normalize /ffo/bar/anc/./foo/.tml]] +} 1 +test filesystem-1.36a {file normalisation with '/./'} -body { + file normalize /foo/bar/anc/././asdasd/.tml +} -match regexp -result {^(?:(?!/\./).)*$} +test filesystem-1.36b {file normalisation with '/./'} { + llength [regexp -all asdasd [file normalize /foo/bar/anc/././asdasd/.tml]] +} 1 +test filesystem-1.37 {file normalisation with '/./'} -body { set fname "/abc/./def/./ghi/./asda/.././.././asd/x/../../../../....." - set res [file norm $fname] - if {[string first "//" $res] != -1} { - set res "normalization of $fname is: $res" - } else { - set res "ok" - } - set res -} {ok} -test filesystem-1.38 {file normalisation with volume relative} \ - {win moreThanOneDrive} { - set path "[string range [lindex $drives 0] 0 1]foo" + file norm $fname +} -match regexp -result {^(?:[^/]|/(?:[^/]|$))+$} +test filesystem-1.38 {file normalisation with volume relative} -setup { set dir [pwd] +} -constraints {win moreThanOneDrive} -body { + set path "[string range [lindex $drives 0] 0 1]foo" cd [lindex $drives 1] - set res [file norm $path] + file norm $path +} -cleanup { cd $dir - set res -} "[lindex $drives 0]foo" -test filesystem-1.39 {file normalisation with volume relative} {win} { - set drv C:/ - set dir [lindex [glob -type d -dir $drv *] 0] +} -result "[lindex $drives 0]foo" +test filesystem-1.39 {file normalisation with volume relative} -setup { set old [pwd] - cd $dir - set res [file norm [string range $drv 0 1]] +} -constraints {win} -body { + set drv C:/ + cd [lindex [glob -type d -dir $drv *] 0] + file norm [string range $drv 0 1] +} -cleanup { cd $old - if {[string index $res end] eq "/"} { - set res "Bad normalized path: $res" - } else { - set res "ok" - } -} {ok} +} -match glob -result {*[^/]} test filesystem-1.40 {file normalisation with repeated separators} { - set a [file norm foo////bar] - set b [file norm foo/bar] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm foo////bar] [file norm foo/bar] +} ok test filesystem-1.41 {file normalisation with repeated separators} {win} { - set a [file norm foo\\\\\\bar] - set b [file norm foo/bar] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm foo\\\\\\bar] [file norm foo/bar] +} ok test filesystem-1.42 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/..] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/..] [file norm /] +} ok test filesystem-1.42.1 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/../] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/../] [file norm /] +} ok test filesystem-1.43 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/foo/../..] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/foo/../..] [file norm /] +} ok test filesystem-1.43.1 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/foo/../../] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/foo/../../] [file norm /] +} ok test filesystem-1.44 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/foo/../../bar] - set b [file norm /bar] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/foo/../../bar] [file norm /bar] +} ok test filesystem-1.45 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/../../bar] - set b [file norm /bar] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/../../bar] [file norm /bar] +} ok test filesystem-1.46 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /xxx/../bar] - set b [file norm /bar] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /xxx/../bar] [file norm /bar] +} ok test filesystem-1.47 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /..] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /..] [file norm /] +} ok test filesystem-1.48 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /../] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /../] [file norm /] +} ok test filesystem-1.49 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /.] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /.] [file norm /] +} ok test filesystem-1.50 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /./] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /./] [file norm /] +} ok test filesystem-1.51 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /../..] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /../..] [file norm /] +} ok test filesystem-1.51.1 {file normalisation .. beyond root (Bug 1379287)} { - set a [file norm /../../] - set b [file norm /] - if {![string equal $a $b]} { - set res "Paths should be equal: $a , $b" - } else { - set res "ok" - } -} {ok} + testPathEqual [file norm /../../] [file norm /] +} ok test filesystem-2.0 {new native path} {unix} { foreach f [lsort [glob -nocomplain /usr/bin/c*]] { catch {file readlink $f} } # If we reach here we've succeeded. We used to crash above. - expr 1 -} {1} + return ok +} ok # Make sure the testfilesystem hasn't been registered. if {[testConstraint testfilesystem]} { @@ -511,28 +391,28 @@ test filesystem-4.0 {testfilesystem} -constraints testfilesystem -body { set filesystemReport {} file exists foo testfilesystem 0 - set filesystemReport + return $filesystemReport } -match glob -result {*{access foo}} test filesystem-4.1 {testfilesystem} -constraints testfilesystem -body { testfilesystem 1 set filesystemReport {} catch {file stat foo bar} testfilesystem 0 - set filesystemReport + return $filesystemReport } -match glob -result {*{stat foo}} test filesystem-4.2 {testfilesystem} -constraints testfilesystem -body { testfilesystem 1 set filesystemReport {} catch {file lstat foo bar} testfilesystem 0 - set filesystemReport + return $filesystemReport } -match glob -result {*{lstat foo}} test filesystem-4.3 {testfilesystem} -constraints testfilesystem -body { testfilesystem 1 set filesystemReport {} catch {glob *} testfilesystem 0 - set filesystemReport + return $filesystemReport } -match glob -result {*{matchindirectory *}*} test filesystem-5.1 {cache and ~} -constraints testfilesystem -setup { @@ -1041,7 +921,7 @@ test filesystem-9.9 {path objects and glob and file tail and tilde} -setup { # ---------------------------------------------------------------------- cleanupTests -unset -nocomplain drive +unset -nocomplain drive drives } namespace delete ::tcl::test::fileSystem return diff --git a/tests/init.test b/tests/init.test index 62b3af2..79d9a04 100644 --- a/tests/init.test +++ b/tests/init.test @@ -11,7 +11,7 @@ # this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { - package require tcltest 2 + package require tcltest 2.3.3 namespace import -force ::tcltest::* } diff --git a/tests/namespace.test b/tests/namespace.test index 9d7cb59..f4e50bc 100644 --- a/tests/namespace.test +++ b/tests/namespace.test @@ -2517,6 +2517,22 @@ test namespace-51.17 {resolution epoch handling: Bug 2898722} -setup { catch {rename ::c {}} unset result } -result {A 1 . A A . B B . B B . B B . B B . G G} +test namespace-51.18 {Bug 3185407} -setup { + namespace eval ::test_ns_1 {} +} -body { + namespace eval ::test_ns_1 { + variable result {} + namespace eval ns {proc foo {} {}} + namespace eval ns2 {proc foo {} {}} + namespace path {ns ns2} + variable x foo + lappend result [namespace which $x] + proc foo {} {} + lappend result [namespace which $x] + } +} -cleanup { + namespace delete ::test_ns_1 +} -result {::test_ns_1::ns::foo ::test_ns_1::foo} # TIP 181 - namespace unknown tests test namespace-52.1 {unknown: default handler ::unknown} { diff --git a/tests/package.test b/tests/package.test index 55aaf2b..bd57e86 100644 --- a/tests/package.test +++ b/tests/package.test @@ -13,7 +13,7 @@ # this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { - package require tcltest 2 + package require tcltest 2.3.3 namespace import -force ::tcltest::* } diff --git a/tests/socket.test b/tests/socket.test index e36914f..7f5c5c2 100644 --- a/tests/socket.test +++ b/tests/socket.test @@ -822,7 +822,7 @@ test socket_$af-6.2 { readable fileevent on server socket } -setup { set sock [socket -server dummy 0] -} -body { +} -constraints [list socket supported_$af] -body { fileevent $sock readable dummy } -cleanup { close $sock @@ -830,7 +830,7 @@ test socket_$af-6.2 { test socket_$af-6.3 {writable fileevent on server socket} -setup { set sock [socket -server dummy 0] -} -body { +} -constraints [list socket supported_$af] -body { fileevent $sock writable dummy } -cleanup { close $sock |