summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--generic/tclBasic.c37
-rw-r--r--generic/tclCmdIL.c4
-rw-r--r--generic/tclCompile.c10
-rw-r--r--tests/info.test50
5 files changed, 79 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index a40abf4..42a3272 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-07-23 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclBasic.c: Modified TclArgumentGet to reject pure lists
+ * generic/tclCmdIL.c: immediately, without search. Reworked setup
+ * generic/tclCompile.c: of eoFramePtr, doesn't need the line
+ * tests/info.test: information, more sensible to have everything
+ on line 1 when eval'ing a pure list. Updated the users of the line
+ information to special case this based on the frame type (i.e.
+ TCL_LOCATION_EVAL_LIST). Added a testcase demonstrating the new
+ behaviour.
+
2008-07-22 Andreas Kupries <andreask@activestate.com>
* generic/tclBasic.c: Added missing function comments.
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 1a24a29..c91fdc1 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -14,7 +14,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.75.2.31 2008/07/22 22:46:09 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.75.2.32 2008/07/23 20:45:16 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -4573,6 +4573,17 @@ TclArgumentGet(interp,obj,cfPtrPtr,wordPtr)
CmdFrame* framePtr;
/*
+ * An object which either has no string rep guaranteed to have been
+ * generated dynamically: bail out, this cannot have a usable absolute
+ * location. _Do not touch_ the information the set up by the caller. It
+ * knows better than us.
+ */
+
+ if (!obj->bytes) {
+ return;
+ }
+
+ /*
* First look for location information recorded in the argument
* stack. That is nearest.
*/
@@ -4782,7 +4793,6 @@ TclEvalObjEx(interp, objPtr, flags, invoker, word)
* As we know that this is dynamic execution we ignore the
* invoker, even if known.
*/
- int line;
CmdFrame eoFrame;
eoFrame.type = TCL_LOCATION_EVAL_LIST;
@@ -4791,8 +4801,8 @@ TclEvalObjEx(interp, objPtr, flags, invoker, word)
iPtr->cmdFramePtr->level + 1);
eoFrame.framePtr = iPtr->framePtr;
eoFrame.nextPtr = iPtr->cmdFramePtr;
- eoFrame.nline = objc;
- eoFrame.line = (int*) ckalloc (objc * sizeof (int));
+ eoFrame.nline = 0;
+ eoFrame.line = NULL;
/* NOTE: Getting the string rep of the list to eval to fill the
* command information required by 'info frame' implies that
@@ -4815,23 +4825,18 @@ TclEvalObjEx(interp, objPtr, flags, invoker, word)
* Copy the list elements here, to avoid a segfault if
* objPtr loses its List internal rep [Bug 1119369].
*
- * TIP #280 Computes all the line numbers for the
- * words in the command.
+ * TIP #280 We do _not_ compute all the line numbers for the words
+ * in the command. For the eval of a pure list the most sensible
+ * choice is to put all words on line 1. Given that we neither
+ * need memory for them nor compute anything. 'line' is left
+ * NULL. The two places using this information (TclInfoFrame, and
+ * TclInitCompileEnv), are special-cased to use the proper line
+ * number directly instead of accessing the 'line' array.
*/
-#ifdef TCL_TIP280
- line = 1;
-#endif
for (i=0; i < objc; i++) {
objv[i] = listRepPtr->elements[i];
Tcl_IncrRefCount(objv[i]);
-#ifdef TCL_TIP280
- eoFrame.line [i] = line;
- {
- char* w = Tcl_GetString (objv [i]);
- TclAdvanceLines (&line, w, w+ strlen(w));
- }
-#endif
}
#ifdef TCL_TIP280
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 54359af..7bf46fb 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -15,7 +15,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.47.2.15 2008/07/07 21:39:22 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.47.2.16 2008/07/23 20:45:17 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -1153,7 +1153,7 @@ InfoFrameCmd(dummy, interp, objc, objv)
lv [lc ++] = Tcl_NewStringObj ("type",-1);
lv [lc ++] = Tcl_NewStringObj (typeString [framePtr->type],-1);
lv [lc ++] = Tcl_NewStringObj ("line",-1);
- lv [lc ++] = Tcl_NewIntObj (framePtr->line[0]);
+ lv [lc ++] = Tcl_NewIntObj (1);
/* We put a duplicate of the command list obj into the result
* to ensure that the 'pure List'-property of the command
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index a49297c..59be33a 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompile.c,v 1.43.2.11 2008/07/22 22:30:05 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclCompile.c,v 1.43.2.12 2008/07/23 20:45:18 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -818,8 +818,12 @@ TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
envPtr->extCmdMapPtr->neiloc = 0;
envPtr->extCmdMapPtr->nueiloc = 0;
- if (invoker == NULL) {
- /* Initialize the compiler for relative counting */
+ if (invoker == NULL ||
+ (invoker->type == TCL_LOCATION_EVAL_LIST)) {
+ /*
+ * Initialize the compiler for relative counting in case of a
+ * dynamic context.
+ */
envPtr->line = 1;
envPtr->extCmdMapPtr->type = (envPtr->procPtr
diff --git a/tests/info.test b/tests/info.test
index 22ed8ca..35297b3 100644
--- a/tests/info.test
+++ b/tests/info.test
@@ -13,7 +13,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: info.test,v 1.24.2.6 2008/06/16 20:46:16 andreas_kupries Exp $
+# RCS: @(#) $Id: info.test,v 1.24.2.7 2008/07/23 20:45:18 andreas_kupries Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
@@ -698,7 +698,7 @@ proc reduce {frame} {
incr pos
set cmd [lindex $frame $pos]
if {[regexp \n $cmd]} {
- set first [string range [lindex [split $cmd \n] 0] 0 end-11]
+ set first [lindex [split $cmd \n] 0] ; set first [expr {[string length $first] > 11 ? [string range $first 0 end-11] : [string range $first 0 end-4]}]
set frame [lreplace $frame $pos $pos $first]
}
set pos [lsearch -exact $frame file]
@@ -744,17 +744,17 @@ test info-22.2 {info frame, bad level absolute} tip280 {
set msg
} {bad level "9"}
-test info-22.3 {info frame, current, relative} tip280 {
+test info-22.3 {info frame, current, relative} -constraints tip280 -match glob -body {
info frame 0
-} {type eval line 2 cmd {info frame 0} proc ::tcltest::RunTest}
+} -result {type source line 748 file *info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-22.4 {info frame, current, relative, nested} tip280 {
+test info-22.4 {info frame, current, relative, nested} -constraints tip280 -match glob -body {
set res [info frame 0]
-} {type eval line 2 cmd {info frame 0} proc ::tcltest::RunTest}
+} -result {type source line 752 file *info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-22.5 {info frame, current, absolute} tip280 {
+test info-22.5 {info frame, current, absolute} -constraints tip280 -match glob -body {
reduce [info frame 7]
-} {type eval line 2 cmd {info frame 7} proc ::tcltest::RunTest}
+} -result {type source line 756 file *info.test cmd {info frame 7} proc ::tcltest::RunTest}
test info-22.6 {info frame, global, relative} tip280 {
reduce [info frame -6]
@@ -767,7 +767,7 @@ test info-22.7 {info frame, global, absolute} tip280 {
test info-22.8 {info frame, basic trace} tip280 {
join [etrace] \n
} {8 {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
-7 {type eval line 2 cmd etrace proc ::tcltest::RunTest}
+7 {type source line 768 file info.test cmd etrace proc ::tcltest::RunTest}
6 {type source line 2277 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::RunTest}
5 {type eval line 1 cmd {::tcltest::RunTest } proc ::tcltest::Eval}
4 {type source line 1619 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::Eval}
@@ -788,11 +788,11 @@ test info-23.2 {eval'd info frame, dynamic} tip280 {
eval $script
} 8
-test info-23.3 {eval'd info frame, literal} tip280 {
+test info-23.3 {eval'd info frame, literal} -constraints tip280 -match glob -body {
eval {
info frame 0
}
-} {type eval line 2 cmd {info frame 0} proc ::tcltest::RunTest}
+} -result {type source line 793 file *info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.4 {eval'd info frame, semi-dynamic} tip280 {
eval info frame 0
@@ -808,7 +808,7 @@ test info-23.6 {eval'd info frame, trace} tip280 {
join [eval $script] \n
} {9 {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
8 {type eval line 1 cmd etrace proc ::tcltest::RunTest}
-7 {type eval line 3 cmd {eval $script} proc ::tcltest::RunTest}
+7 {type source line 808 file info.test cmd {eval $script} proc ::tcltest::RunTest}
6 {type source line 2277 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::RunTest}
5 {type eval line 1 cmd {::tcltest::RunTest } proc ::tcltest::Eval}
4 {type source line 1619 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::Eval}
@@ -1075,6 +1075,32 @@ namespace delete foo
# -------------------------------------------------------------------------
+test info-34.0 {eval pure list, single line} {
+ # Basically, counting the newline in the word seen through $foo
+ # doesn't really make sense. It makes a bit of sense if the word
+ # would have been a string literal in the command list.
+ #
+ # Problem: At the point where we see the list elements we cannot
+ # distinguish the two cases, thus we cannot switch between
+ # count/not-count, it is has to be one or the other for all
+ # cases. Of the two possibilities miguel convinced me that 'not
+ # counting' is the more proper.
+ set foo {b
+ c}
+ set cmd [list foreach $foo {x y} {
+ set res [join [lrange [etrace] 0 2] \n]
+ break
+ }]
+ eval $cmd
+ set res
+} {10 {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
+9 {type eval line 2 cmd etrace proc ::tcltest::RunTest}
+8 {type eval line 1 cmd foreac proc ::tcltest::RunTest}}
+
+# -------------------------------------------------------------------------
+
+# -------------------------------------------------------------------------
+
# cleanup
catch {namespace delete test_ns_info1 test_ns_info2}
::tcltest::cleanupTests