zsh-workers
 help / color / mirror / code / Atom feed
* eval line number weirdness
@ 2008-08-31 23:46 Rocky Bernstein
  2008-09-02 17:28 ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Rocky Bernstein @ 2008-08-31 23:46 UTC (permalink / raw)
  To: Zsh hackers list

I think that the line numbers reported in eval statements are bit hard
to explain. Consider this program

  debug_hook() { print $funcfiletrace[1] $functrace[1]; }
  set -o DEBUG_BEFORE_CMD
  trap "debug_hook" DEBUG
  fn() {
    a=1
    eval "b=2"
    c=3
  }
  fn
  w=5
  eval "x=6
  y=7"
  z=8

which reports:

  linebug3.sh:4 linebug3.sh:4
  linebug3.sh:9 linebug3.sh:9
  linebug3.sh:5 fn:1
  linebug3.sh:6 fn:2
  linebug3.sh:5 fn:1  # Should be linebug3.sh:6 eval:1 ?
  linebug3.sh:7 fn:3
  linebug3.sh:10 linebug3.sh:10
  linebug3.sh:11 linebug3.sh:11
  linebug3.sh:1 linebug3.sh:1  # Should be linebug3.sh:11 eval:1 ?
  linebug3.sh:2 linebug3.sh:2  # Should be linebug3.sh:12 eval:2 ?
  linebug3.sh:13 linebug3.sh:13

The problem is in describing exactly what is reported when eval gets
run and having that mean something meaningful.

With funcfiletrace, an absolute line number in a file name is I think
supposed to be reported. So the 1 and 2 listed above (which is
relative to the line number eval sees) doesn't seem right.

And while for functrace it is okay to report line 1 and 2, the
function name isn't right -- it should be eval than either fn or
linebug3.sh. If functrace is supposed to report the line offset of the
thing it is in (which seems dubious to me), then the above information
isn't right. Instead of fn:1 we would get instead fn:2 since the eval
is on the second line of fn; And presumably instead of linebug:1 one
would see linebug:11.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: eval line number weirdness
  2008-08-31 23:46 eval line number weirdness Rocky Bernstein
@ 2008-09-02 17:28 ` Peter Stephenson
  2008-09-03  3:37   ` Rocky Bernstein
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Stephenson @ 2008-09-02 17:28 UTC (permalink / raw)
  To: Zsh hackers list

On Sun, 31 Aug 2008 19:46:14 -0400
"Rocky Bernstein" <rocky.bernstein@gmail.com> wrote:
> I think that the line numbers reported in eval statements are bit hard
> to explain.

I think they're plain wrong.  The problem is (in the native zsh case where
the option EVAL_LINENO is set) we reset the line number on an eval, and
that's all we do.  We really ought to fix up the stack trace so that when
the line number is reset we generate a new context indicating the surrounding
line information.

I think this does it.  An "eval" is pretty much like an inline function
for tracing, with the difference that the line numbering starts from 1
rather than 0 so needs offsetting when added to the file line number.

I think I've also sorted out a consistency problem with tracing information
nested inside sourced files.  Note this changes the way $funcsourcetrace
reports sourced files---they work like autoloaded functions, i.e. the line
number is 0 because the entire body of the file contains the code.  I ought
to write a test that checks this.

