about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-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
5 files changed, 84 insertions, 24 deletions
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 */