summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/tclCmdMZ.c4
-rw-r--r--generic/tclDictObj.c12
-rw-r--r--generic/tclListObj.c8
-rw-r--r--generic/tclParse.c42
-rw-r--r--generic/tclUtil.c40
5 files changed, 62 insertions, 44 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index c34ce6c..e7c7152 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -1643,7 +1643,7 @@ StringIsCmd(
*/
const char *elemStart, *nextElem;
- int lenRemain, elemSize, hasBrace;
+ int lenRemain, elemSize;
register const char *p;
string1 = TclGetStringFromObj(objPtr, &length1);
@@ -1652,7 +1652,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/tclDictObj.c b/generic/tclDictObj.c
index 508c2af..b33bb31 100644
--- a/generic/tclDictObj.c
+++ b/generic/tclDictObj.c
@@ -567,7 +567,7 @@ SetDictFromAny(
const char *string;
char *s;
const char *elemStart, *nextElem;
- int lenRemain, length, elemSize, hasBrace, result, isNew;
+ int lenRemain, length, elemSize, result, isNew;
const char *limit; /* Points just after string's last byte. */
register const char *p;
register Tcl_Obj *keyPtr, *valuePtr;
@@ -649,8 +649,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) {
if (interp != NULL) {
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL);
@@ -667,7 +669,7 @@ SetDictFromAny(
*/
s = ckalloc(elemSize + 1);
- if (hasBrace) {
+ if (literal) {
memcpy(s, elemStart, (size_t) elemSize);
s[elemSize] = 0;
} else {
@@ -685,7 +687,7 @@ SetDictFromAny(
}
result = TclFindElement(interp, p, lenRemain,
- &elemStart, &nextElem, &elemSize, &hasBrace);
+ &elemStart, &nextElem, &elemSize, &literal);
if (result != TCL_OK) {
if (interp != NULL) {
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL);
@@ -703,7 +705,7 @@ SetDictFromAny(
*/
s = ckalloc(elemSize + 1);
- if (hasBrace) {
+ if (literal) {
memcpy(s, elemStart, (size_t) elemSize);
s[elemSize] = 0;
} else {
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index 03843b8..f330937 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -1717,7 +1717,7 @@ SetListFromAny(
const char *string;
char *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;
@@ -1801,8 +1801,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];
@@ -1827,7 +1829,7 @@ SetListFromAny(
*/
s = ckalloc(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 429d33a..4afb219 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,35 +455,26 @@ 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
- * handling of this to compile/eval time, where code is
- * already in place to report the "attempt to expand a
+ * 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
* substitution.
*/
@@ -505,6 +496,7 @@ Tcl_ParseCommand(
* tokens representing the expanded list.
*/
+ CONST char *listStart;
int growthNeeded = wordIndex + 2*elemCount
- parsePtr->numTokens;
@@ -524,9 +516,9 @@ Tcl_ParseCommand(
* word value.
*/
- nextElem = tokenPtr[1].start;
+ listStart = nextElem = tokenPtr[1].start;
while (nextElem < listEnd) {
- int quoted, brace;
+ int quoted;
tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
tokenPtr->numComponents = 1;
@@ -536,9 +528,11 @@ 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->start > listStart;
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 d4630af..7baadff 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -180,8 +180,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.
@@ -205,8 +210,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. */
@@ -215,6 +224,7 @@ TclFindElement(
int inQuotes = 0;
int size = 0; /* lint. */
int numChars;
+ int literal = 1;
const char *p2;
/*
@@ -240,9 +250,6 @@ TclFindElement(
p++;
}
elemStart = p;
- if (bracePtr != 0) {
- *bracePtr = openBraces;
- }
/*
* Find element's end (a space, close brace, or the end of the string).
@@ -302,6 +309,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;
@@ -392,6 +408,9 @@ TclFindElement(
if (sizePtr != 0) {
*sizePtr = size;
}
+ if (literalPtr != 0) {
+ *literalPtr = literal;
+ }
return TCL_OK;
}
@@ -484,7 +503,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
@@ -502,9 +521,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(argv);
@@ -524,7 +544,7 @@ Tcl_SplitList(
return TCL_ERROR;
}
argv[i] = p;
- if (brace) {
+ if (literal) {
memcpy(p, element, (size_t) elSize);
p += elSize;
*p = 0;