Index: Doc/Zsh/mod_parameter.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_parameter.yo,v
retrieving revision 1.11
diff -u -r1.11 mod_parameter.yo
--- Doc/Zsh/mod_parameter.yo	13 Aug 2008 21:02:02 -0000	1.11
+++ Doc/Zsh/mod_parameter.yo	2 Sep 2008 17:15:52 -0000
@@ -167,7 +167,8 @@
 vindex(funcfiletrace)
 item(tt(funcfiletrace))(
 This array contains the absolute line numbers and corresponding file
-names for the point where the current function or sourced file was
+names for the point where the current function, sourced file, or (if
+tt(EVAL_LINENO) is set) tt(eval) command was
 called.  The array is of the same length as tt(funcsourcetrace) and
 tt(functrace), but differs from tt(funcsourcetrace) in that the line and
 file are the point of call, not the point of definition, and differs
@@ -176,23 +177,25 @@
 )
 vindex(funcsourcetrace)
 item(tt(funcsourcetrace))(
-This array contains the file names and line numbers of the 
-points where the functions currently being executed were
+This array contains the file names and line numbers of the
+points where the functions, sourced files, and (if tt(EVAL_LINENO) is set)
+tt(eval) commands currently being executed were
 defined.  The line number is the line where the `tt(function) var(name)'
 or `var(name) tt(LPAR()RPAR())' started.  In the case of an autoloaded
-function in native zsh format where only the body of the function occurs
-in the file the line number is reported as zero.
+function  the line number is reported as zero.
 The format of each element is var(filename)tt(:)var(lineno).
-For files that have been executed by the tt(source) or tt(.) builtins
-(in which case there is no separate definition) the trace information is
-shown as tt(source:0).
+For functions autoloaded from a file in native zsh format, where only the
+body of the function occurs in the file, or for files that have been
+executed by the tt(source) or tt(.) builtins, the trace information is
+shown as var(filename)tt(:)var(0), since the entire file is the definition.
 
 Most users will be interested in the information in the
 tt(funcfiletrace) array instead.
 )
 vindex(funcstack)
 item(tt(funcstack))(
-This array contains the names of the functions currently being
+This array contains the names of the functions, sourced files,
+and (if tt(EVAL_LINENO) is set) tt(eval) commands. currently being
 executed. The first element is the name of the function using the
 parameter.
 )
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.203
diff -u -r1.203 builtin.c
--- Src/builtin.c	31 Aug 2008 13:35:28 -0000	1.203
+++ Src/builtin.c	2 Sep 2008 17:15:53 -0000
@@ -4712,15 +4712,53 @@
 {
     Eprog prog;
     char *oscriptname = scriptname;
-    int oineval = ineval;
+    int oineval = ineval, fpushed;
+    struct funcstack fstack;
+
     /*
      * If EVALLINENO is not set, we use the line number of the
      * environment and must flag this up to exec.c.  Otherwise,
      * we use a special script name to indicate the special line number.
      */
     ineval = !isset(EVALLINENO);
-    if (!ineval)
+    if (!ineval) {
 	scriptname = "(eval)";
+	fstack.prev = funcstack;
+	fstack.name = scriptname;
+	fstack.caller = funcstack ? funcstack->name : dupstring(argzero);
+	fstack.lineno = lineno;
+	fstack.tp = FS_EVAL;
+
+	/*
+	 * To get file line numbers, we need to know if parent is
+	 * the original script/shell or a sourced file, in which
+	 * case we use the line number raw, or a function or eval,
+	 * in which case we need to deduce where that came from.
+	 *
+	 * This replicates the logic for working out the information
+	 * for $funcfiletrace---eval is similar to an inlined function
+	 * call from a tracing perspective.
+	 */
+	if (!funcstack || funcstack->tp == FS_SOURCE) {
+	    fstack.flineno = fstack.lineno;
+	    fstack.filename = fstack.caller;
+	} else {
+	    fstack.flineno = funcstack->flineno + lineno;
+	    /*
+	     * Line numbers in eval start from 1, not zero,
+	     * so offset by one to get line in file.
+	     */
+	    if (funcstack->tp == FS_EVAL)
+		fstack.flineno--;
+	    fstack.filename = funcstack->filename;
+	    if (!fstack.filename)
+		fstack.filename = "";
+	}
+	funcstack = &fstack;
+
+	fpushed = 1;
+    } else
+	fpushed = 0;
 
     prog = parse_string(zjoin(argv, ' ', 1));
     if (prog) {
@@ -4737,6 +4775,9 @@
 	lastval = 1;
     }
 
+    if (fpushed)
+	funcstack = funcstack->prev;
+
     errflag = 0;
     scriptname = oscriptname;
     ineval = oineval;
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.145
diff -u -r1.145 exec.c
--- Src/exec.c	1 Sep 2008 20:18:47 -0000	1.145
+++ Src/exec.c	2 Sep 2008 17:15:53 -0000
@@ -4264,10 +4264,16 @@
     }
 #endif
     fstack.name = dupstring(name);
