summaryrefslogtreecommitdiffstats
path: root/generic/tclCompCmdsSZ.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclCompCmdsSZ.c')
-rw-r--r--generic/tclCompCmdsSZ.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/generic/tclCompCmdsSZ.c b/generic/tclCompCmdsSZ.c
index 6f0cc8f..5cd1c3b 100644
--- a/generic/tclCompCmdsSZ.c
+++ b/generic/tclCompCmdsSZ.c
@@ -930,22 +930,48 @@ TclCompileStringRangeCmd(
fromTokenPtr = TokenAfter(stringTokenPtr);
toTokenPtr = TokenAfter(fromTokenPtr);
+ /* Every path must push the string argument */
+ CompileWord(envPtr, stringTokenPtr, interp, 1);
+
/*
* Parse the two indices.
*/
- if (TclGetIndexFromToken(fromTokenPtr, &idx1) != TCL_OK) {
+ if (TclGetIndexFromToken(fromTokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
+ &idx1) != TCL_OK) {
goto nonConstantIndices;
}
- if (TclGetIndexFromToken(toTokenPtr, &idx2) != TCL_OK) {
+ /*
+ * Token parsed as an index expression. We treat all indices before
+ * the string the same as the start of the string.
+ */
+
+ if (idx1 == TCL_INDEX_AFTER) {
+ /* [string range $s end+1 $last] must be empty string */
+ OP( POP);
+ PUSH( "");
+ return TCL_OK;
+ }
+
+ if (TclGetIndexFromToken(toTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
+ &idx2) != TCL_OK) {
goto nonConstantIndices;
}
+ /*
+ * Token parsed as an index expression. We treat all indices after
+ * the string the same as the end of the string.
+ */
+ if (idx2 == TCL_INDEX_BEFORE) {
+ /* [string range $s $first -1] must be empty string */
+ OP( POP);
+ PUSH( "");
+ return TCL_OK;
+ }
/*
* Push the operand onto the stack and then the substring operation.
*/
- CompileWord(envPtr, stringTokenPtr, interp, 1);
OP44( STR_RANGE_IMM, idx1, idx2);
return TCL_OK;
@@ -954,7 +980,6 @@ TclCompileStringRangeCmd(
*/
nonConstantIndices:
- CompileWord(envPtr, stringTokenPtr, interp, 1);
CompileWord(envPtr, fromTokenPtr, interp, 2);
CompileWord(envPtr, toTokenPtr, interp, 3);
OP( STR_RANGE);
@@ -984,23 +1009,27 @@ TclCompileStringReplaceCmd(
replacementTokenPtr = TokenAfter(tokenPtr);
}
- /*
- * Parse the indices. Will only compile special cases if both are
- * constants and not an _integer_ less than zero (since we reserve
- * negative indices here for end-relative indexing) or an end-based index
- * greater than 'end' itself.
- */
-
tokenPtr = TokenAfter(valueTokenPtr);
- if (TclGetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
+ if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
+ &idx1) != TCL_OK) {
goto genericReplace;
}
+ /*
+ * Token parsed as an index value. Indices before the string are
+ * treated as index of start of string.
+ */
tokenPtr = TokenAfter(tokenPtr);
- if (TclGetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
+ if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
+ &idx2) != TCL_OK) {
goto genericReplace;
}
+ /*
+ * Token parsed as an index value. Indices after the string are
+ * treated as index of end of string.
+ */
+/* TODO...... */
/*
* We handle these replacements specially: first character (where
* idx1=idx2=0) and last character (where idx1=idx2=TCL_INDEX_END). Anything