Tcl Source Code

Artifact [4749bcfab2]
Login

Artifact 4749bcfab2480b6d0832b9a8b5798f9a84899e51:

Attachment "411825.patch" to ticket [411825ffff] added by dgp 2003-08-28 02:59:29.
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.36.2.2
diff -u -r1.36.2.2 tclUtil.c
--- generic/tclUtil.c	16 Jul 2003 21:25:07 -0000	1.36.2.2
+++ generic/tclUtil.c	27 Aug 2003 19:51:55 -0000
@@ -2001,42 +2001,53 @@
     CONST char *end;		/* End of string (place where space will
 				 * be added, if appropriate). */
 {
-    Tcl_UniChar ch;
-
     /*
      * A space is needed unless either
      * (a) we're at the start of the string, or
-     * (b) the trailing characters of the string consist of one or more
-     *     open curly braces preceded by a space or extending back to
-     *     the beginning of the string.
-     * (c) the trailing characters of the string consist of a space
-     *	   preceded by a character other than backslash.
      */
-
     if (end == start) {
 	return 0;
     }
+
+    /*
+     * (b) we're at the start of a nested list-element, quoted with an
+     *     open curly brace; we can be nested arbitrarily deep, so long
+     *     as the first curly brace starts an element, so backtrack over
+     *     open curly braces that are trailing characters of the string; and
+     */
+
     end = Tcl_UtfPrev(end, start);
-    if (*end != '{') {
-	Tcl_UtfToUniChar(end, &ch);
-	/*
-	 * Direct char comparison on next line is safe as it is with
-	 * a character in the ASCII subset, and so single-byte in UTF8.
-	 */
-	if (Tcl_UniCharIsSpace(ch) && ((end == start) || (end[-1] != '\\'))) {
-	    return 0;
-	}
-	return 1;
-    }
-    do {
+    while (*end == '{') {
 	if (end == start) {
 	    return 0;
 	}
 	end = Tcl_UtfPrev(end, start);
-    } while (*end == '{');
-    Tcl_UtfToUniChar(end, &ch);
-    if (Tcl_UniCharIsSpace(ch)) {
-	return 0;
+    }
+
+    /*
+     * (c) the trailing character of the string is already a list-element
+     *     separator (according to TclFindElement); that is, one of these
+     *     characters:
+     *     	\u0009	\t	TAB
+     *     	\u000A	\n	NEWLINE
+     *     	\u000B	\v	VERTICAL TAB
+     *     	\u000C	\f	FORM FEED
+     *     	\u000D	\r	CARRIAGE RETURN
+     *     	\u0020		SPACE
+     *     with the condition that the penultimate character is not a
+     *     backslash.
+     */
+
+    switch (*end) {
+	case ' ':
+        case '\f':
+        case '\n':
+        case '\r':
+        case '\t':
+        case '\v':
+	    if ((end == start) || (end[-1] != '\\')) {
+		return 0;
+	    }
     }
     return 1;
 }
Index: tests/util.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/util.test,v
retrieving revision 1.10.4.1
diff -u -r1.10.4.1 util.test
--- tests/util.test	27 Aug 2003 17:56:46 -0000	1.10.4.1
+++ tests/util.test	27 Aug 2003 19:51:56 -0000
@@ -342,6 +342,26 @@
     testdstring element foo
     llength [testdstring get]
 } 2
+test util-8.5 {TclNeedSpace - correct UTF8 handling} testdstring {
+    # Note that in this test TclNeedSpace actually gets it wrong,
+    # claiming we need a space when we really do not.  Extra space
+    # between list elements is harmless though, and better to have
+    # extra space in really weird string reps of lists, than to
+    # invest the effort required to make TclNeedSpace foolproof.
+    testdstring free
+    testdstring append {\\ } -1
+    testdstring element foo
+    list [llength [testdstring get]] [string length [testdstring get]]
+} {2 7}
+test util-8.6 {TclNeedSpace - correct UTF8 handling} testdstring {
+    # Another example of TclNeedSpace harmlessly getting it wrong.
+    testdstring free
+    testdstring append {\\ } -1
+    testdstring append \{ -1
+    testdstring element foo
+    testdstring append \} -1
+    list [llength [testdstring get]] [string length [testdstring get]]
+} {2 9}
 
 # cleanup
 ::tcltest::cleanupTests