about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-09-03 09:08:18 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-09-03 09:08:18 +0000
commit0cba5ef62ad8e98924c2bd9367f9c7c7e72e2fd0 (patch)
treeaff6e4b164bdd8dd1ad12c921ee774405a5ea244
parentae79d264a3fd989713f6c7413c5096151413f284 (diff)
downloadzsh-0cba5ef62ad8e98924c2bd9367f9c7c7e72e2fd0.tar.gz
zsh-0cba5ef62ad8e98924c2bd9367f9c7c7e72e2fd0.tar.xz
zsh-0cba5ef62ad8e98924c2bd9367f9c7c7e72e2fd0.zip
25595: fix line numbers with EVAL_LINENO,
try to fix oddities with funcstack and sourced files,
simplify use of caller element of funcstack
-rw-r--r--ChangeLog8
-rw-r--r--Doc/Zsh/mod_parameter.yo21
-rw-r--r--Src/Modules/parameter.c15
-rw-r--r--Src/builtin.c45
-rw-r--r--Src/exec.c13
-rw-r--r--Src/init.c25
-rw-r--r--Src/zsh.h10
-rw-r--r--Test/V06parameter.ztst31
8 files changed, 134 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 52a79b8d5..7f0023247 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-09-03  Peter Stephenson  <pws@csr.com>
+
+	* 25595: Doc/Zsh/mod_parameter.yo, Src/builtin.c, Src/exec.c,
+	Src/init.c, Src/zsh.h, Src/Modules/parameter.c,
+	Test/V06parameter.ztst: fix line numbers with EVAL_LINENO;
+	try to fix up oddities with funcstack for source files;
+	simplify use of caller element of funcstack.
+
 2008-09-02  Barton E. Schaefer  <schaefer@zsh.org>
 
 	* 25600: Functions/Prompts/prompt_bart_setup: fix pattern
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo
index 5a9f5c318..0f2c21252 100644
--- a/Doc/Zsh/mod_parameter.yo
+++ b/Doc/Zsh/mod_parameter.yo
@@ -167,7 +167,8 @@ directories.
 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 @@ files, rather than relative to the start of a function, if any.
 )
 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.
 )
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 4119c4982..b6c8c5608 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -583,7 +583,7 @@ funcfiletracegetfn(UNUSED(Param pm))
     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 @@ funcfiletracegetfn(UNUSED(Param pm))
 	    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));
diff --git a/Src/builtin.c b/Src/builtin.c
index 654665bfc..69f0aaa6e 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4712,15 +4712,53 @@ bin_eval(UNUSED(char *nam), char **argv, UNUSED(Options ops), UNUSED(int func))
 {
     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 @@ bin_eval(UNUSED(char *nam), char **argv, UNUSED(Options ops), UNUSED(int func))
 	lastval = 1;
     }
 
+    if (fpushed)
+	funcstack = funcstack->prev;
+
     errflag = 0;
     scriptname = oscriptname;
     ineval = oineval;
diff --git a/Src/exec.c b/Src/exec.c
index cf0efed19..a46dfd683 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -4264,10 +4264,16 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
     }
 #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 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
 	fstack.flineno = 0;
 	fstack.filename = dupstring(fstack.caller);
     }
-    
-    
+
     if (prog->flags & EF_RUN) {
 	Shfunc shf;
 
diff --git a/Src/init.c b/Src/init.c
index 7e912a363..923b94876 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1061,6 +1061,7 @@ source(char *s)
     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 @@ source(char *s)
     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;
diff --git a/Src/zsh.h b/Src/zsh.h
index 011aa3634..9326e1a11 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1077,6 +1077,14 @@ struct shfunc {
 #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 @@ struct funcstack {
     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 */
diff --git a/Test/V06parameter.ztst b/Test/V06parameter.ztst
index ce6dacee9..98136a38f 100644
--- a/Test/V06parameter.ztst
+++ b/Test/V06parameter.ztst
@@ -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
+