From 865f11be2c3ee4294408debefcd72de0fc6b2772 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 14 Jun 2017 21:42:38 +0000 Subject: [f2336c116b] Move pragmas to make gcc happy; it is pickier than clang. --- unix/tclUnixSock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 2353f94..c0df035 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -730,6 +730,8 @@ TcpClose2Proc( */ #ifndef NEED_FAKE_RFC2553 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" static inline int IPv6AddressNeedsNumericRendering( struct in6_addr addr) @@ -743,16 +745,14 @@ IPv6AddressNeedsNumericRendering( * at least some versions of OSX. */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" if (!IN6_IS_ADDR_V4MAPPED(&addr)) { -#pragma GCC diagnostic pop return 0; } return (addr.s6_addr[12] == 0 && addr.s6_addr[13] == 0 && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0); } +#pragma GCC diagnostic pop #endif /* NEED_FAKE_RFC2553 */ static void -- cgit v0.12 From affb7e28db4184bd802837ba53146b985adee9ba Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 14 Jun 2017 21:49:08 +0000 Subject: [9c058c5803e30d02] Correction to cross linking in dict(n)'s SEE ALSO section. --- doc/dict.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dict.n b/doc/dict.n index fecad85..cd7e94c 100644 --- a/doc/dict.n +++ b/doc/dict.n @@ -437,7 +437,7 @@ puts $foo # prints: \fIa b foo {a b} bar 2 baz 3\fR .CE .SH "SEE ALSO" -append(n), array(n), foreach(n), mapeach(n), incr(n), list(n), lappend(n), set(n) +append(n), array(n), foreach(n), incr(n), list(n), lappend(n), lmap(n), set(n) .SH KEYWORDS dictionary, create, update, lookup, iterate, filter, map '\" Local Variables: -- cgit v0.12 From f7860f65a494888a46e377831ba0419de5f364d9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 15 Jun 2017 09:13:51 +0000 Subject: Make panic in TclParseNumber() work when IEEE_FLOATING_POINT is not defined. --- generic/tclStrToD.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 67b6482..2091928 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -1183,9 +1183,9 @@ TclParseNumber( case sNA: case sNANPAREN: case sNANHEX: +#endif Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'", acceptState, bytes); -#endif case BINARY: shift = numTrailZeros; if (!significandOverflow && significandWide != 0 && -- cgit v0.12 From bcc916d762591d6fae72ea0ba0ac0c747bcc0173 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 11:47:46 +0000 Subject: Better define the meaning of "first" and "last". --- generic/tclStringObj.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index aa99545..0a38836 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2848,8 +2848,10 @@ TclStringCatObjv( Tcl_Obj **objPtrPtr) { Tcl_Obj *objPtr, *objResultPtr, * const *ov; - int oc, length = 0, binary = 1, first = 0, last = 0; + int oc, length = 0, binary = 1; int allowUniChar = 1, requestUniChar = 0; + int first = objc - 1; /* Index of first value possibly not empty */ + int last = 0; /* Index of last value possibly not empty */ /* assert ( objc >= 0 ) */ @@ -2981,9 +2983,9 @@ TclStringCatObjv( } while (--oc); } - if (last == first /*|| length == 0 */) { + if (last <= first /*|| length == 0 */) { /* Only one non-empty value or zero length; return first */ - /* NOTE: (length == 0) implies (last == first) */ + /* NOTE: (length == 0) implies (last <= first) */ *objPtrPtr = objv[first]; return TCL_OK; } -- cgit v0.12 From fdf4b7c6eef91298ad2b24e4f622229eb10cc9b5 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 12:56:03 +0000 Subject: Extend cases where string rep generation can be prevented. --- generic/tclStringObj.c | 16 ++++++++++++++++ tests/string.test | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 0a38836..261e01f 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2966,9 +2966,25 @@ TclStringCatObjv( Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ if (numBytes == 0) { + if (pendingPtr && pendingPtr->bytes) { + /* + * Generating string rep of objPtr also + * generated string rep of pendingPtr. + */ + if (pendingPtr->length) { + /* Can this happen? */ + goto foo; + } else { + /* string-29.14 */ + first = objc - 1; + last = 0; + pendingPtr = NULL; + } + } continue; } last = objc - oc; +foo: if (pendingPtr) { Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */ pendingPtr = NULL; diff --git a/tests/string.test b/tests/string.test index 9c43f29..7b02928 100644 --- a/tests/string.test +++ b/tests/string.test @@ -2024,6 +2024,21 @@ test string-29.13 {string cat, efficiency} -body { tcl::unsupported::representation [string cat \ [encoding convertto utf-8 {}] [encoding convertto utf-8 {}] [list x]] } -match glob -result {*, string representation "x"} +test string-29.14 {string cat, efficiency} -setup { + set e [encoding convertto utf-8 {}] +} -cleanup { + unset e +} -body { + tcl::unsupported::representation [string cat $e $e [list x]] +} -match glob -result {*no string representation} +test string-29.15 {string cat, efficiency} -setup { + set e [encoding convertto utf-8 {}] + set f [encoding convertto utf-8 {}] +} -cleanup { + unset e f +} -body { + tcl::unsupported::representation [string cat $e $f $e $f [list x]] +} -match glob -result {*no string representation} -- cgit v0.12 From b146fea6c309eba008fed11685a34076a44d1ce0 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 14:43:16 +0000 Subject: Rework the logic. Equivalent function. --- generic/tclStringObj.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 261e01f..587ba76 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2965,32 +2965,22 @@ TclStringCatObjv( } else { Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ - if (numBytes == 0) { - if (pendingPtr && pendingPtr->bytes) { - /* - * Generating string rep of objPtr also - * generated string rep of pendingPtr. - */ - if (pendingPtr->length) { - /* Can this happen? */ - goto foo; - } else { - /* string-29.14 */ - first = objc - 1; - last = 0; - pendingPtr = NULL; - } - } + if (numBytes) { + last = objc - oc; + } else if (pendingPtr == NULL || pendingPtr->bytes == NULL) { continue; } - last = objc - oc; -foo: if (pendingPtr) { Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */ pendingPtr = NULL; } if (length == 0) { - first = last; + if (numBytes) { + first = last; + } else { + first = objc - 1; + last = 0; + } } else if (numBytes > INT_MAX - length) { goto overflow; } -- cgit v0.12 From 214ae82fc9c08209d8d3ed426f86a72b10410c4e Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 14:46:56 +0000 Subject: Use local variables. --- generic/tclStringObj.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 587ba76..8155711 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2847,7 +2847,7 @@ TclStringCatObjv( Tcl_Obj * const objv[], Tcl_Obj **objPtrPtr) { - Tcl_Obj *objPtr, *objResultPtr, * const *ov; + Tcl_Obj *objResultPtr, * const *ov; int oc, length = 0, binary = 1; int allowUniChar = 1, requestUniChar = 0; int first = objc - 1; /* Index of first value possibly not empty */ @@ -2872,7 +2872,7 @@ TclStringCatObjv( ov = objv, oc = objc; do { - objPtr = *ov++; + Tcl_Obj *objPtr = *ov++; if (objPtr->bytes) { /* Value has a string rep. */ @@ -2908,7 +2908,7 @@ TclStringCatObjv( /* Result will be pure byte array. Pre-size it */ ov = objv; oc = objc; do { - objPtr = *ov++; + Tcl_Obj *objPtr = *ov++; if (objPtr->bytes == NULL) { int numBytes; @@ -2929,7 +2929,7 @@ TclStringCatObjv( /* Result will be pure Tcl_UniChar array. Pre-size it. */ ov = objv; oc = objc; do { - objPtr = *ov++; + Tcl_Obj *objPtr = *ov++; if ((objPtr->bytes == NULL) || (objPtr->length)) { int numChars; @@ -2954,7 +2954,7 @@ TclStringCatObjv( do { int numBytes; - objPtr = *ov++; + Tcl_Obj *objPtr = *ov++; if ((length == 0) && (objPtr->bytes == NULL) && !pendingPtr) { /* No string rep; Take the chance we can avoid making it */ -- cgit v0.12 From 44fb1d2c660ae623debe25e06b4ce34c30791141 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 15:51:12 +0000 Subject: Factor out and simplify loop scanning leading known empty values. --- generic/tclStringObj.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 8155711..870696e 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2952,6 +2952,26 @@ TclStringCatObjv( /* Result will be concat of string reps. Pre-size it. */ ov = objv; oc = objc; do { + /* assert ( pendingPtr == NULL ) */ + /* assert ( length == 0 ) */ + + Tcl_Obj *objPtr = *ov++; + + if (objPtr->bytes == NULL) { + /* No string rep; Take the chance we can avoid making it */ + pendingPtr = objPtr; + } else { + Tcl_GetStringFromObj(objPtr, &length); /* PANIC? */ + } + } while (--oc && (length == 0) && (pendingPtr == NULL)); + + if (oc) { + + /* assert ( length > 0 || pendingPtr != NULL ) */ + + first = last = objc - oc - 1; + + do { int numBytes; Tcl_Obj *objPtr = *ov++; @@ -2987,6 +3007,7 @@ TclStringCatObjv( length += numBytes; } } while (--oc); + } } if (last <= first /*|| length == 0 */) { -- cgit v0.12 From 58311abbb709a5255f685e5d45ae837b0e9c7251 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 16:07:48 +0000 Subject: Split loop into two cases for further simplification. --- generic/tclStringObj.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 870696e..be686cf 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2965,11 +2965,52 @@ TclStringCatObjv( } } while (--oc && (length == 0) && (pendingPtr == NULL)); + first = last = objc - oc - 1; + + while (oc && (length == 0)) { + int numBytes; + Tcl_Obj *objPtr = *ov++; + + /* assert ( pendingPtr != NULL ) <-- aiming for */ + + if ((length == 0) && (objPtr->bytes == NULL) && !pendingPtr) { + /* No string rep; Take the chance we can avoid making it */ + + last = objc - oc; + first = last; + pendingPtr = objPtr; + } else { + + Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ + if (numBytes) { + last = objc - oc; + } else if (pendingPtr == NULL || pendingPtr->bytes == NULL) { + --oc; + continue; + } + if (pendingPtr) { + Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */ + pendingPtr = NULL; + } + if (length == 0) { + if (numBytes) { + first = last; + } else { + first = objc - 1; + last = 0; + } + } else if (numBytes > INT_MAX - length) { + goto overflow; + } + length += numBytes; + } + --oc; + } + if (oc) { - /* assert ( length > 0 || pendingPtr != NULL ) */ + /* assert ( length > 0 ) */ - first = last = objc - oc - 1; do { int numBytes; -- cgit v0.12 From 5425edf173bf9efcf17955623e5be64196eae2fa Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 16:23:22 +0000 Subject: Simplify the final loop when we know we're generating strings for all. --- generic/tclStringObj.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index be686cf..51d6c13 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3007,48 +3007,22 @@ TclStringCatObjv( --oc; } - if (oc) { - - /* assert ( length > 0 ) */ - - - do { + while (oc) { int numBytes; - Tcl_Obj *objPtr = *ov++; - if ((length == 0) && (objPtr->bytes == NULL) && !pendingPtr) { - /* No string rep; Take the chance we can avoid making it */ + /* assert ( length > 0 && pendingPtr == NULL ) */ + Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ + if (numBytes) { last = objc - oc; - first = last; - pendingPtr = objPtr; - } else { - - Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ - if (numBytes) { - last = objc - oc; - } else if (pendingPtr == NULL || pendingPtr->bytes == NULL) { - continue; - } - if (pendingPtr) { - Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */ - pendingPtr = NULL; - } - if (length == 0) { - if (numBytes) { - first = last; - } else { - first = objc - 1; - last = 0; - } - } else if (numBytes > INT_MAX - length) { + if (numBytes > INT_MAX - length) { goto overflow; } length += numBytes; } - } while (--oc); - } + --oc; + } } if (last <= first /*|| length == 0 */) { -- cgit v0.12 From b4133af5ee0c655f627443f04d50f492eedc58fa Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 16 Jun 2017 19:54:57 +0000 Subject: Another reworking, now with comments. --- generic/tclStringObj.c | 79 +++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 51d6c13..41dad65 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2947,65 +2947,72 @@ TclStringCatObjv( } } while (--oc); } else { - Tcl_Obj *pendingPtr = NULL; - /* Result will be concat of string reps. Pre-size it. */ ov = objv; oc = objc; do { - /* assert ( pendingPtr == NULL ) */ - /* assert ( length == 0 ) */ + Tcl_Obj *pendingPtr = NULL; - Tcl_Obj *objPtr = *ov++; + /* + * Loop until a possibly non-empty value is reached. + * Keep string rep generation pending when possible. + */ - if (objPtr->bytes == NULL) { - /* No string rep; Take the chance we can avoid making it */ - pendingPtr = objPtr; - } else { - Tcl_GetStringFromObj(objPtr, &length); /* PANIC? */ - } - } while (--oc && (length == 0) && (pendingPtr == NULL)); + do { + /* assert ( pendingPtr == NULL ) */ + /* assert ( length == 0 ) */ - first = last = objc - oc - 1; + Tcl_Obj *objPtr = *ov++; - while (oc && (length == 0)) { - int numBytes; - Tcl_Obj *objPtr = *ov++; + if (objPtr->bytes == NULL) { + /* No string rep; Take the chance we can avoid making it */ + pendingPtr = objPtr; + } else { + Tcl_GetStringFromObj(objPtr, &length); /* PANIC? */ + } + } while (--oc && (length == 0) && (pendingPtr == NULL)); + + /* + * Either we found a possibly non-empty value, and we + * remember this index as the first and last such value so + * far seen, or (oc == 0) and all values are known empty, + * so first = last = objc - 1 signals the right quick return. + */ - /* assert ( pendingPtr != NULL ) <-- aiming for */ + first = last = objc - oc - 1; - if ((length == 0) && (objPtr->bytes == NULL) && !pendingPtr) { - /* No string rep; Take the chance we can avoid making it */ + if (oc && (length == 0)) { + int numBytes; - last = objc - oc; - first = last; - pendingPtr = objPtr; - } else { + /* assert ( pendingPtr != NULL ) */ + + /* + * There's a pending value followed by more values. + * Loop over remaining values generating strings until + * a non-empty value is found, or the pending value gets + * its string generated. + */ + + do { + Tcl_Obj *objPtr = *ov++; + Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ + } while (--oc && numBytes == 0 && pendingPtr->bytes == NULL); - Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ if (numBytes) { - last = objc - oc; - } else if (pendingPtr == NULL || pendingPtr->bytes == NULL) { - --oc; - continue; + last = objc -oc -1; } - if (pendingPtr) { - Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */ - pendingPtr = NULL; + if (oc || numBytes) { + Tcl_GetStringFromObj(pendingPtr, &length); } if (length == 0) { if (numBytes) { first = last; - } else { - first = objc - 1; - last = 0; } } else if (numBytes > INT_MAX - length) { goto overflow; } length += numBytes; } - --oc; - } + } while (oc && (length == 0)); while (oc) { int numBytes; -- cgit v0.12