summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c111
1 files changed, 106 insertions, 5 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index c3808f5..d2d802a 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclExecute.c,v 1.253 2006/11/27 15:10:45 dgp Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.254 2006/11/28 22:20:28 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -784,7 +784,8 @@ Tcl_ExprObj(
}
}
if (objPtr->typePtr != &tclByteCodeType) {
- TclInitCompileEnv(interp, &compEnv, string, length);
+ /* TIP #280 : No invoker (yet) - Expression compilation */
+ TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
result = TclCompileExpr(interp, string, length, &compEnv);
/*
@@ -914,7 +915,9 @@ Tcl_ExprObj(
int
TclCompEvalObj(
Tcl_Interp *interp,
- Tcl_Obj *objPtr)
+ Tcl_Obj *objPtr,
+ CONST CmdFrame* invoker,
+ int word)
{
register Interp *iPtr = (Interp *) interp;
register ByteCode* codePtr; /* Tcl Internal type of bytecode. */
@@ -946,7 +949,17 @@ TclCompEvalObj(
if (objPtr->typePtr != &tclByteCodeType) {
recompileObj:
iPtr->errorLine = 1;
+
+ /* TIP #280. Remember the invoker for a moment in the interpreter
+ * structures so that the byte code compiler can pick it up when
+ * initializing the compilation environment, i.e. the extended
+ * location information.
+ */
+
+ iPtr->invokeCmdFramePtr = invoker;
+ iPtr->invokeWord = word;
result = tclByteCodeType.setFromAnyProc(interp, objPtr);
+ iPtr->invokeCmdFramePtr = NULL;
if (result != TCL_OK) {
iPtr->numLevels--;
return result;
@@ -1180,6 +1193,9 @@ TclExecuteByteCode(
int result = TCL_OK; /* Return code returned after execution. */
+ /* TIP #280 : Structures for tracking lines */
+ CmdFrame bcFrame;
+
/*
* Locals - variables that are used within opcodes or bounded sections of
* the file (jumps between opcodes within a family).
@@ -1212,6 +1228,24 @@ TclExecuteByteCode(
}
initStackTop = tosPtr - eePtr->stackPtr;
+ /* TIP #280 : Initialize the frame. Do not push it yet. */
+
+ bcFrame.type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED)
+ ? TCL_LOCATION_PREBC
+ : TCL_LOCATION_BC);
+ bcFrame.level = (iPtr->cmdFramePtr == NULL ?
+ 1 :
+ iPtr->cmdFramePtr->level + 1);
+ bcFrame.framePtr = iPtr->framePtr;
+ bcFrame.nextPtr = iPtr->cmdFramePtr;
+ bcFrame.nline = 0;
+ bcFrame.line = NULL;
+
+ bcFrame.data.tebc.codePtr = codePtr;
+ bcFrame.data.tebc.pc = NULL;
+ bcFrame.cmd.str.cmd = NULL;
+ bcFrame.cmd.str.len = 0;
+
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
PrintByteCodeInfo(codePtr);
@@ -1788,12 +1822,18 @@ TclExecuteByteCode(
/*
* Finally, let TclEvalObjvInternal handle the command.
+ *
+ * TIP #280 : Record the last piece of info needed by
+ * 'TclGetSrcInfoForPc', and push the frame.
*/
+ bcFrame.data.tebc.pc = pc;
+ iPtr->cmdFramePtr = &bcFrame;
DECACHE_STACK_INFO();
/*Tcl_ResetResult(interp);*/
result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
CACHE_STACK_INFO();
+ iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
/*
* If the old stack is going to be released, it is safe to do so
@@ -1853,7 +1893,13 @@ TclExecuteByteCode(
objPtr = *tosPtr;
DECACHE_STACK_INFO();
- result = TclCompEvalObj(interp, objPtr);
+
+ /* TIP #280: The invoking context is left NULL for a dynamically
+ * constructed command. We cannot match its lines to the outer
+ * context.
+ */
+
+ result = TclCompEvalObj(interp, objPtr, NULL,0);
CACHE_STACK_INFO();
if (result == TCL_OK) {
/*
@@ -6386,7 +6432,7 @@ IllegalExprOperandType(
/*
*----------------------------------------------------------------------
*
- * GetSrcInfoForPc --
+ * TclGetSrcInfoForPc, GetSrcInfoForPc --
*
* Given a program counter value, finds the closest command in the
* bytecode code unit's CmdLocation array and returns information about
@@ -6407,6 +6453,61 @@ IllegalExprOperandType(
*----------------------------------------------------------------------
*/
+void
+TclGetSrcInfoForPc (cfPtr)
+ CmdFrame* cfPtr;
+{
+ ByteCode* codePtr = (ByteCode*) cfPtr->data.tebc.codePtr;
+
+ if (cfPtr->cmd.str.cmd == NULL) {
+ cfPtr->cmd.str.cmd = GetSrcInfoForPc((char*) cfPtr->data.tebc.pc,
+ codePtr,
+ &cfPtr->cmd.str.len);
+ }
+
+ if (cfPtr->cmd.str.cmd != NULL) {
+ /* We now have the command. We can get the srcOffset back and
+ * from there find the list of word locations for this command
+ */
+
+ ExtCmdLoc* eclPtr;
+ ECL* locPtr = NULL;
+ int srcOffset;
+
+ Interp* iPtr = (Interp*) *codePtr->interpHandle;
+ Tcl_HashEntry* hePtr = Tcl_FindHashEntry (iPtr->lineBCPtr, (char *) codePtr);
+
+ if (!hePtr) return;
+
+ srcOffset = cfPtr->cmd.str.cmd - codePtr->source;
+ eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hePtr);
+
+ {
+ int i;
+ for (i=0; i < eclPtr->nuloc; i++) {
+ if (eclPtr->loc [i].srcOffset == srcOffset) {
+ locPtr = &(eclPtr->loc [i]);
+ break;
+ }
+ }
+ }
+
+ if (locPtr == NULL) {Tcl_Panic ("LocSearch failure");}
+
+ cfPtr->line = locPtr->line;
+ cfPtr->nline = locPtr->nline;
+ cfPtr->type = eclPtr->type;
+
+ if (eclPtr->type == TCL_LOCATION_SOURCE) {
+ cfPtr->data.eval.path = eclPtr->path;
+ Tcl_IncrRefCount (cfPtr->data.eval.path);
+ }
+ /* Do not set cfPtr->data.eval.path NULL for non-SOURCE
+ * Needed for cfPtr->data.tebc.codePtr.
+ */
+ }
+}
+
static char *
GetSrcInfoForPc(
unsigned char *pc, /* The program counter value for which to