summaryrefslogtreecommitdiffstats
path: root/generic/tclCompile.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclCompile.c')
-rw-r--r--generic/tclCompile.c100
1 files changed, 98 insertions, 2 deletions
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index f62ec14..2d959c0 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -7,6 +7,7 @@
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
* Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2007 BitMover, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -662,6 +663,51 @@ InstructionDesc const tclInstructionTable[] = {
{"lappendListStk", 1, -1, 0, {OPERAND_NONE}},
/* Lappend list to general variable.
* Stack: ... varName list => ... listVarContents */
+ {"rot", 2, 0, 1, {OPERAND_UINT1}},
+ /* Rotate the top opnd elements in the stack */
+ {"l-index", 5, -1, 1, {OPERAND_UINT4}},
+ /* Index into a nested struct/array/hash. opnd contains flags,
+ * index is stktop, object to index into is stknext. */
+ {"l-deep-write", 9, -1, 2, {OPERAND_UINT4, OPERAND_UINT4}},
+ /* Write via L deep pointer pushed by l-index above. opnd1 is a local
+ * var index of a var that points to the top-level object being
+ * indexed; it will be written if the top-level object needed to be
+ * copied by l-index for copy-on-write. opnd2 contains flags
+ * indicating whether to leave old or new value on stack top.
+ * stktop is the L deep pointer, stknext is the value to write. */
+ {"lsplit", 2, 0, 1, {OPERAND_UINT4}},
+ /* Perl-like string split. opnd is a flags word (see Expr_f),
+ * stack contains the limit (optional), then the delimeter
+ * (optional) then the string to split. */
+ {"l-defined", 1, 0, 0, {OPERAND_NONE}},
+ /* Test whether value at stackTop is the L undefined value. */
+ {"l-push-list-size", 1, 0, 0, {OPERAND_NONE}},
+ /* Store the size of the list at stktop in the internal L
+ * sizes stack. Sizes are used to implement the L END keyword. */
+ {"l-push-string-size", 1, 0, 0, {OPERAND_NONE}},
+ /* Store the length of the string at stktop in the internal L
+ * sizes stack. */
+ {"l-read-size", 1, 1, 0, {OPERAND_NONE}},
+ /* Push what's on the top of the internal L sizes stack. */
+ {"l-pop-size", 1, 0, 0, {OPERAND_NONE}},
+ /* Pop the internal L sizes stack. */
+ {"l-push-undef", 1, 1, 0, {OPERAND_NONE}},
+ /* Push the L undef object. */
+ {"expandRot", 2, 0, 1, {OPERAND_UINT1}},
+ /* Rotate the top opnd1 stack elements with those after
+ * the expand marker (see expandStart). */
+ {"l-lindex-stk", 2, 1, 1, {OPERAND_UINT1}},
+ /* push(listindex stktop opnd) except if opnd is <0 or
+ * > # list elements then push the L undef object. */
+ {"l-list-insert", 9, 0, 3, {OPERAND_LVT4, OPERAND_UINT4}},
+ /* Insert into list local var. Operands are local slot index,
+ * flags, and list index to insert before (0 means prepend,
+ * -1 means append). */
+ {"unsetLocal", 5, 0, 1, {OPERAND_LVT4}},
+ /* Unset the local variable at index op1. */
+ {"different-obj", 5, 0, 1, {OPERAND_LVT4}},
+ /* Determine whether the variable whose name is at stktop
+ * points to a different object as the given local. */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
@@ -1809,13 +1855,29 @@ TclCompileInvocation(
int numWords,
CompileEnv *envPtr)
{
- int wordIdx = 0, depth = TclGetStackDepth(envPtr);
+ int adjust = 0, wordIdx = 0, depth = TclGetStackDepth(envPtr);
+ char *cmd, *s;
+ Tcl_Obj *obj;
DefineLineInformation;
if (cmdObj) {
CompileCmdLiteral(interp, cmdObj, envPtr);
wordIdx = 1;
tokenPtr = TokenAfter(tokenPtr);
+ cmd = Tcl_GetString(cmdObj);
+ if (!strcmp("L", cmd) || !strcmp("Lhtml", cmd)) {
+ /*
+ * If this is the L or Lhtml command, push the argument --line=%d
+ * to it now. This communicates the source line # to the L
+ * compiler.
+ */
+ obj = Tcl_ObjPrintf("--line=%d", envPtr->line+1);
+ Tcl_IncrRefCount(obj);
+ s = TclGetString(obj);
+ adjust = TclRegisterNewLiteral(envPtr, s, strlen(s));
+ Tcl_DecrRefCount(obj);
+ TclEmitPush(adjust, envPtr);
+ }
}
for (; wordIdx < numWords; wordIdx++, tokenPtr = TokenAfter(tokenPtr)) {
@@ -1837,6 +1899,14 @@ TclCompileInvocation(
TclEmitPush(objIdx, envPtr);
}
+ /*
+ * Possible adjust for L-command argument injection (see comment
+ * above).
+ */
+ if (adjust) {
+ ++wordIdx;
+ }
+
if (wordIdx <= 255) {
TclEmitInvoke(envPtr, INST_INVOKE_STK1, wordIdx);
} else {
@@ -1853,7 +1923,8 @@ CompileExpanded(
int numWords,
CompileEnv *envPtr)
{
- int wordIdx = 0;
+ int adjust = 0, wordIdx = 0;
+ char *cmd;
DefineLineInformation;
int depth = TclGetStackDepth(envPtr);
@@ -1862,6 +1933,23 @@ CompileExpanded(
CompileCmdLiteral(interp, cmdObj, envPtr);
wordIdx = 1;
tokenPtr = TokenAfter(tokenPtr);
+ cmd = Tcl_GetString(cmdObj);
+ if (!strcmp("L", cmd) || !strcmp("Lhtml", cmd)) {
+ /*
+ * If this is the L or Lhtml command, push the argument --line=%d
+ * to it now. This communicates the source line # to the L
+ * compiler.
+ */
+ char *s;
+ Tcl_Obj *obj;
+
+ obj = Tcl_ObjPrintf("--line=%d", envPtr->line+1);
+ Tcl_IncrRefCount(obj);
+ s = TclGetString(obj);
+ adjust = TclRegisterNewLiteral(envPtr, s, strlen(s));
+ Tcl_DecrRefCount(obj);
+ TclEmitPush(adjust, envPtr);
+ }
}
for (; wordIdx < numWords; wordIdx++, tokenPtr = TokenAfter(tokenPtr)) {
@@ -1888,6 +1976,14 @@ CompileExpanded(
}
/*
+ * Possible adjust for L-command argument injection (see comment
+ * above).
+ */
+ if (adjust) {
+ ++wordIdx;
+ }
+
+ /*
* The stack depth during argument expansion can only be managed at
* runtime, as the number of elements in the expanded lists is not known
* at compile time. We adjust here the stack depth estimate so that it is