summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--doc/SplitList.314
-rw-r--r--generic/tcl.h15
-rw-r--r--generic/tclDictObj.c8
-rw-r--r--generic/tclListObj.c5
-rw-r--r--generic/tclResult.c8
-rw-r--r--generic/tclUtil.c37
7 files changed, 82 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index c2173c6..af5ba8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2003-09-04 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/SplitList.3: Implementation of TIP 148. Fixes [Bug 489537].
+ * generic/tcl.h: Updated Tcl_ConvertCountedElement() to quote
+ * generic/tclUtil.c: the leading "#" character of all list elements
+ unless the TCL_DONT_QUOTE_HASH flag is passed in.
+
+ * generic/tclDictObj.c: Updated Tcl_ConvertCountedElement() callers
+ * generic/tclListObj.c: to pass in the TCL_DONT_QUOTE_HASH flags
+ * generic/tclResult.c: when appropriate.
+
2003-08-31 Don Porter <dgp@users.sourceforge.net>
* doc/return.n: Updated [return] docs to cover new TIP 90 features.
diff --git a/doc/SplitList.3 b/doc/SplitList.3
index c046af5..a237293 100644
--- a/doc/SplitList.3
+++ b/doc/SplitList.3
@@ -5,7 +5,7 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
-'\" RCS: @(#) $Id: SplitList.3,v 1.6 2002/01/25 20:40:55 dgp Exp $
+'\" RCS: @(#) $Id: SplitList.3,v 1.7 2003/09/04 16:44:12 dgp Exp $
'\"
.so man.macros
.TH Tcl_SplitList 3 8.0 Tcl "Tcl Library Procedures"
@@ -166,6 +166,18 @@ used to generate a portion of an argument for a Tcl command.
In this case, surrounding \fIsrc\fR with curly braces would cause
the command not to be parsed correctly.
.PP
+.VS 8.5
+By default, \fBTcl_ConvertElement\fR will use quoting in its output
+to be sure the first character of an element is not the hash
+character (``#''). This is to be sure the first element of any list
+passed to \fBeval\fR is not mis-parsed as the beginning of a comment.
+When a list element is not the first element of a list, this quoting
+is not necessary. When the caller can be sure that the element is
+not the first element of a list, it can disable quoting of the leading
+hash character by OR-ing the flag value returned by \fBTcl_ScanElement\fR
+with \fBTCL_DONT_QUOTE_HASH\fR.
+.VE 8.5
+.PP
\fBTcl_ScanCountedElement\fR and \fBTcl_ConvertCountedElement\fR are
the same as \fBTcl_ScanElement\fR and \fBTcl_ConvertElement\fR, except
the length of string \fIsrc\fR is specified by the \fIlength\fR
diff --git a/generic/tcl.h b/generic/tcl.h
index ccfa8c1..692cbf3 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tcl.h,v 1.164 2003/08/27 06:58:43 davygrvy Exp $
+ * RCS: @(#) $Id: tcl.h,v 1.165 2003/09/04 16:44:12 dgp Exp $
*/
#ifndef _TCL
@@ -994,11 +994,18 @@ typedef struct Tcl_DString {
#define TCL_INTEGER_SPACE 24
/*
- * Flag that may be passed to Tcl_ConvertElement to force it not to
- * output braces (careful! if you change this flag be sure to change
- * the definitions at the front of tclUtil.c).
+ * Flag values passed to Tcl_ConvertElement.
+ * TCL_DONT_USE_BRACES forces it not to enclose the element in braces, but
+ * to use backslash quoting instead.
+ * TCL_DONT_QUOTE_HASH disables the default quoting of the '#' character.
+ * It is safe to leave the hash unquoted when the element is not the
+ * first element of a list, and this flag can be used by the caller to
+ * indicated that condition.
+ * (careful! if you change these flag values be sure to change the
+ * definitions at the front of tclUtil.c).
*/
#define TCL_DONT_USE_BRACES 1
+#define TCL_DONT_QUOTE_HASH 8
/*
* Flag that may be passed to Tcl_GetIndexFromObj to force it to disallow
diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
index 8a9ab53..364ffcd 100644
--- a/generic/tclDictObj.c
+++ b/generic/tclDictObj.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclDictObj.c,v 1.10 2003/05/07 15:26:27 dkf Exp $
+ * RCS: @(#) $Id: tclDictObj.c,v 1.11 2003/09/04 16:44:12 dgp Exp $
*/
#include "tclInt.h"
@@ -293,12 +293,14 @@ UpdateStringOfDict(dictPtr)
i+=2,hPtr=Tcl_NextHashEntry(&search)) {
keyPtr = (Tcl_Obj *) Tcl_GetHashKey(&dict->table, hPtr);
elem = Tcl_GetStringFromObj(keyPtr, &length);
- dst += Tcl_ConvertCountedElement(elem, length, dst, flagPtr[i]);
+ dst += Tcl_ConvertCountedElement(elem, length, dst,
+ flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH) );
*(dst++) = ' ';
valuePtr = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
elem = Tcl_GetStringFromObj(valuePtr, &length);
- dst += Tcl_ConvertCountedElement(elem, length, dst, flagPtr[i+1]);
+ dst += Tcl_ConvertCountedElement(elem, length, dst,
+ flagPtr[i+1] | TCL_DONT_QUOTE_HASH);
*(dst++) = ' ';
}
if (flagPtr != localFlags) {
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index cdd8cb9..2fb083c 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclListObj.c,v 1.13 2002/01/07 23:09:13 dgp Exp $
+ * RCS: @(#) $Id: tclListObj.c,v 1.14 2003/09/04 16:44:12 dgp Exp $
*/
#include "tclInt.h"
@@ -1641,7 +1641,8 @@ UpdateStringOfList(listPtr)
dst = listPtr->bytes;
for (i = 0; i < numElems; i++) {
elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
- dst += Tcl_ConvertCountedElement(elem, length, dst, flagPtr[i]);
+ dst += Tcl_ConvertCountedElement(elem, length, dst,
+ flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH) );
*dst = ' ';
dst++;
}
diff --git a/generic/tclResult.c b/generic/tclResult.c
index 22cf249..7c4d696 100644
--- a/generic/tclResult.c
+++ b/generic/tclResult.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclResult.c,v 1.7 2003/07/16 21:24:12 hobbs Exp $
+ * RCS: @(#) $Id: tclResult.c,v 1.8 2003/09/04 16:44:12 dgp Exp $
*/
#include "tclInt.h"
@@ -634,6 +634,12 @@ Tcl_AppendElement(interp, string)
iPtr->appendUsed++;
*dst = ' ';
dst++;
+ /*
+ * If we need a space to separate this element from preceding
+ * stuff, then this element will not lead a list, and need not
+ * have it's leading '#' quoted.
+ */
+ flags |= TCL_DONT_QUOTE_HASH;
}
iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
}
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index 4321833..10cddf2 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUtil.c,v 1.42 2003/08/27 21:31:05 dgp Exp $
+ * RCS: @(#) $Id: tclUtil.c,v 1.43 2003/09/04 16:44:12 dgp Exp $
*/
#include "tclInt.h"
@@ -29,9 +29,9 @@ char *tclNativeExecutableName = NULL;
/*
* The following values are used in the flags returned by Tcl_ScanElement
- * and used by Tcl_ConvertElement. The value TCL_DONT_USE_BRACES is also
- * defined in tcl.h; make sure its value doesn't overlap with any of the
- * values below.
+ * and used by Tcl_ConvertElement. The values TCL_DONT_USE_BRACES and
+ * TCL_DONT_QUOTE_HASH are defined in tcl.h; make sure neither value
+ * overlaps with any of the values below.
*
* TCL_DONT_USE_BRACES - 1 means the string mustn't be enclosed in
* braces (e.g. it contains unmatched braces,
@@ -43,6 +43,12 @@ char *tclNativeExecutableName = NULL;
* enclosing the entire argument in braces.
* BRACES_UNMATCHED - 1 means that braces aren't properly matched
* in the argument.
+ * TCL_DONT_QUOTE_HASH - 1 means the caller insists that a leading
+ * hash character ('#') should *not* be quoted.
+ * This is appropriate when the caller can
+ * guarantee the element is not the first element
+ * of a list, so [eval] cannot mis-parse the
+ * element as a comment.
*/
#define USE_BRACES 2
@@ -733,6 +739,9 @@ Tcl_ConvertCountedElement(src, length, dst, flags)
return 2;
}
lastChar = src + length;
+ if ((*src == '#') && !(flags & TCL_DONT_QUOTE_HASH)) {
+ flags |= USE_BRACES;
+ }
if ((flags & USE_BRACES) && !(flags & TCL_DONT_USE_BRACES)) {
*p = '{';
p++;
@@ -755,6 +764,17 @@ Tcl_ConvertCountedElement(src, length, dst, flags)
p += 2;
src++;
flags |= BRACES_UNMATCHED;
+ } else if ((*src == '#') && !(flags & TCL_DONT_QUOTE_HASH)) {
+ /*
+ * Leading '#' could be seen by [eval] as the start of
+ * a comment, if on the first element of a list, so
+ * quote it.
+ */
+
+ p[0] = '\\';
+ p[1] = '#';
+ p += 2;
+ src++;
}
for (; src != lastChar; src++) {
switch (*src) {
@@ -877,7 +897,8 @@ Tcl_Merge(argc, argv)
result = (char *) ckalloc((unsigned) numChars);
dst = result;
for (i = 0; i < argc; i++) {
- numChars = Tcl_ConvertElement(argv[i], dst, flagPtr[i]);
+ numChars = Tcl_ConvertElement(argv[i], dst,
+ flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH) );
dst += numChars;
*dst = ' ';
dst++;
@@ -1556,6 +1577,12 @@ Tcl_DStringAppendElement(dsPtr, string)
*dst = ' ';
dst++;
dsPtr->length++;
+ /*
+ * If we need a space to separate this element from preceding
+ * stuff, then this element will not lead a list, and need not
+ * have it's leading '#' quoted.
+ */
+ flags |= TCL_DONT_QUOTE_HASH;
}
dsPtr->length += Tcl_ConvertCountedElement(string, strSize, dst, flags);
return dsPtr->string;