From 50a76c2d9e2b751c9ca040cbb8308ca088f3d034 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 4 Sep 2003 16:44:11 +0000 Subject: * 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. --- ChangeLog | 11 +++++++++++ doc/SplitList.3 | 14 +++++++++++++- generic/tcl.h | 15 +++++++++++---- generic/tclDictObj.c | 8 +++++--- generic/tclListObj.c | 5 +++-- generic/tclResult.c | 8 +++++++- generic/tclUtil.c | 37 ++++++++++++++++++++++++++++++++----- 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 + + * 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 * 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; -- cgit v0.12