Tcl Source Code

Artifact [23ffb90c1c]
Login

Artifact 23ffb90c1cb942311a445af5b7a406698d33d769:

Attachment "inner.patch" to ticket [2995655fff] added by ferrieux 2010-05-10 05:07:27.
Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.455
diff -u -p -r1.455 tclBasic.c
--- generic/tclBasic.c	30 Apr 2010 12:38:46 -0000	1.455
+++ generic/tclBasic.c	2 May 2010 23:06:28 -0000
@@ -542,6 +542,8 @@ Tcl_CreateInterp(void)
     Tcl_IncrRefCount(iPtr->upLiteral);
     TclNewLiteralStringObj(iPtr->callLiteral,"CALL");
     Tcl_IncrRefCount(iPtr->callLiteral);
+    TclNewLiteralStringObj(iPtr->innerLiteral,"INNER");
+    Tcl_IncrRefCount(iPtr->innerLiteral);
     iPtr->errorCode = NULL;
     TclNewLiteralStringObj(iPtr->ecVar, "::errorCode");
     Tcl_IncrRefCount(iPtr->ecVar);
@@ -1486,6 +1488,7 @@ DeleteInterpProc(
     iPtr->errorStack = NULL;
     Tcl_DecrRefCount(iPtr->upLiteral);
     Tcl_DecrRefCount(iPtr->callLiteral);
+    Tcl_DecrRefCount(iPtr->innerLiteral);
     if (iPtr->returnOpts) {
 	Tcl_DecrRefCount(iPtr->returnOpts);
     }
Index: generic/tclCompile.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompile.c,v
retrieving revision 1.185
diff -u -p -r1.185 tclCompile.c
--- generic/tclCompile.c	29 Apr 2010 23:39:32 -0000	1.185
+++ generic/tclCompile.c	2 May 2010 23:06:32 -0000
@@ -4244,6 +4244,94 @@ FormatInstruction(
 /*
  *----------------------------------------------------------------------
  *
+ * TclGetInnerContext --
+ *
+ *	If possible, returns a list capturing the inner context. Otherwise
+ *	return NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+Tcl_Obj *TclGetInnerContext(Tcl_Interp *interp,
+			    const unsigned char *pc,
+			    Tcl_Obj **tosPtr)
+{
+    int objc = 0, off = 0;
+    Tcl_Obj *result;
+
+    switch(*pc) {
+
+    case INST_STR_LEN:
+    case INST_LNOT:
+    case INST_BITNOT:
+    case INST_UMINUS:
+    case INST_UPLUS:
+    case INST_TRY_CVT_TO_NUMERIC:
+    case INST_EXPAND_STKTOP:
+    case INST_EXPR_STK:
+
+        objc = 1;
+        break;
+
+    case INST_LIST_IN:
+    case INST_LIST_NOT_IN:	/* Basic list containment operators. */
+    case INST_STR_EQ:
+    case INST_STR_NEQ:		/* String (in)equality check */
+    case INST_STR_CMP:		/* String compare. */
+    case INST_STR_INDEX:
+    case INST_STR_MATCH:
+    case INST_REGEXP:
+    case INST_EQ:
+    case INST_NEQ:
+    case INST_LT:
+    case INST_GT:
+    case INST_LE:
+    case INST_GE:
+    case INST_MOD:
+    case INST_LSHIFT:
+    case INST_RSHIFT:
+    case INST_BITOR:
+    case INST_BITXOR:
+    case INST_BITAND:
+    case INST_EXPON:
+    case INST_ADD:
+    case INST_SUB:
+    case INST_DIV:
+    case INST_MULT:
+        objc = 2;
+        break;
+
+    case INST_RETURN_STK:
+        /* early pop. TODO: dig out opt dict too :/ */
+        objc = 1;
+        break;
+
+    case INST_SYNTAX:
+    case INST_RETURN_IMM:
+        objc = 2;
+        break;
+
+   case INST_INVOKE_STK4:
+	objc = TclGetUInt4AtPtr(pc+1);
+        break;
+
+    case INST_INVOKE_STK1:
+	objc = TclGetUInt1AtPtr(pc+1);
+	break;
+
+
+
+    }
+    result = Tcl_NewListObj(objc + 1, NULL);
+    Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(tclInstructionTable[*pc].name, -1));
+    for(;objc>0;objc--)
+        Tcl_ListObjAppendElement(NULL, result, tosPtr[1 - objc + off]);
+
+    return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
  * PrintSourceToObj --
  *
  *	Appends a quoted representation of a string to a Tcl_Obj.