-    fstack.caller = dupstring(oargv0 ? oargv0 : argzero);
+    /*
+     * The caller is whatever is immediately before on the stack,
+     * unless we're at the top, in which case it's the script
+     * or interactive shell name.
+     */
+    fstack.caller = funcstack ? funcstack->name :
+	dupstring(oargv0 ? oargv0 : argzero);
     fstack.lineno = lineno;
     fstack.prev = funcstack;
-    fstack.sourced = 0;
+    fstack.tp = FS_FUNC;
     funcstack = &fstack;
 
     if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) {
@@ -4277,8 +4283,7 @@
 	fstack.flineno = 0;
 	fstack.filename = dupstring(fstack.caller);
     }
-    
-    
+
     if (prog->flags & EF_RUN) {
 	Shfunc shf;
 
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.94
diff -u -r1.94 init.c
--- Src/init.c	13 Aug 2008 21:02:03 -0000	1.94
+++ Src/init.c	2 Sep 2008 17:15:53 -0000
@@ -1061,6 +1061,7 @@
     unsigned char *ocs;
     int ocsp;
     int otrap_return = trap_return, otrap_state = trap_state;
+    struct funcstack fstack;
 
     if (!s || 
 	(!(prog = try_source_file((us = unmeta(s)))) &&
@@ -1100,19 +1101,17 @@
     trap_state = TRAP_STATE_INACTIVE;
 
     sourcelevel++;
-    {
-       struct funcstack fstack;
-       fstack.name = dupstring("source");
-       fstack.caller = dupstring(old_scriptfilename ? old_scriptfilename :
-				 "zsh");
-       fstack.flineno = 0;
-       fstack.lineno = oldlineno;
-       fstack.filename = fstack.name;
-       fstack.prev = funcstack;
-       fstack.sourced = 1;
-       funcstack = &fstack;
-    }
-    
+
+    fstack.name = scriptfilename;
+    fstack.caller = funcstack ? funcstack->name :
+	dupstring(old_scriptfilename ? old_scriptfilename : "zsh");
+    fstack.flineno = 0;
+    fstack.lineno = oldlineno;
+    fstack.filename = scriptfilename;
+    fstack.prev = funcstack;
+    fstack.tp = FS_SOURCE;
+    funcstack = &fstack;
+
     if (prog) {
 	pushheap();
 	errflag = 0;
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.144
diff -u -r1.144 zsh.h
--- Src/zsh.h	31 Aug 2008 16:01:12 -0000	1.144
+++ Src/zsh.h	2 Sep 2008 17:15:53 -0000
@@ -1077,6 +1077,14 @@
 #define SFC_COMPLETE 5		/* called from completion code */
 #define SFC_CWIDGET  6		/* new style completion widget */
 
+/* tp in funcstack */
+
+enum {
+    FS_SOURCE,
+    FS_FUNC,
+    FS_EVAL
+};
+
 /* node in function stack */
 
 struct funcstack {
@@ -1086,7 +1094,7 @@
     char *caller;		/* name of caller */
     zlong flineno;		/* line number in file */
     zlong lineno;		/* line offset from beginning of function */
-    int sourced;		/* type of entry is a sourced file */
+    int tp;     		/* type of entry: sourced file, func, eval */
 };
 
 /* node in list of function call wrappers */
Index: Src/Modules/parameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
retrieving revision 1.47
diff -u -r1.47 parameter.c
--- Src/Modules/parameter.c	13 Aug 2008 21:02:04 -0000	1.47
+++ Src/Modules/parameter.c	2 Sep 2008 17:15:54 -0000
@@ -583,7 +583,7 @@
     for (f = funcstack, p = ret; f; f = f->prev, p++) {
 	char *colonpair, *fname;
 
-	if (!f->prev || f->prev->sourced) {
+	if (!f->prev || f->prev->tp == FS_SOURCE) {
 	    /*
 	     * Calling context is a file---either the parent
 	     * script or interactive shell, or a sourced
@@ -595,13 +595,20 @@
 	    sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
 	} else {
 	    /*
-	     * Calling context is a function; we need to find the line number
-	     * in the file where that function was defined.  For this we need
-	     * the $funcsourcetrace information for the context above,
+	     * Calling context is a function or eval; we need to find
+	     * the line number in the file where that function was
+	     * defined or the eval was called.  For this we need the
+	     * $funcsourcetrace information for the context above,
 	     * together with the $functrace line number for the current
 	     * context.
 	     */
 	    long flineno = (long)(f->prev->flineno + f->lineno);
+	    /*
+	     * Line numbers in eval start from 1, not zero,
+	     * so offset by one to get line in file.
+	     */
+	    if (f->prev->tp == FS_EVAL)
+		flineno--;
 	    fname = f->prev->filename ? f->prev->filename : "";
 
 	    colonpair = zhalloc(strlen(fname) + (flineno > 9999 ? 24 : 6));
Index: Test/V06parameter.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/V06parameter.ztst,v
retrieving revision 1.3
diff -u -r1.3 V06parameter.ztst
--- Test/V06parameter.ztst	12 Aug 2008 20:25:14 -0000	1.3
+++ Test/V06parameter.ztst	2 Sep 2008 17:15:54 -0000
@@ -36,4 +36,33 @@
 >Inside autofn
 >2 + ./functrace.zsh:21 + ./autofn:0
 >In sourced file
->2 + ./functrace.zsh:22 + source:0
+>2 + ./functrace.zsh:22 + ./sourcedfile:0
+
+  print -r -- 'module_path=(./Modules)
+  debug_hook() { print $funcfiletrace[1] $functrace[1]; }
+  set -o DEBUG_BEFORE_CMD
+  trap "debug_hook" DEBUG
+  fn() {
+    a=1
+    eval "b=2"
+    c=3
+  }
+  fn
+  w=5
+  eval "x=6
+  y=7"
+  z=8' >rocky3.zsh
+  $ZTST_testdir/../Src/zsh +Z -f ./rocky3.zsh
+0:Eval tracing
+>./rocky3.zsh:5 ./rocky3.zsh:5
+>./rocky3.zsh:10 ./rocky3.zsh:10
+>./rocky3.zsh:6 fn:1
+>./rocky3.zsh:7 fn:2
+>./rocky3.zsh:7 (eval):1
+>./rocky3.zsh:8 fn:3
+>./rocky3.zsh:11 ./rocky3.zsh:11
+>./rocky3.zsh:12 ./rocky3.zsh:12
+>./rocky3.zsh:12 (eval):1
+>./rocky3.zsh:13 (eval):2
+>./rocky3.zsh:14 ./rocky3.zsh:14
+

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: eval line number weirdness
  2008-09-02 17:28 ` Peter Stephenson
@ 2008-09-03  3:37   ` Rocky Bernstein
  0 siblings, 0 replies; 3+ messages in thread
From: Rocky Bernstein @ 2008-09-03  3:37 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh hackers list

I applied the patch and it works great. Thanks.

I've fixed and committed my zshdb bugs in this area.  Now that the
line numbers are pretty accurate, I guess it's time to start adding
debugger breakpoints by file and line number. (Started tonight; The
corresponding bashdb code is is ugly and can be simplified and made
more reliable using associative arrays.)

Onward and upward. Thanks again.

On Tue, Sep 2, 2008 at 1:28 PM, Peter Stephenson <pws@csr.com> wrote:
> On Sun, 31 Aug 2008 19:46:14 -0400
> "Rocky Bernstein" <rocky.bernstein@gmail.com> wrote:
>> I think that the line numbers reported in eval statements are bit hard
>> to explain.
>
> I think they're plain wrong.  The problem is (in the native zsh case where
> the option EVAL_LINENO is set) we reset the line number on an eval, and
> that's all we do.  We really ought to fix up the stack trace so that when
> the line number is reset we generate a new context indicating the surrounding
> line information.
>
> I think this does it.  An "eval" is pretty much like an inline function
> for tracing, with the difference that the line numbering starts from 1
> rather than 0 so needs offsetting when added to the file line number.
>
> I think I've also sorted out a consistency problem with tracing information
> nested inside sourced files.  Note this changes the way $funcsourcetrace
> reports sourced files---they work like autoloaded functions, i.e. the line
> number is 0 because the entire body of the file contains the code.  I ought
> to write a test that checks this.
>
> Index: Doc/Zsh/mod_parameter.yo
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_parameter.yo,v
> retrieving revision 1.11
> diff -u -r1.11 mod_parameter.yo
> --- Doc/Zsh/mod_parameter.yo    13 Aug 2008 21:02:02 -0000      1.11
> +++ Doc/Zsh/mod_parameter.yo    2 Sep 2008 17:15:52 -0000
> @@ -167,7 +167,8 @@
>  vindex(funcfiletrace)
>  item(tt(funcfiletrace))(
>  This array contains the absolute line numbers and corresponding file
> -names for the point where the current function or sourced file was
> +names for the point where the current function, sourced file, or (if
> +tt(EVAL_LINENO) is set) tt(eval) command was
>  called.  The array is of the same length as tt(funcsourcetrace) and
>  tt(functrace), but differs from tt(funcsourcetrace) in that the line and
>  file are the point of call, not the point of definition, and differs
> @@ -176,23 +177,25 @@
>  )
>  vindex(funcsourcetrace)
>  item(tt(funcsourcetrace))(
> -This array contains the file names and line numbers of the
> -points where the functions currently being executed were
> +This array contains the file names and line numbers of the
> +points where the functions, sourced files, and (if tt(EVAL_LINENO) is set)
> +tt(eval) commands currently being executed were
>  defined.  The line number is the line where the `tt(function) var(name)'
>  or `var(name) tt(LPAR()RPAR())' started.  In the case of an autoloaded
> -function in native zsh format where only the body of the function occurs
> -in the file the line number is reported as zero.
> +function  the line number is reported as zero.
>  The format of each element is var(filename)tt(:)var(lineno).
> -For files that have been executed by the tt(source) or tt(.) builtins
> -(in which case there is no separate definition) the trace information is
> -shown as tt(source:0).
> +For functions autoloaded from a file in native zsh format, where only the
> +body of the function occurs in the file, or for files that have been
> +executed by the tt(source) or tt(.) builtins, the trace information is
> +shown as var(filename)tt(:)var(0), since the entire file is the definition.
>
>  Most users will be interested in the information in the
>  tt(funcfiletrace) array instead.
>  )
>  vindex(funcstack)
>  item(tt(funcstack))(
> -This array contains the names of the functions currently being
> +This array contains the names of the functions, sourced files,
> +and (if tt(EVAL_LINENO) is set) tt(eval) commands. currently being
>  executed. The first element is the name of the function using the
>  parameter.
>  )
> Index: Src/builtin.c
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
> retrieving revision 1.203
> diff -u -r1.203 builtin.c
> --- Src/builtin.c       31 Aug 2008 13:35:28 -0000      1.203
> +++ Src/builtin.c       2 Sep 2008 17:15:53 -0000
> @@ -4712,15 +4712,53 @@
>  {
>     Eprog prog;
>     char *oscriptname = scriptname;
> -    int oineval = ineval;
> +    int oineval = ineval, fpushed;
> +    struct funcstack fstack;
> +
>     /*
>      * If EVALLINENO is not set, we use the line number of the
>      * environment and must flag this up to exec.c.  Otherwise,
>      * we use a special script name to indicate the special line number.
>      */
>     ineval = !isset(EVALLINENO);
> -    if (!ineval)
> +    if (!ineval) {
>        scriptname = "(eval)";
> +       fstack.prev = funcstack;
> +       fstack.name = scriptname;
> +       fstack.caller = funcstack ? funcstack->name : dupstring(argzero);
> +       fstack.lineno = lineno;
> +       fstack.tp = FS_EVAL;
> +
> +       /*
> +        * To get file line numbers, we need to know if parent is
> +        * the original script/shell or a sourced file, in which
> +        * case we use the line number raw, or a function or eval,
> +        * in which case we need to deduce where that came from.
> +        *
> +        * This replicates the logic for working out the information
> +        * for $funcfiletrace---eval is similar to an inlined function
> +        * call from a tracing perspective.
> +        */
> +       if (!funcstack || funcstack->tp == FS_SOURCE) {
> +           fstack.flineno = fstack.lineno;
> +           fstack.filename = fstack.caller;
> +       } else {
> +           fstack.flineno = funcstack->flineno + lineno;
> +           /*
> +            * Line numbers in eval start from 1, not zero,
> +            * so offset by one to get line in file.
> +            */
> +           if (funcstack->tp == FS_EVAL)
> +               fstack.flineno--;
> +           fstack.filename = funcstack->filename;
> +           if (!fstack.filename)
> +               fstack.filename = "";
> +       }
> +       funcstack = &fstack;
> +
> +       fpushed = 1;
> +    } else
> +       fpushed = 0;
>
>     prog = parse_string(zjoin(argv, ' ', 1));
>     if (prog) {
> @@ -4737,6 +4775,9 @@
>        lastval = 1;
>     }
>
> +    if (fpushed)
> +       funcstack = funcstack->prev;
> +
>     errflag = 0;
>     scriptname = oscriptname;
>     ineval = oineval;
> Index: Src/exec.c
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
> retrieving revision 1.145
> diff -u -r1.145 exec.c
> --- Src/exec.c  1 Sep 2008 20:18:47 -0000       1.145
> +++ Src/exec.c  2 Sep 2008 17:15:53 -0000
> @@ -4264,10 +4264,16 @@
>     }
>  #endif
>     fstack.name = dupstring(name);
> -    fstack.caller = dupstring(oargv0 ? oargv0 : argzero);
> +    /*
> +     * The caller is whatever is immediately before on the stack,
> +     * unless we're at the top, in which case it's the script
> +     * or interactive shell name.
> +     */
> +    fstack.caller = funcstack ? funcstack->name :
> +       dupstring(oargv0 ? oargv0 : argzero);
>     fstack.lineno = lineno;
>     fstack.prev = funcstack;
> -    fstack.sourced = 0;
> +    fstack.tp = FS_FUNC;
>     funcstack = &fstack;
>
>     if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) {
> @@ -4277,8 +4283,7 @@
>        fstack.flineno = 0;
>        fstack.filename = dupstring(fstack.caller);
>     }
> -
> -
> +
>     if (prog->flags & EF_RUN) {
>        Shfunc shf;
>
> Index: Src/init.c
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Src/init.c,v
> retrieving revision 1.94
> diff -u -r1.94 init.c
> --- Src/init.c  13 Aug 2008 21:02:03 -0000      1.94
> +++ Src/init.c  2 Sep 2008 17:15:53 -0000
> @@ -1061,6 +1061,7 @@
>     unsigned char *ocs;
>     int ocsp;
>     int otrap_return = trap_return, otrap_state = trap_state;
> +    struct funcstack fstack;
>
>     if (!s ||
>        (!(prog = try_source_file((us = unmeta(s)))) &&
> @@ -1100,19 +1101,17 @@
>     trap_state = TRAP_STATE_INACTIVE;
>
>     sourcelevel++;
> -    {
> -       struct funcstack fstack;
> -       fstack.name = dupstring("source");
> -       fstack.caller = dupstring(old_scriptfilename ? old_scriptfilename :
> -                                "zsh");
> -       fstack.flineno = 0;
> -       fstack.lineno = oldlineno;
> -       fstack.filename = fstack.name;
> -       fstack.prev = funcstack;
> -       fstack.sourced = 1;
> -       funcstack = &fstack;
> -    }
> -
> +
> +    fstack.name = scriptfilename;
> +    fstack.caller = funcstack ? funcstack->name :
> +       dupstring(old_scriptfilename ? old_scriptfilename : "zsh");
> +    fstack.flineno = 0;
> +    fstack.lineno = oldlineno;
> +    fstack.filename = scriptfilename;
> +    fstack.prev = funcstack;
> +    fstack.tp = FS_SOURCE;
> +    funcstack = &fstack;
> +
>     if (prog) {
>        pushheap();
>        errflag = 0;
> Index: Src/zsh.h
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
> retrieving revision 1.144
> diff -u -r1.144 zsh.h
> --- Src/zsh.h   31 Aug 2008 16:01:12 -0000      1.144
> +++ Src/zsh.h   2 Sep 2008 17:15:53 -0000
> @@ -1077,6 +1077,14 @@
>  #define SFC_COMPLETE 5         /* called from completion code */
>  #define SFC_CWIDGET  6         /* new style completion widget */
>
> +/* tp in funcstack */
> +
> +enum {
> +    FS_SOURCE,
> +    FS_FUNC,
> +    FS_EVAL
> +};
> +
>  /* node in function stack */
>
>  struct funcstack {
> @@ -1086,7 +1094,7 @@
>     char *caller;              /* name of caller */
>     zlong flineno;             /* line number in file */
>     zlong lineno;              /* line offset from beginning of function */
> -    int sourced;               /* type of entry is a sourced file */
> +    int tp;                    /* type of entry: sourced file, func, eval */
>  };
>
>  /* node in list of function call wrappers */
> Index: Src/Modules/parameter.c
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
> retrieving revision 1.47
> diff -u -r1.47 parameter.c
> --- Src/Modules/parameter.c     13 Aug 2008 21:02:04 -0000      1.47
> +++ Src/Modules/parameter.c     2 Sep 2008 17:15:54 -0000
> @@ -583,7 +583,7 @@
>     for (f = funcstack, p = ret; f; f = f->prev, p++) {
>        char *colonpair, *fname;
>
> -       if (!f->prev || f->prev->sourced) {
> +       if (!f->prev || f->prev->tp == FS_SOURCE) {
>            /*
>             * Calling context is a file---either the parent
>             * script or interactive shell, or a sourced
> @@ -595,13 +595,20 @@
>            sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
>        } else {
>            /*
> -            * Calling context is a function; we need to find the line number
> -            * in the file where that function was defined.  For this we need
> -            * the $funcsourcetrace information for the context above,
> +            * Calling context is a function or eval; we need to find
> +            * the line number in the file where that function was
> +            * defined or the eval was called.  For this we need the
> +            * $funcsourcetrace information for the context above,
>             * together with the $functrace line number for the current
>             * context.
>             */
>            long flineno = (long)(f->prev->flineno + f->lineno);
> +           /*
> +            * Line numbers in eval start from 1, not zero,
> +            * so offset by one to get line in file.
> +            */
> +           if (f->prev->tp == FS_EVAL)
> +               flineno--;
>            fname = f->prev->filename ? f->prev->filename : "";
>
>            colonpair = zhalloc(strlen(fname) + (flineno > 9999 ? 24 : 6));
> Index: Test/V06parameter.ztst
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Test/V06parameter.ztst,v
> retrieving revision 1.3
> diff -u -r1.3 V06parameter.ztst
> --- Test/V06parameter.ztst      12 Aug 2008 20:25:14 -0000      1.3
> +++ Test/V06parameter.ztst      2 Sep 2008 17:15:54 -0000
> @@ -36,4 +36,33 @@
>  >Inside autofn
>  >2 + ./functrace.zsh:21 + ./autofn:0
>  >In sourced file
> ->2 + ./functrace.zsh:22 + source:0
> +>2 + ./functrace.zsh:22 + ./sourcedfile:0
> +
> +  print -r -- 'module_path=(./Modules)
> +  debug_hook() { print $funcfiletrace[1] $functrace[1]; }
> +  set -o DEBUG_BEFORE_CMD
> +  trap "debug_hook" DEBUG
> +  fn() {
> +    a=1
> +    eval "b=2"
> +    c=3
> +  }
> +  fn
> +  w=5
> +  eval "x=6
> +  y=7"
> +  z=8' >rocky3.zsh
> +  $ZTST_testdir/../Src/zsh +Z -f ./rocky3.zsh
> +0:Eval tracing
> +>./rocky3.zsh:5 ./rocky3.zsh:5
> +>./rocky3.zsh:10 ./rocky3.zsh:10
> +>./rocky3.zsh:6 fn:1
> +>./rocky3.zsh:7 fn:2
> +>./rocky3.zsh:7 (eval):1
> +>./rocky3.zsh:8 fn:3
> +>./rocky3.zsh:11 ./rocky3.zsh:11
> +>./rocky3.zsh:12 ./rocky3.zsh:12
> +>./rocky3.zsh:12 (eval):1
> +>./rocky3.zsh:13 (eval):2
> +>./rocky3.zsh:14 ./rocky3.zsh:14
> +
>
> --
> Peter Stephenson <pws@csr.com>                  Software Engineer
> CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
> Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070
>


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-09-03  3:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-31 23:46 eval line number weirdness Rocky Bernstein
2008-09-02 17:28 ` Peter Stephenson
2008-09-03  3:37   ` Rocky Bernstein

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).