summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2011-04-28 20:40:46 (GMT)
committerdgp <dgp@users.sourceforge.net>2011-04-28 20:40:46 (GMT)
commit77ed9a126f206b71970125701e8285cc2009b7ff (patch)
treef1d39c64119f01c97ab1fe30fd2b0fbea1ab1fcf /generic
parent98b8497049cfeef401ed6514580249aac3383d4e (diff)
downloadtcl-77ed9a126f206b71970125701e8285cc2009b7ff.zip
tcl-77ed9a126f206b71970125701e8285cc2009b7ff.tar.gz
tcl-77ed9a126f206b71970125701e8285cc2009b7ff.tar.bz2
Rewrite of parts of the [switch] compiler to better use the powers of
TclFindElement() and do less parsing on its own. Needs review and testing.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclCompCmds.c107
1 files changed, 104 insertions, 3 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index ddd2242..b06b7bf 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -3907,7 +3907,9 @@ TclCompileSwitchCmd(
int savedStackDepth = envPtr->currStackDepth;
int noCase; /* Has the -nocase flag been given? */
int foundMode = 0; /* Have we seen a mode flag yet? */
+#if 0
int isListedArms = 0;
+#endif
int i, valueIndex;
DefineLineInformation; /* TIP #280 */
int* clNext = envPtr->clNext;
@@ -4047,6 +4049,7 @@ TclCompileSwitchCmd(
*/
if (numWords == 1) {
+#if 0
Tcl_DString bodyList;
const char **argv = NULL, *tokenStartPtr, *p;
int bline; /* TIP #280: line of the pattern/action list,
@@ -4085,7 +4088,9 @@ TclCompileSwitchCmd(
return TCL_ERROR;
}
+#if 0
isListedArms = 1;
+#endif
bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * numWords);
bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords);
bodyLines = (int *) ckalloc(sizeof(int) * numWords);
@@ -4178,6 +4183,91 @@ TclCompileSwitchCmd(
ckfree((char *) bodyNext);
return TCL_ERROR;
}
+#else
+ CONST char *bytes, *p;
+ int maxLen, braced, numBytes;
+ int bline; /* TIP #280: line of the pattern/action list,
+ * and start of list for when tracking the
+ * location. This list comes immediately after
+ * the value we switch on. */
+
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ bytes = tokenPtr[1].start;
+ numBytes = tokenPtr[1].size;
+
+ /*
+ * A list can have at most one more element than the number
+ * of runs of element-separating white space.
+ */
+
+ maxLen = TclCountSpaceRuns(bytes, numBytes, NULL) + 1;
+ if (maxLen < 2) {
+ return TCL_ERROR;
+ }
+ bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * maxLen);
+ bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * maxLen);
+ bodyLines = (int *) ckalloc(sizeof(int) * maxLen);
+ bodyNext = (int **) ckalloc(sizeof(int*) * maxLen);
+
+ bline = mapPtr->loc[eclIndex].line[valueIndex+1];
+ p = bytes;
+ numWords = 0;
+
+ while (numBytes > 0) {
+ CONST char *start, *prevBytes = bytes;
+ int size;
+
+ if (TCL_OK != TclFindElement(NULL, bytes, numBytes, &start,
+ &bytes, &size, &braced)) {
+ abort:
+ ckfree((char *) bodyToken);
+ ckfree((char *) bodyTokenArray);
+ ckfree((char *) bodyLines);
+ ckfree((char *) bodyNext);
+ return TCL_ERROR;
+ }
+ numBytes -= (bytes - prevBytes);
+
+ if (numWords == 0 && numBytes == 0) {
+ break;
+ }
+
+ bodyTokenArray[numWords].type = TCL_TOKEN_TEXT;
+ bodyTokenArray[numWords].start = start;
+ bodyTokenArray[numWords].size = size;
+ bodyTokenArray[numWords].numComponents = 0;
+ bodyToken[numWords] = bodyTokenArray + numWords;
+
+ if (!braced) {
+ while (size--) {
+ if (*start++ == '\\') {
+ goto abort;
+ }
+ }
+ }
+
+ /*
+ * TIP #280: Now determine the line the list element starts on
+ * (there is no need to do it earlier, due to the possibility of
+ * aborting, see above).
+ */
+
+ TclAdvanceLines(&bline, p, bodyTokenArray[numWords].start);
+ TclAdvanceContinuations (&bline, &clNext,
+ bodyTokenArray[numWords].start - envPtr->source);
+ bodyLines[numWords] = bline;
+ bodyNext[numWords] = clNext;
+ p = bodyTokenArray[numWords].start;
+
+ numWords++;
+ }
+ if (numWords % 2) {
+ goto abort;
+ }
+
+#endif
} else if (numWords % 2 || numWords == 0) {
/*
@@ -4205,8 +4295,11 @@ TclCompileSwitchCmd(
* traces, etc.
*/
- if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
- tokenPtr->numComponents != 1) {
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD
+#if 0
+ || tokenPtr->numComponents != 1
+#endif
+ ) {
ckfree((char *) bodyToken);
ckfree((char *) bodyLines);
ckfree((char *) bodyNext);
@@ -4255,7 +4348,15 @@ TclCompileSwitchCmd(
* but it handles the most common case well enough.
*/
- if (isListedArms && mode == Switch_Exact && !noCase) {
+ if (
+#if 0
+ isListedArms &&
+#endif
+ mode == Switch_Exact
+#if 0
+ && !noCase
+#endif
+ ) {
JumptableInfo *jtPtr;
int infoIndex, isNew, *finalFixups, numRealBodies = 0, jumpLocation;
int mustGenerate, jumpToDefault;