1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-29 05:21:00 +01:00

25595: fix line numbers with EVAL_LINENO,

try to fix oddities with funcstack and sourced files,
simplify use of caller element of funcstack
This commit is contained in:
Peter Stephenson 2008-09-03 09:08:18 +00:00
parent ae79d264a3
commit 0cba5ef62a
8 changed files with 134 additions and 34 deletions

View file

@ -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

View file

@ -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.
)

View file

@ -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));

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

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

View file

@ -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