summaryrefslogtreecommitdiff
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 */