diff options
author | sebres <sebres@users.sourceforge.net> | 2019-01-31 16:22:45 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2019-01-31 16:22:45 (GMT) |
commit | 272e429c2c0bc13b8284eae3a420a69c6140d38d (patch) | |
tree | 42b8bd9f3ce637d0432640e6239e042166cde965 /generic/tclCompCmds.c | |
parent | fc5dc8e81101cd4ed4970ab6451792f7fa975811 (diff) | |
download | tcl-272e429c2c0bc13b8284eae3a420a69c6140d38d.zip tcl-272e429c2c0bc13b8284eae3a420a69c6140d38d.tar.gz tcl-272e429c2c0bc13b8284eae3a420a69c6140d38d.tar.bz2 |
TclPushVarName: rewritten iterators over token-strings considering utf-8 multi-bytes.
Diffstat (limited to 'generic/tclCompCmds.c')
-rw-r--r-- | generic/tclCompCmds.c | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 838e9d7..d8f0aeb 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -3408,10 +3408,10 @@ TclPushVarName( int *isScalarPtr) /* Must not be NULL. */ { register const char *p; - const char *name, *elName; - register int i, n; + const char *last, *name, *elName; + register int n; Tcl_Token *elemTokenPtr = NULL; - int nameChars, elNameChars, simpleVarName, localIndex; + int nameLen, elNameLen, simpleVarName, localIndex; int elemTokenCount = 0, allocedTokens = 0, removedParen = 0; /* @@ -3424,7 +3424,7 @@ TclPushVarName( simpleVarName = 0; name = elName = NULL; - nameChars = elNameChars = 0; + nameLen = elNameLen = 0; localIndex = -1; if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { @@ -3436,22 +3436,25 @@ TclPushVarName( simpleVarName = 1; name = varTokenPtr[1].start; - nameChars = varTokenPtr[1].size; - if (name[nameChars-1] == ')') { + nameLen = varTokenPtr[1].size; + if (name[nameLen-1] == ')') { /* * last char is ')' => potential array reference. */ - - for (i=0,p=name ; i<nameChars ; i++,p++) { - if (*p == '(') { - elName = p + 1; - elNameChars = nameChars - i - 2; - nameChars = i; - break; + last = Tcl_UtfPrev(name + nameLen, name); + + if (*last == ')') { + for (p = name; p < last; p = Tcl_UtfNext(p)) { + if (*p == '(') { + elName = p + 1; + elNameLen = last - elName; + nameLen = p - name; + break; + } } } - if (!(flags & TCL_NO_ELEMENT) && (elName != NULL) && elNameChars) { + if (!(flags & TCL_NO_ELEMENT) && elNameLen) { /* * An array element, the element name is a simple string: * assemble the corresponding token. @@ -3461,7 +3464,7 @@ TclPushVarName( allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; - elemTokenPtr->size = elNameChars; + elemTokenPtr->size = elNameLen; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } @@ -3469,21 +3472,22 @@ TclPushVarName( } else if (interp && ((n = varTokenPtr->numComponents) > 1) && (varTokenPtr[1].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].type == TCL_TOKEN_TEXT) - && (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) { + && (*((p = varTokenPtr[n].start + varTokenPtr[n].size)-1) == ')') + && (*Tcl_UtfPrev(p, varTokenPtr[n].start) == ')')) { /* * Check for parentheses inside first token. */ simpleVarName = 0; - for (i = 0, p = varTokenPtr[1].start; - i < varTokenPtr[1].size; i++, p++) { + for (p = varTokenPtr[1].start, + last = p + varTokenPtr[1].size; p < last; p = Tcl_UtfNext(p)) { if (*p == '(') { simpleVarName = 1; break; } } if (simpleVarName) { - int remainingChars; + int remainingLen; /* * Check the last token: if it is just ')', do not count it. @@ -3499,13 +3503,13 @@ TclPushVarName( } name = varTokenPtr[1].start; - nameChars = p - varTokenPtr[1].start; + nameLen = p - varTokenPtr[1].start; elName = p + 1; - remainingChars = (varTokenPtr[2].start - p) - 1; - elNameChars = (varTokenPtr[n].start-p) + varTokenPtr[n].size - 1; + remainingLen = (varTokenPtr[2].start - p) - 1; + elNameLen = (varTokenPtr[n].start-p) + varTokenPtr[n].size - 1; if (!(flags & TCL_NO_ELEMENT)) { - if (remainingChars) { + if (remainingLen) { /* * Make a first token with the extra characters in the first * token. @@ -3515,7 +3519,7 @@ TclPushVarName( allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; - elemTokenPtr->size = remainingChars; + elemTokenPtr->size = remainingLen; elemTokenPtr->numComponents = 0; elemTokenCount = n; @@ -3544,8 +3548,8 @@ TclPushVarName( int hasNsQualifiers = 0; - for (i = 0, p = name; i < nameChars; i++, p++) { - if ((*p == ':') && ((i+1) < nameChars) && (*(p+1) == ':')) { + for (p = name, last = p + nameLen-1; p < last; p = Tcl_UtfNext(p)) { + if ((*p == ':') && (*(p+1) == ':')) { hasNsQualifiers = 1; break; } @@ -3558,7 +3562,7 @@ TclPushVarName( */ if (!hasNsQualifiers) { - localIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); + localIndex = TclFindCompiledLocal(name, nameLen, 1, envPtr); if ((flags & TCL_NO_LARGE_INDEX) && (localIndex > 255)) { /* * We'll push the name. @@ -3568,7 +3572,7 @@ TclPushVarName( } } if (interp && localIndex < 0) { - PushLiteral(envPtr, name, nameChars); + PushLiteral(envPtr, name, nameLen); } /* @@ -3577,7 +3581,7 @@ TclPushVarName( */ if (elName != NULL && !(flags & TCL_NO_ELEMENT)) { - if (elNameChars) { + if (elNameLen) { TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr); } else { |