@@ -4349,5 +4437,7 @@ RecordByteCodeStats(
  * mode: c
  * c-basic-offset: 4
  * fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
  * End:
  */
Index: generic/tclCompile.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompile.h,v
retrieving revision 1.125
diff -u -p -r1.125 tclCompile.h
--- generic/tclCompile.h	29 Apr 2010 23:39:32 -0000	1.125
+++ generic/tclCompile.h	2 May 2010 23:06:34 -0000
@@ -981,6 +981,13 @@ MODULE_SCOPE void	TclVerifyLocalLiteralT
 #endif
 MODULE_SCOPE int	TclWordKnownAtCompileTime(Tcl_Token *tokenPtr,
 			    Tcl_Obj *valuePtr);
+MODULE_SCOPE void	TclLogCommandInfo(Tcl_Interp *interp,
+					  const char *script,
+					  const char *command, int length,
+					  const unsigned char *pc, Tcl_Obj **tosPtr); 
+MODULE_SCOPE Tcl_Obj	*TclGetInnerContext(Tcl_Interp *interp,
+					    const unsigned char *pc, Tcl_Obj **tosPtr); 
+
 
 /*
  *----------------------------------------------------------------
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.482
diff -u -p -r1.482 tclExecute.c
--- generic/tclExecute.c	30 Apr 2010 08:29:40 -0000	1.482
+++ generic/tclExecute.c	2 May 2010 23:06:42 -0000
@@ -1967,6 +1967,9 @@ TclExecuteByteCode(
 				 * stack. */
     const unsigned char *pc = NULL;
 				/* The current program counter. */
+    const unsigned char *curPc = NULL;
+				/* Keep track of beginning of inst */
+    
 
     /*
      * Transfer variables - needed only between opcodes, but not while
@@ -2170,6 +2173,8 @@ TclExecuteByteCode(
     }
   cleanup0:
 
+    curPc = pc;
+
 #ifdef TCL_COMPILE_DEBUG
     /*
      * Skip the stack depth check if an expansion is in progress.
@@ -6417,7 +6422,7 @@ TclExecuteByteCode(
 	    bytes = GetSrcInfoForPc(pc, codePtr, &length);
 	    if (bytes != NULL) {
 		DECACHE_STACK_INFO();
-		Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
+		TclLogCommandInfo(interp, codePtr->source, bytes, length, curPc, tosPtr);
 		CACHE_STACK_INFO();
 	    }
 	}
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.475
diff -u -p -r1.475 tclInt.h
--- generic/tclInt.h	30 Apr 2010 20:52:51 -0000	1.475
+++ generic/tclInt.h	2 May 2010 23:06:53 -0000
@@ -1985,6 +1985,7 @@ typedef struct Interp {
     Tcl_Obj *errorStack;	/* [info errorstack] value (as a Tcl_Obj). */
     Tcl_Obj *upLiteral;		/* "UP" literal for [info errorstack] */
     Tcl_Obj *callLiteral;	/* "CALL" literal for [info errorstack] */
+    Tcl_Obj *innerLiteral;	/* "INNER" literal for [info errorstack] */
     int resetErrorStack;        /* controls cleaning up of ::errorStack */
     int returnLevel;		/* [return -level] parameter. */
 
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.205
diff -u -p -r1.205 tclNamesp.c
--- generic/tclNamesp.c	5 Apr 2010 19:44:45 -0000	1.205
+++ generic/tclNamesp.c	2 May 2010 23:06:53 -0000
@@ -26,7 +26,7 @@
  */
 
 #include "tclInt.h"
-#include "tclCompile.h" /* just for NRCommand */
+#include "tclCompile.h" /* for NRCommand; and TclLogCommandInfo visibility */
 
 /*
  * Thread-local storage used to avoid having a global lock on data that is not
@@ -4845,31 +4845,36 @@ TclGetNamespaceChildTable(
 /*
  *----------------------------------------------------------------------
  *
- * Tcl_LogCommandInfo --
+ * TclLogCommandInfo --
  *
  *	This function is invoked after an error occurs in an interpreter. It
- *	adds information to iPtr->errorInfo field to describe the command that
- *	was being executed when the error occurred.
+ *	adds information to iPtr->errorInfo/errorStack fields to describe the
+ *	command that was being executed when the error occurred. When pc and
+ *	tosPtr are non-NULL, conveying a bytecode execution "inner context",
+ *	and the offending instruction is suitable, that inner context is
+ *	recorded in errorStack.
  *
  * Results:
  *	None.
  *
  * Side effects:
- *	Information about the command is added to errorInfo and the line
- *	number stored internally in the interpreter is set.
+ *	Information about the command is added to errorInfo/errorStack and the
+ *	line number stored internally in the interpreter is set.
  *
  *----------------------------------------------------------------------
  */
 
 void
-Tcl_LogCommandInfo(
+TclLogCommandInfo(
     Tcl_Interp *interp,		/* Interpreter in which to log information. */
     const char *script,		/* First character in script containing
 				 * command (must be <= command). */
     const char *command,	/* First character in command that generated
 				 * the error. */
-    int length)			/* Number of bytes in command (-1 means use
+    int length,			/* Number of bytes in command (-1 means use
 				 * all bytes up to first null byte). */
+    const unsigned char *pc,    /* current pc of bytecode execution context */
+    Tcl_Obj **tosPtr)           /* current stack of bytecode execution context */
 {
     register const char *p;
     Interp *iPtr = (Interp *) interp;
@@ -4952,6 +4957,15 @@ Tcl_LogCommandInfo(
 	Tcl_ListObjLength(interp, iPtr->errorStack, &len);
         /* reset while keeping the list intrep as much as possible */
         Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL);
+        if (pc != NULL) {
+            Tcl_Obj *innerContext;
+
+            innerContext = TclGetInnerContext(interp, pc, tosPtr);
+            if (innerContext != NULL) {
+                Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->innerLiteral);
+                Tcl_ListObjAppendElement(NULL, iPtr->errorStack, innerContext);
+            }
+        }
     } 
 
     if (iPtr->varFramePtr != iPtr->framePtr) {
@@ -4974,6 +4988,39 @@ Tcl_LogCommandInfo(
 }
 
 /*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LogCommandInfo --
+ *
+ *	This function is invoked after an error occurs in an interpreter. It
+ *	adds information to iPtr->errorInfo/errorStack fields to describe the
+ *	command that was being executed when the error occurred.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Information about the command is added to errorInfo/errorStack and the
+ *	line number stored internally in the interpreter is set.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LogCommandInfo(
+    Tcl_Interp *interp,		/* Interpreter in which to log information. */
+    const char *script,		/* First character in script containing
+				 * command (must be <= command). */
+    const char *command,	/* First character in command that generated
+				 * the error. */
+    int length)			/* Number of bytes in command (-1 means use
+				 * all bytes up to first null byte). */
+{
+    TclLogCommandInfo(interp, script, command, length, NULL, NULL);
+}
+
+
+/*
  * Local Variables:
  * mode: c
  * c-basic-offset: 4