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:
parent
ae79d264a3
commit
0cba5ef62a
8 changed files with 134 additions and 34 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
13
Src/exec.c
13
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;
|
||||
|
||||
|
|
|
|||
25
Src/init.c
25
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;
|
||||
|
|
|
|||
10
Src/zsh.h
10
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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue