From 2041c85d62dba1eac0c108bf85727787164941da Mon Sep 17 00:00:00 2001 From: andreas_kupries Date: Wed, 23 Jul 2008 20:45:08 +0000 Subject: * 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. --- ChangeLog | 11 +++++++++++ generic/tclBasic.c | 37 +++++++++++++++++++++---------------- generic/tclCmdIL.c | 4 ++-- generic/tclCompile.c | 10 +++++++--- tests/info.test | 50 ++++++++++++++++++++++++++++++++++++++------------ 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 + + * 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 * 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 -- cgit v0.12