summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--generic/tclCmdMZ.c4
-rw-r--r--generic/tclCompCmds.c19
-rw-r--r--generic/tclDictObj.c12
-rw-r--r--generic/tclListObj.c8
-rw-r--r--generic/tclParse.c34
-rw-r--r--generic/tclUtil.c40
7 files changed, 83 insertions, 55 deletions
diff --git a/ChangeLog b/ChangeLog
index d7610a5..1e512ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
2011-05-02 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCmdMZ.c: Revised TclFindElement() interface. The
+ * generic/tclDictObj.c: final argument had been bracePtr, the address
+ * generic/tclListObj.c: of a boolean var, where the caller can be told
+ * generic/tclParse.c: whether or not the parsed list element was
+ * generic/tclUtil.c: enclosed in braces. In practice, no callers
+ really care about that. What the callers really want to know is
+ whether the list element value exists as a literal substring of the
+ string being parsed, or whether a call to TclCopyAndCollpase() is
+ needed to produce the list element value. Now the final argument
+ is changed to do what callers actually need. This is a better fit
+ for the calls in tclParse.c, where now a good deal of post-processing
+ checking for "naked backslashes" is no longer necessary.
+ ***POTENTIAL INCOMPATIBILITY***
+ For any callers calling in via the internal stubs table who really
+ do use the final argument explicitly to check for the enclosing brace
+ scenario. Simply looking for the braces where they must be is the
+ revision available to those callers, and it will backport cleanly.
+
+ * generic/tclCompCmds.c: New TclFindElement() is also a better
+ fit for the [switch] compiler.
+
* generic/tclInt.h: Replace TclCountSpaceRuns() with
* generic/tclListObj.c: TclMaxListLength() which is the function we
* generic/tclUtil.c: actually want.
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index 5390cf0..60a9414 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -1621,7 +1621,7 @@ StringIsCmd(
*/
const char *elemStart, *nextElem;
- int lenRemain, elemSize, hasBrace;
+ int lenRemain, elemSize;
register const char *p;
string1 = TclGetStringFromObj(objPtr, &length1);
@@ -1630,7 +1630,7 @@ StringIsCmd(
for (p=string1, lenRemain=length1; lenRemain > 0;
p=nextElem, lenRemain=end-nextElem) {
if (TCL_ERROR == TclFindElement(NULL, p, lenRemain,
- &elemStart, &nextElem, &elemSize, &hasBrace)) {
+ &elemStart, &nextElem, &elemSize, NULL)) {
Tcl_Obj *tmpStr;
/*
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index 2b6f84c..81fd615 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -4211,11 +4211,12 @@ TclCompileSwitchCmd(
numWords = 0;
while (numBytes > 0) {
- CONST char *start, *prevBytes = bytes;
- int size, braced;
+ CONST char *prevBytes = bytes;
+ int literal;
- if (TCL_OK != TclFindElement(NULL, bytes, numBytes, &start,
- &bytes, &size, &braced)) {
+ if (TCL_OK != TclFindElement(NULL, bytes, numBytes,
+ &(bodyTokenArray[numWords].start), &bytes,
+ &(bodyTokenArray[numWords].size), &literal) || !literal) {
abort:
ckfree((char *) bodyToken);
ckfree((char *) bodyTokenArray);
@@ -4225,19 +4226,9 @@ TclCompileSwitchCmd(
}
bodyTokenArray[numWords].type = TCL_TOKEN_TEXT;
- bodyTokenArray[numWords].start = start;
- bodyTokenArray[numWords].size = size;
bodyTokenArray[numWords].numComponents = 0;
bodyToken[numWords] = bodyTokenArray + numWords;
- if (!braced) {
- while (size--) {
- if (*start++ == '\\') {
- goto abort;
- }
- }
- }
-
/*
* TIP #280: Now determine the line the list element starts on
* (there is no need to do it earlier, due to the possibility of
diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
index 912e7a9..8b44137 100644
--- a/generic/tclDictObj.c
+++ b/generic/tclDictObj.c
@@ -558,7 +558,7 @@ SetDictFromAny(
{
char *string, *s;
const char *elemStart, *nextElem;
- int lenRemain, length, elemSize, hasBrace, result, isNew;
+ int lenRemain, length, elemSize, result, isNew;
char *limit; /* Points just after string's last byte. */
register const char *p;
register Tcl_Obj *keyPtr, *valuePtr;
@@ -639,8 +639,10 @@ SetDictFromAny(
for (p = string, lenRemain = length;
lenRemain > 0;
p = nextElem, lenRemain = (limit - nextElem)) {
+ int literal;
+
result = TclFindElement(interp, p, lenRemain,
- &elemStart, &nextElem, &elemSize, &hasBrace);
+ &elemStart, &nextElem, &elemSize, &literal);
if (result != TCL_OK) {
goto errorExit;
}
@@ -654,7 +656,7 @@ SetDictFromAny(
*/
s = ckalloc((unsigned) elemSize + 1);
- if (hasBrace) {
+ if (literal) {
memcpy(s, elemStart, (size_t) elemSize);
s[elemSize] = 0;
} else {
@@ -672,7 +674,7 @@ SetDictFromAny(
}
result = TclFindElement(interp, p, lenRemain,
- &elemStart, &nextElem, &elemSize, &hasBrace);
+ &elemStart, &nextElem, &elemSize, &literal);
if (result != TCL_OK) {
TclDecrRefCount(keyPtr);
goto errorExit;
@@ -687,7 +689,7 @@ SetDictFromAny(
*/
s = ckalloc((unsigned) elemSize + 1);
- if (hasBrace) {
+ if (literal) {
memcpy((void *) s, (void *) elemStart, (size_t) elemSize);
s[elemSize] = 0;
} else {
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index 1fabcab..412a902 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -1693,7 +1693,7 @@ SetListFromAny(
{
char *string, *s;
const char *elemStart, *nextElem;
- int lenRemain, length, estCount, elemSize, hasBrace, i, j, result;
+ int lenRemain, length, estCount, elemSize, i, j, result;
const char *limit; /* Points just after string's last byte. */
register const char *p;
register Tcl_Obj **elemPtrs;
@@ -1777,8 +1777,10 @@ SetListFromAny(
for (p=string, lenRemain=length, i=0;
lenRemain > 0;
p=nextElem, lenRemain=limit-nextElem, i++) {
+ int literal;
+
result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
- &elemSize, &hasBrace);
+ &elemSize, &literal);
if (result != TCL_OK) {
for (j = 0; j < i; j++) {
elemPtr = elemPtrs[j];
@@ -1800,7 +1802,7 @@ SetListFromAny(
*/
s = ckalloc((unsigned) elemSize + 1);
- if (hasBrace) {
+ if (literal) {
memcpy(s, elemStart, (size_t) elemSize);
s[elemSize] = 0;
} else {
diff --git a/generic/tclParse.c b/generic/tclParse.c
index 4e1e8b0..c8d2012 100644
--- a/generic/tclParse.c
+++ b/generic/tclParse.c
@@ -433,7 +433,7 @@ Tcl_ParseCommand(
}
if (isLiteral) {
- int elemCount = 0, code = TCL_OK, nakedbs = 0;
+ int elemCount = 0, code = TCL_OK, literal = 1;
const char *nextElem, *listEnd, *elemStart;
/*
@@ -455,33 +455,24 @@ Tcl_ParseCommand(
*/
while (nextElem < listEnd) {
- int size, brace;
+ int size;
code = TclFindElement(NULL, nextElem, listEnd - nextElem,
- &elemStart, &nextElem, &size, &brace);
- if (code != TCL_OK) {
+ &elemStart, &nextElem, &size, &literal);
+ if ((code != TCL_OK) || !literal) {
break;
}
- if (!brace) {
- const char *s;
-
- for(s=elemStart;size>0;s++,size--) {
- if ((*s)=='\\') {
- nakedbs=1;
- break;
- }
- }
- }
if (elemStart < listEnd) {
elemCount++;
}
}
- if ((code != TCL_OK) || nakedbs) {
+ if ((code != TCL_OK) || !literal) {
/*
- * Some list element could not be parsed, or contained
- * naked backslashes. This means the literal string was
- * not in fact a valid nor canonical list. Defer the
+ * Some list element could not be parsed, or is not
+ * present as a literal substring of the script. The
+ * compiler cannot handle list elements that get generated
+ * by a call to TclCopyAndCollapse(). Defer the
* handling of this to compile/eval time, where code is
* already in place to report the "attempt to expand a
* non-list" error or expand lists that require
@@ -525,7 +516,7 @@ Tcl_ParseCommand(
nextElem = tokenPtr[1].start;
while (nextElem < listEnd) {
- int quoted, brace;
+ int quoted;
tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
tokenPtr->numComponents = 1;
@@ -535,9 +526,10 @@ Tcl_ParseCommand(
tokenPtr->numComponents = 0;
TclFindElement(NULL, nextElem, listEnd - nextElem,
&(tokenPtr->start), &nextElem,
- &(tokenPtr->size), &brace);
+ &(tokenPtr->size), NULL);
- quoted = brace || tokenPtr->start[-1] == '"';
+ quoted = tokenPtr->start[-1] == '{'
+ || tokenPtr->start[-1] == '"';
tokenPtr[-1].start = tokenPtr->start - quoted;
tokenPtr[-1].size = tokenPtr->start + tokenPtr->size
- tokenPtr[-1].start + quoted;
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index 76676a1..fd3d935 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -181,8 +181,13 @@ TclMaxListLength(
* after the opening brace and *sizePtr will not include either of the
* braces. If there isn't an element in the list, *sizePtr will be zero,
* and both *elementPtr and *termPtr will point just after the last
- * character in the list. Note: this function does NOT collapse backslash
- * sequences.
+ * character in the list. If literalPtr is non-NULL, *literalPtr is set
+ * to a boolean value indicating whether the substring returned as
+ * the values of **elementPtr and *sizePtr is the literal value of
+ * a list element. If not, a call to TclCopyAndCollapse() is needed
+ * to produce the actual value of the list element. Note: this function
+ * does NOT collapse backslash sequences, but uses *literalPtr to tell
+ * callers when it is required for them to do so.
*
* Side effects:
* None.
@@ -206,8 +211,12 @@ TclFindElement(
* argument (next arg or end of list). */
int *sizePtr, /* If non-zero, fill in with size of
* element. */
- int *bracePtr) /* If non-zero, fill in with non-zero/zero to
- * indicate that arg was/wasn't in braces. */
+ int *literalPtr) /* If non-zero, fill in with non-zero/zero to
+ * indicate that the substring of *sizePtr
+ * bytes starting at **elementPtr is/is not
+ * the literal list element and therefore
+ * does not/does require a call to
+ * TclCopyAndCollapse() by the caller. */
{
CONST char *p = list;
CONST char *elemStart; /* Points to first byte of first element. */
@@ -216,6 +225,7 @@ TclFindElement(
int inQuotes = 0;
int size = 0; /* lint. */
int numChars;
+ int literal = 1;
CONST char *p2;
/*
@@ -241,9 +251,6 @@ TclFindElement(
p++;
}
elemStart = p;
- if (bracePtr != 0) {
- *bracePtr = openBraces;
- }
/*
* Find element's end (a space, close brace, or the end of the string).
@@ -301,6 +308,15 @@ TclFindElement(
*/
case '\\':
+ if (openBraces == 0) {
+ /*
+ * A backslash sequence not within a brace quoted element
+ * means the value of the element is different from the
+ * substring we are parsing. A call to TclCopyAndCollapse()
+ * is needed to produce the element value. Inform the caller.
+ */
+ literal = 0;
+ }
TclParseBackslash(p, limit - p, &numChars, NULL);
p += (numChars - 1);
break;
@@ -385,6 +401,9 @@ TclFindElement(
if (sizePtr != 0) {
*sizePtr = size;
}
+ if (literalPtr != 0) {
+ *literalPtr = literal;
+ }
return TCL_OK;
}
@@ -477,7 +496,7 @@ Tcl_SplitList(
{
CONST char **argv, *end, *element;
char *p;
- int length, size, i, result, elSize, brace;
+ int length, size, i, result, elSize;
/*
* Allocate enough space to work in. A (CONST char *) for each
@@ -496,9 +515,10 @@ Tcl_SplitList(
for (i = 0, p = ((char *) argv) + size*sizeof(char *);
*list != 0; i++) {
CONST char *prevList = list;
+ int literal;
result = TclFindElement(interp, list, length, &element, &list,
- &elSize, &brace);
+ &elSize, &literal);
length -= (list - prevList);
if (result != TCL_OK) {
ckfree((char *) argv);
@@ -516,7 +536,7 @@ Tcl_SplitList(
return TCL_ERROR;
}
argv[i] = p;
- if (brace) {
+ if (literal) {
memcpy(p, element, (size_t) elSize);
p += elSize;
*p = 0;