Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Update the command compilers and bytecode execution engine to use new machinery. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | bug-db36fa5122 |
Files: | files | file ages | folders |
SHA3-256: |
4d0f21f4556ff7dcc723afc728c398a6 |
User & Date: | dgp 2018-03-09 20:34:33.246 |
Context
2018-03-09
| ||
20:46 | Newer utility routine is more suitable. check-in: b864232e48 user: dgp tags: bug-db36fa5122 | |
20:34 | Update the command compilers and bytecode execution engine to use new machinery. check-in: 4d0f21f455 user: dgp tags: bug-db36fa5122 | |
19:40 | Use new machinery to repair index value flaws in [lsort]. check-in: c07b8490b6 user: dgp tags: bug-db36fa5122 | |
Changes
Changes to generic/tclAssembly.c.
︙ | ︙ | |||
2259 2260 2261 2262 2263 2264 2265 | /* Convert to an integer, advance to the next token and return. */ /* * NOTE: Indexing a list with an index before it yields the * same result as indexing after it, and might be more easily portable * when list size limits grow. */ | | | | 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 | /* Convert to an integer, advance to the next token and return. */ /* * NOTE: Indexing a list with an index before it yields the * same result as indexing after it, and might be more easily portable * when list size limits grow. */ status = TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_BEFORE, result); *tokenPtrPtr = TokenAfter(tokenPtr); if (status == TCL_ERROR && interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%.*s\"", tokenPtr->size, tokenPtr->start)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADINDEX", NULL); } return status; |
︙ | ︙ |
Changes to generic/tclCompCmdsGR.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 | /* *---------------------------------------------------------------------- * * TclGetIndexFromToken -- * * Parse a token to determine if an index value is known at | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | < < < | < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | /* *---------------------------------------------------------------------- * * TclGetIndexFromToken -- * * Parse a token to determine if an index value is known at * compile time. * * Returns: * TCL_OK if parsing succeeded, and TCL_ERROR if it failed. * * Side effects: * When TCL_OK is returned, the encoded index value is written * to *index. * *---------------------------------------------------------------------- */ int TclGetIndexFromToken( Tcl_Token *tokenPtr, int before, int after, int *indexPtr) { Tcl_Obj *tmpObj = Tcl_NewObj(); int result = TCL_ERROR; if (TclWordKnownAtCompileTime(tokenPtr, tmpObj)) { result = TclIndexEncode(NULL, tmpObj, before, after, indexPtr); } Tcl_DecrRefCount(tmpObj); return result; } /* *---------------------------------------------------------------------- * * TclCompileGlobalCmd -- |
︙ | ︙ | |||
1173 1174 1175 1176 1177 1178 1179 | valTokenPtr = TokenAfter(parsePtr->tokenPtr); if (numWords != 3) { goto emitComplexLindex; } idxTokenPtr = TokenAfter(valTokenPtr); | | | | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 | valTokenPtr = TokenAfter(parsePtr->tokenPtr); if (numWords != 3) { goto emitComplexLindex; } idxTokenPtr = TokenAfter(valTokenPtr); if (TclGetIndexFromToken(idxTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_BEFORE, &idx) == TCL_OK) { /* * The idxTokenPtr parsed as a valid index value and was * encoded as expected by INST_LIST_INDEX_IMM. * * NOTE: that we rely on indexing before a list producing the * same result as indexing after a list. */ |
︙ | ︙ | |||
1402 1403 1404 1405 1406 1407 1408 | if (parsePtr->numWords != 4) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(listTokenPtr); | | | | | | 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 | if (parsePtr->numWords != 4) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(listTokenPtr); if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER, &idx1) != TCL_OK) { return TCL_ERROR; } /* * Token was an index value, and we treat all "first" indices * before the list same as the start of the list. */ tokenPtr = TokenAfter(tokenPtr); if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END, &idx2) != TCL_OK) { return TCL_ERROR; } /* * Token was an index value, and we treat all "last" indices * after the list same as the end of the list. */ |
︙ | ︙ | |||
1477 1478 1479 1480 1481 1482 1483 | /* * NOTE: This command treats all inserts at indices before the list * the same as inserts at the start of the list, and all inserts * after the list the same as inserts at the end of the list. We * make that transformation here so we can use the optimized bytecode * as much as possible. */ | | | | 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 | /* * NOTE: This command treats all inserts at indices before the list * the same as inserts at the start of the list, and all inserts * after the list the same as inserts at the end of the list. We * make that transformation here so we can use the optimized bytecode * as much as possible. */ if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_END, &idx) != TCL_OK) { return TCL_ERROR; } /* * There are four main cases. If there are no values to insert, this is * just a confirm-listiness check. If the index is '0', this is a prepend. * If the index is 'end' (== TCL_INDEX_END), this is an append. Otherwise, |
︙ | ︙ | |||
1567 1568 1569 1570 1571 1572 1573 | if (parsePtr->numWords < 4) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(listTokenPtr); | | | | | | 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 | if (parsePtr->numWords < 4) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(listTokenPtr); if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER, &idx1) != TCL_OK) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END, &idx2) != TCL_OK) { return TCL_ERROR; } /* * idx1, idx2 are the conventional encoded forms of the tokens parsed * as all forms of index values. Values of idx1 that come before the * list are treated the same as if they were the start of the list. |
︙ | ︙ |
Changes to generic/tclCompCmdsSZ.c.
︙ | ︙ | |||
933 934 935 936 937 938 939 | /* Every path must push the string argument */ CompileWord(envPtr, stringTokenPtr, interp, 1); /* * Parse the two indices. */ | | | | | | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | /* Every path must push the string argument */ CompileWord(envPtr, stringTokenPtr, interp, 1); /* * Parse the two indices. */ if (TclGetIndexFromToken(fromTokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER, &idx1) != TCL_OK) { goto nonConstantIndices; } /* * 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) { |
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 | if (parsePtr->numWords == 5) { tokenPtr = TokenAfter(valueTokenPtr); tokenPtr = TokenAfter(tokenPtr); replacementTokenPtr = TokenAfter(tokenPtr); } tokenPtr = TokenAfter(valueTokenPtr); | | | | | | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 | if (parsePtr->numWords == 5) { tokenPtr = TokenAfter(valueTokenPtr); tokenPtr = TokenAfter(tokenPtr); replacementTokenPtr = TokenAfter(tokenPtr); } tokenPtr = TokenAfter(valueTokenPtr); 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, 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. */ |
︙ | ︙ |
Changes to generic/tclCompile.h.
︙ | ︙ | |||
1117 1118 1119 1120 1121 1122 1123 | MODULE_SCOPE int TclFindCompiledLocal(const char *name, int nameChars, int create, CompileEnv *envPtr); MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr, JumpFixup *jumpFixupPtr, int jumpDist, int distThreshold); MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr); MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr); | | | | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 | MODULE_SCOPE int TclFindCompiledLocal(const char *name, int nameChars, int create, CompileEnv *envPtr); MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr, JumpFixup *jumpFixupPtr, int jumpDist, int distThreshold); MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr); MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr); MODULE_SCOPE int TclGetIndexFromToken(Tcl_Token *tokenPtr, int before, int after, int *indexPtr); MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr, CompileEnv *envPtr); MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp, CompileEnv *envPtr, const char *string, int numBytes, const CmdFrame *invoker, int word); MODULE_SCOPE void TclInitJumpFixupArray(JumpFixupArray *fixupArrayPtr); MODULE_SCOPE void TclInitLiteralTable(LiteralTable *tablePtr); |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
5089 5090 5091 5092 5093 5094 5095 | goto gotError; } /* * Decode end-offset index values. */ | < | < | 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 | goto gotError; } /* * Decode end-offset index values. */ index = TclIndexDecode(index, objc - 1); pcAdjustment = 5; lindexFastPath: if (index >= 0 && index < objc) { objResultPtr = objv[index]; } else { TclNewObj(objResultPtr); |
︙ | ︙ | |||
5246 5247 5248 5249 5250 5251 5252 | /* Decode index value operands. */ assert ( toIdx != TCL_INDEX_AFTER); if ((toIdx == TCL_INDEX_BEFORE) || (fromIdx == TCL_INDEX_AFTER)) { goto emptyList; } | < | | | < | < | | | < < | 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 | /* Decode index value operands. */ assert ( toIdx != TCL_INDEX_AFTER); if ((toIdx == TCL_INDEX_BEFORE) || (fromIdx == TCL_INDEX_AFTER)) { goto emptyList; } toIdx = TclIndexDecode(toIdx, objc - 1); if (toIdx < 0) { goto emptyList; } else if (toIdx >= objc) { toIdx = objc - 1; } assert ( toIdx >= 0 && toIdx < objc); assert ( fromIdx != TCL_INDEX_BEFORE ); assert ( fromIdx != TCL_INDEX_AFTER); fromIdx = TclIndexDecode(fromIdx, objc - 1); if (fromIdx < 0) { fromIdx = 0; } if (fromIdx <= toIdx) { /* Construct the subsquence list */ /* unshared optimization */ if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx); } else { |
︙ | ︙ | |||
5639 5640 5641 5642 5643 5644 5645 | } /* Decode index operands. */ assert ( toIdx != TCL_INDEX_BEFORE ); assert ( toIdx != TCL_INDEX_AFTER); | | < | | < | < | | | < < < | 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 | } /* Decode index operands. */ assert ( toIdx != TCL_INDEX_BEFORE ); assert ( toIdx != TCL_INDEX_AFTER); toIdx = TclIndexDecode(toIdx, length - 1); if (toIdx < 0) { goto emptyRange; } else if (toIdx >= length) { toIdx = length - 1; } assert ( toIdx >= 0 && toIdx < length ); assert ( fromIdx != TCL_INDEX_BEFORE ); assert ( fromIdx != TCL_INDEX_AFTER); fromIdx = TclIndexDecode(fromIdx, length - 1); if (fromIdx < 0) { fromIdx = 0; } if (fromIdx <= toIdx) { objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx); } else { emptyRange: TclNewObj(objResultPtr); } |
︙ | ︙ |