summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c144
1 files changed, 81 insertions, 63 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 93ed50b..151a899 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -5089,16 +5089,9 @@ TEBCresume(
goto gotError;
}
- /*
- * Select the list item based on the index. Negative operand means
- * end-based indexing.
- */
+ /* Decode end-offset index values. */
- if (opnd < -1) {
- index = opnd+1 + objc;
- } else {
- index = opnd;
- }
+ index = TclIndexDecode(opnd, objc - 1);
pcAdjustment = 5;
lindexFastPath:
@@ -5246,60 +5239,58 @@ TEBCresume(
}
#endif
- /*
- * Adjust the indices for end-based handling.
+ /* Decode index value operands. */
+
+ /*
+ assert ( toIdx != TCL_INDEX_AFTER);
+ *
+ * Extra safety for legacy bytecodes:
*/
+ if (toIdx == TCL_INDEX_AFTER) {
+ toIdx = TCL_INDEX_END;
+ }
- if (fromIdx < -1) {
- fromIdx += 1+objc;
- if (fromIdx < -1) {
- fromIdx = -1;
- }
- } else if (fromIdx > objc) {
- fromIdx = objc;
+ if ((toIdx == TCL_INDEX_BEFORE) || (fromIdx == TCL_INDEX_AFTER)) {
+ goto emptyList;
}
- if (toIdx < -1) {
- toIdx += 1 + objc;
- if (toIdx < -1) {
- toIdx = -1;
- }
- } else if (toIdx > objc) {
- toIdx = objc;
+ toIdx = TclIndexDecode(toIdx, objc - 1);
+ if (toIdx < 0) {
+ goto emptyList;
+ } else if (toIdx >= objc) {
+ toIdx = objc - 1;
}
+ assert ( toIdx >= 0 && toIdx < objc);
/*
- * Check if we are referring to a valid, non-empty list range, and if
- * so, build the list of elements in that range.
+ assert ( fromIdx != TCL_INDEX_BEFORE );
+ *
+ * Extra safety for legacy bytecodes:
*/
+ if (fromIdx == TCL_INDEX_BEFORE) {
+ fromIdx = TCL_INDEX_START;
+ }
- if (fromIdx<=toIdx && fromIdx<objc && toIdx>=0) {
- if (fromIdx < 0) {
- fromIdx = 0;
- }
- if (toIdx >= objc) {
- toIdx = objc-1;
- }
- if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) {
- /*
- * BEWARE! This is looking inside the implementation of the
- * list type.
- */
-
- List *listPtr = valuePtr->internalRep.twoPtrValue.ptr1;
+ fromIdx = TclIndexDecode(fromIdx, objc - 1);
+ if (fromIdx < 0) {
+ fromIdx = 0;
+ }
- if (listPtr->refCount == 1) {
- for (index=toIdx+1; index<objc ; index++) {
- TclDecrRefCount(objv[index]);
- }
- listPtr->elemCount = toIdx+1;
- listPtr->canonicalFlag = 1;
- TclInvalidateStringRep(valuePtr);
- TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
- NEXT_INST_F(9, 0, 0);
+ if (fromIdx <= toIdx) {
+ /* Construct the subsquence list */
+ /* unshared optimization */
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
+ } else {
+ if (toIdx != objc - 1) {
+ Tcl_ListObjReplace(NULL, valuePtr, toIdx + 1,
+ objc - 1 - toIdx, 0, NULL);
}
+ Tcl_ListObjReplace(NULL, valuePtr, 0, fromIdx, 0, NULL);
+ TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
+ NEXT_INST_F(9, 0, 0);
}
- objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
} else {
+ emptyList:
TclNewObj(objResultPtr);
}
@@ -5645,31 +5636,58 @@ TEBCresume(
length = Tcl_GetCharLength(valuePtr);
TRACE(("\"%.20s\" %d %d => ", O2S(valuePtr), fromIdx, toIdx));
+ /* Every range of an empty value is an empty value */
+ if (length == 0) {
+ TRACE_APPEND(("\n"));
+ NEXT_INST_F(9, 0, 0);
+ }
+
+ /* Decode index operands. */
+
/*
- * Adjust indices for end-based indexing.
+ assert ( toIdx != TCL_INDEX_BEFORE );
+ assert ( toIdx != TCL_INDEX_AFTER);
+ *
+ * Extra safety for legacy bytecodes:
*/
-
- if (fromIdx < -1) {
- fromIdx += 1 + length;
- if (fromIdx < 0) {
- fromIdx = 0;
- }
- } else if (fromIdx >= length) {
- fromIdx = length;
+ if (toIdx == TCL_INDEX_BEFORE) {
+ goto emptyRange;
}
- if (toIdx < -1) {
- toIdx += 1 + length;
+ if (toIdx == TCL_INDEX_AFTER) {
+ toIdx = TCL_INDEX_END;
+ }
+
+ toIdx = TclIndexDecode(toIdx, length - 1);
+ if (toIdx < 0) {
+ goto emptyRange;
} else if (toIdx >= length) {
toIdx = length - 1;
}
+ assert ( toIdx >= 0 && toIdx < length );
+
/*
- * Check if we can do a sane substring.
+ assert ( fromIdx != TCL_INDEX_BEFORE );
+ assert ( fromIdx != TCL_INDEX_AFTER);
+ *
+ * Extra safety for legacy bytecodes:
*/
+ if (fromIdx == TCL_INDEX_BEFORE) {
+ fromIdx = TCL_INDEX_START;
+ }
+ if (fromIdx == TCL_INDEX_AFTER) {
+ goto emptyRange;
+ }
+
+ fromIdx = TclIndexDecode(fromIdx, length - 1);
+ if (fromIdx < 0) {
+ fromIdx = 0;
+ }
if (fromIdx <= toIdx) {
objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
} else {
+ emptyRange:
TclNewObj(objResultPtr);
}
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));