summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-08-11 19:22:54 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-08-11 19:22:54 +0000
commit2853ca830ac8d504b7374de2be0ec82122d33c2d (patch)
treed86ea41af13f51f6a9549833a3463c6da307bfc0
parent2e485d60ffbf14a461a2d814b30245a9141abeb7 (diff)
downloadzsh-2853ca830ac8d504b7374de2be0ec82122d33c2d.tar.gz
zsh-2853ca830ac8d504b7374de2be0ec82122d33c2d.zip
25247 with further modifications: add $funcsourcetrace
-rw-r--r--ChangeLog9
-rw-r--r--Doc/Zsh/mod_parameter.yo12
-rw-r--r--Src/Modules/parameter.c36
-rw-r--r--Src/Modules/parameter.mdd2
-rw-r--r--Src/exec.c41
-rw-r--r--Src/hashtable.c1
-rw-r--r--Src/init.c21
-rw-r--r--Src/parse.c12
-rw-r--r--Src/signals.c1
-rw-r--r--Src/utils.c5
-rw-r--r--Src/zsh.h6
-rw-r--r--Test/.distfiles1
-rw-r--r--Test/V01zmodload.ztst1
-rw-r--r--Test/V06parameter.ztst37
14 files changed, 167 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 973fcb941..0fc0e5c99 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-08-11 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 25247 with further modifications: Doc/Zsh/mod_parameter.yo,
+ Src/exec.c, Src/hashtable.c, Src/init.c, Src/parse.c,
+ Src/signals.c, Src/utils.c, Src/zsh.h, Src/Modules/parameter.c,
+ Src/Modules/parameter.mdd, Test/.distfiles,
+ Test/V01zmodload.ztst, Test/V06parameter.ztst: add
+ $funcsourcetrace parameter to zsh/parameter.
+
2008-08-11 Peter Stephenson <pws@csr.com>
* unposted: Doc/Zsh/builtins.yo, Doc/Zsh/func.yo: prevent various
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo
index 434397fbf..d3ace6df0 100644
--- a/Doc/Zsh/mod_parameter.yo
+++ b/Doc/Zsh/mod_parameter.yo
@@ -164,6 +164,16 @@ item(tt(userdirs))(
This associative array maps user names to the pathnames of their home
directories.
)
+vindex(funcsourcetrace)
+item(tt(funcsourcetrace))(
+This array contains the file names and line numbers of the
+points where the functions 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.
+The format of each element is var(filename)tt(:)var(lineno).
+)
vindex(funcstack)
item(tt(funcstack))(
This array contains the names of the functions currently being
@@ -174,6 +184,6 @@ vindex(functrace)
item(tt(functrace))(
This array contains the names and line numbers of the callers
corresponding to the functions currently being executed.
-The format of each element is name:lineno.
+The format of each element is var(name)tt(:)var(lineno).
)
enditem()
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index efb22fafd..74593afc0 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -286,7 +286,7 @@ setfunction(char *name, char *val, int dis)
zsfree(val);
return;
}
- shf = (Shfunc) zalloc(sizeof(*shf));
+ shf = (Shfunc) zshcalloc(sizeof(*shf));
shf->funcdef = dupeprog(prog, 0);
shf->node.flags = dis;
@@ -529,7 +529,35 @@ functracegetfn(UNUSED(Param pm))
char *colonpair;
colonpair = zhalloc(strlen(f->caller) + (f->lineno > 9999 ? 24 : 6));
- sprintf(colonpair, "%s:%d", f->caller, f->lineno);
+ sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
+
+ *p = colonpair;
+ }
+ *p = NULL;
+
+ return ret;
+}
+
+/* Functions for the funcsourcetrace special parameter. */
+
+/**/
+static char **
+funcsourcetracegetfn(UNUSED(Param pm))
+{
+ Funcstack f;
+ int num;
+ char **ret, **p;
+
+ for (f = funcstack, num = 0; f; f = f->prev, num++);
+
+ ret = (char **) zhalloc((num + 1) * sizeof(char *));
+
+ for (f = funcstack, p = ret; f; f = f->prev, p++) {
+ char *colonpair;
+ char *fname = f->filename ? f->filename : "";
+
+ colonpair = zhalloc(strlen(fname) + (f->flineno > 9999 ? 24 : 6));
+ sprintf(colonpair, "%s:%ld", fname, (long)f->flineno);
*p = colonpair;
}
@@ -1773,6 +1801,8 @@ static const struct gsu_array funcstack_gsu =
{ funcstackgetfn, arrsetfn, stdunsetfn };
static const struct gsu_array functrace_gsu =
{ functracegetfn, arrsetfn, stdunsetfn };
+static const struct gsu_array funcsourcetrace_gsu =
+{ funcsourcetracegetfn, arrsetfn, stdunsetfn };
static const struct gsu_array reswords_gsu =
{ reswordsgetfn, arrsetfn, stdunsetfn };
static const struct gsu_array disreswords_gsu =
@@ -1801,6 +1831,8 @@ static struct paramdef partab[] = {
&disreswords_gsu, NULL, NULL),
SPECIALPMDEF("dis_saliases", 0,
&pmdissaliases_gsu, getpmdissalias, scanpmdissaliases),
+ SPECIALPMDEF("funcsourcetrace", PM_ARRAY|PM_READONLY,
+ &funcsourcetrace_gsu, NULL, NULL),
SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY,
&funcstack_gsu, NULL, NULL),
SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
diff --git a/Src/Modules/parameter.mdd b/Src/Modules/parameter.mdd
index d506dacb3..04cb6d077 100644
--- a/Src/Modules/parameter.mdd
+++ b/Src/Modules/parameter.mdd
@@ -2,6 +2,6 @@ name=zsh/parameter
link=either
load=yes
-autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases"
+autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcsourcetrace p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases"
objects="parameter.o"
diff --git a/Src/exec.c b/Src/exec.c
index 6ca5b2f2b..f483f7aaf 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -191,7 +191,7 @@ mod_export Eprog
parse_string(char *s)
{
Eprog p;
- int oldlineno = lineno;
+ zlong oldlineno = lineno;
lexsave();
inpush(s, INP_LINENO, NULL);
@@ -1016,7 +1016,8 @@ execlist(Estate state, int dont_change_job, int exiting)
Wordcode next;
wordcode code;
int ret, cj, csp, ltype;
- int old_pline_level, old_list_pipe, oldlineno;
+ int old_pline_level, old_list_pipe;
+ zlong oldlineno;
/*
* ERREXIT only forces the shell to exit if the last command in a &&
* or || fails. This is the case even if an earlier command is a
@@ -3961,6 +3962,8 @@ execfuncdef(Estate state, UNUSED(int do_exec))
shf = (Shfunc) zalloc(sizeof(*shf));
shf->funcdef = prog;
shf->node.flags = 0;
+ shf->filename = ztrdup(scriptfilename);
+ shf->lineno = lineno;
if (!names) {
/*
@@ -4059,15 +4062,24 @@ static int
execautofn(Estate state, UNUSED(int do_exec))
{
Shfunc shf;
- char *oldscriptname;
+ char *oldscriptname, *oldscriptfilename;
if (!(shf = loadautofn(state->prog->shf, 1, 0)))
return 1;
+ /*
+ * Probably we didn't know the filename where this function was
+ * defined yet.
+ */
+ if (funcstack && !funcstack->filename)
+ funcstack->filename = dupstring(shf->filename);
+
oldscriptname = scriptname;
- scriptname = dupstring(shf->node.nam);
+ oldscriptfilename = scriptfilename;
+ scriptname = scriptfilename = dupstring(shf->node.nam);
execode(shf->funcdef, 1, 0);
scriptname = oldscriptname;
+ scriptfilename = oldscriptfilename;
return lastval;
}
@@ -4078,11 +4090,12 @@ loadautofn(Shfunc shf, int fksh, int autol)
{
int noalias = noaliases, ksh = 1;
Eprog prog;
+ char *fname;
pushheap();
noaliases = (shf->node.flags & PM_UNALIASED);
- prog = getfpfunc(shf->node.nam, &ksh);
+ prog = getfpfunc(shf->node.nam, &ksh, &fname);
noaliases = noalias;
if (ksh == 1) {
@@ -4112,6 +4125,7 @@ loadautofn(Shfunc shf, int fksh, int autol)
else
shf->funcdef = dupeprog(prog, 0);
shf->node.flags &= ~PM_UNDEFINED;
+ shf->filename = fname;
} else {
VARARR(char, n, strlen(shf->node.nam) + 1);
strcpy(n, shf->node.nam);
@@ -4123,6 +4137,7 @@ loadautofn(Shfunc shf, int fksh, int autol)
zwarn("%s: function not defined by file", n);
locallevel++;
popheap();
+ zsfree(fname);
return NULL;
}
}
@@ -4133,6 +4148,7 @@ loadautofn(Shfunc shf, int fksh, int autol)
else
shf->funcdef = dupeprog(stripkshdef(prog, shf->node.nam), 0);
shf->node.flags &= ~PM_UNDEFINED;
+ shf->filename = fname;
}
popheap();
@@ -4172,6 +4188,7 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
#ifdef MAX_FUNCTION_DEPTH
static int funcdepth;
#endif
+ Shfunc shf;
pushheap();
@@ -4243,6 +4260,15 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
fstack.prev = funcstack;
funcstack = &fstack;
+ if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) {
+ fstack.flineno = shf->lineno;
+ fstack.filename = dupstring(shf->filename);
+ } else {
+ fstack.flineno = 0;
+ fstack.filename = dupstring(fstack.caller);
+ }
+
+
if (prog->flags & EF_RUN) {
Shfunc shf;
@@ -4362,7 +4388,7 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
/**/
Eprog
-getfpfunc(char *s, int *ksh)
+getfpfunc(char *s, int *ksh, char **fname)
{
char **pp, buf[PATH_MAX];
off_t len;
@@ -4397,6 +4423,9 @@ getfpfunc(char *s, int *ksh)
r = parse_string(d);
scriptname = oldscriptname;
+ if (fname)
+ *fname = ztrdup(buf);
+
zfree(d, len + 1);
return r;
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 160cda506..212882b3f 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -852,6 +852,7 @@ freeshfuncnode(HashNode hn)
zsfree(shf->node.nam);
if (shf->funcdef)
freeeprog(shf->funcdef);
+ zsfree(shf->filename);
zfree(shf, sizeof(struct shfunc));
}
diff --git a/Src/init.c b/Src/init.c
index d8a0dbc57..2f84fc445 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -268,7 +268,7 @@ parseargs(char **argv)
/* -c command */
cmd = *argv;
opts[INTERACTIVE] &= 1;
- scriptname = ztrdup("zsh");
+ scriptname = scriptfilename = ztrdup("zsh");
} else if (**argv == 'o') {
if (!*++*argv)
argv++;
@@ -325,6 +325,7 @@ parseargs(char **argv)
}
opts[INTERACTIVE] &= 1;
argzero = *argv;
+ scriptfilename = argzero;
argv++;
}
while (*argv)
@@ -1051,10 +1052,12 @@ mod_export int
source(char *s)
{
Eprog prog;
- int tempfd = -1, fd, cj, oldlineno;
+ int tempfd = -1, fd, cj;
+ zlong oldlineno;
int oldshst, osubsh, oloops;
FILE *obshin;
char *old_scriptname = scriptname, *us;
+ char *old_scriptfilename = scriptfilename;
unsigned char *ocs;
int ocsp;
int otrap_return = trap_return, otrap_state = trap_state;
@@ -1087,6 +1090,7 @@ source(char *s)
loops = 0;
dosetopt(SHINSTDIN, 0, 1);
scriptname = s;
+ scriptfilename = s;
/*
* The special return behaviour of traps shouldn't
@@ -1096,6 +1100,17 @@ source(char *s)
trap_state = TRAP_STATE_INACTIVE;
sourcelevel++;
+ /* { */
+ /* struct funcstack fstack; */
+ /* fstack.name = dupstring("source"); */
+ /* fstack.caller = dupstring(scriptfilename); */
+ /* fstack.flineno = oldlineno; */
+ /* fstack.lineno = oldlineno; */
+ /* fstack.filename = NULL; */
+ /* fstack.prev = funcstack; */
+ /* funcstack = &fstack; */
+ /* } */
+
if (prog) {
pushheap();
errflag = 0;
@@ -1103,6 +1118,7 @@ source(char *s)
popheap();
} else
loop(0, 0); /* loop through the file to be sourced */
+ /* funcstack = funcstack->prev; */
sourcelevel--;
trap_state = otrap_state;
@@ -1126,6 +1142,7 @@ source(char *s)
if (!exit_pending)
retflag = 0;
scriptname = old_scriptname;
+ scriptfilename = old_scriptfilename;
free(cmdstack);
cmdstack = ocs;
cmdsp = ocsp;
diff --git a/Src/parse.c b/Src/parse.c
index beb88b451..a455b591e 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -720,7 +720,8 @@ par_sublist2(int *complex)
static int
par_pline(int *complex)
{
- int p, line = lineno;
+ int p;
+ zlong line = lineno;
p = ecadd(0);
@@ -1414,8 +1415,9 @@ par_subsh(int *complex)
static void
par_funcdef(void)
{
- int oecused = ecused, oldlineno = lineno, num = 0, onp, p, c = 0;
+ int oecused = ecused, num = 0, onp, p, c = 0;
int so, oecssub = ecssub;
+ zlong oldlineno = lineno;
lineno = 0;
nocorrect = 1;
@@ -1646,7 +1648,8 @@ par_simple(int *complex, int nr)
p += nrediradd;
sr += nrediradd;
} else if (tok == INOUTPAR) {
- int oldlineno = lineno, onp, so, oecssub = ecssub;
+ zlong oldlineno = lineno;
+ int onp, so, oecssub = ecssub;
*complex = c;
lineno = 0;
@@ -2860,7 +2863,8 @@ cur_add_func(char *nam, Shfunc shf, LinkList names, LinkList progs,
return 1;
}
noaliases = (shf->node.flags & PM_UNALIASED);
- if (!(prog = getfpfunc(shf->node.nam, NULL)) || prog == &dummy_eprog) {
+ if (!(prog = getfpfunc(shf->node.nam, NULL, NULL)) ||
+ prog == &dummy_eprog) {
noaliases = ona;
zwarnnam(nam, "can't load function: %s", shf->node.nam);
return 1;
diff --git a/Src/signals.c b/Src/signals.c
index d978c3dec..b794f1527 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -705,6 +705,7 @@ dosavetrap(int sig, int level)
newshf->node.nam = ztrdup(shf->node.nam);
newshf->node.flags = shf->node.flags;
newshf->funcdef = dupeprog(shf->funcdef, 0);
+ newshf->filename = ztrdup(shf->filename);
if (shf->node.flags & PM_UNDEFINED)
newshf->funcdef->shf = newshf;
}
diff --git a/Src/utils.c b/Src/utils.c
index ec2df7cd0..dfece68a8 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -33,7 +33,10 @@
/* name of script being sourced */
/**/
-mod_export char *scriptname;
+mod_export char *scriptname; /* is sometimes a function name */
+
+/**/
+mod_export char *scriptfilename;
#ifdef MULTIBYTE_SUPPORT
struct widechar_array {
diff --git a/Src/zsh.h b/Src/zsh.h
index 49c08c7ac..173b89183 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1061,6 +1061,8 @@ struct cmdnam {
struct shfunc {
struct hashnode node;
+ char *filename; /* Name of file located in */
+ int lineno; /* line number in above file */
Eprog funcdef; /* function definition */
};
@@ -1079,8 +1081,10 @@ struct shfunc {
struct funcstack {
Funcstack prev; /* previous in stack */
char *name; /* name of function called */
+ char *filename; /* file function resides in */
char *caller; /* name of caller */
- int lineno; /* line number in file */
+ zlong flineno; /* line number in file */
+ zlong lineno; /* line offset from beginning of function */
};
/* node in list of function call wrappers */
diff --git a/Test/.distfiles b/Test/.distfiles
index 6fd78491b..53d2b2dd6 100644
--- a/Test/.distfiles
+++ b/Test/.distfiles
@@ -33,6 +33,7 @@ V02zregexparse.ztst
V03mathfunc.ztst
V04features.ztst
V05styles.ztst
+V06parameter.ztst
Y01completion.ztst
Y02compmatch.ztst
Y03arguments.ztst
diff --git a/Test/V01zmodload.ztst b/Test/V01zmodload.ztst
index a51535791..55ac9004d 100644
--- a/Test/V01zmodload.ztst
+++ b/Test/V01zmodload.ztst
@@ -183,6 +183,7 @@
>p:dis_galiases
>p:dis_reswords
>p:dis_saliases
+>p:funcsourcetrace
>p:funcstack
>p:functions
>p:functrace
diff --git a/Test/V06parameter.ztst b/Test/V06parameter.ztst
new file mode 100644
index 000000000..8b4fc30d5
--- /dev/null
+++ b/Test/V06parameter.ztst
@@ -0,0 +1,37 @@
+%prep
+
+ zmodload zsh/parameter
+
+%test
+
+ print -r -- 'print Started functrace.zsh
+ :
+ print $LINENO + $functrace + $funcsourcetrace
+ :
+ fn() {
+ print Inside function $0
+ print $LINENO + $functrace + $funcsourcetrace
+ }
+ :
+ fn
+ :
+ fpath=(. $fpath)
+ :
+ echo '\''print Inside $0
+ print $LINENO + $functrace + $funcsourcetrace
+ '\'' >autofn
+ :
+ autoload autofn
+ :
+ autofn
+ autofn' >functrace.zsh
+ $ZTST_testdir/../Src/zsh +Z -f ./functrace.zsh
+0:Function tracing
+>Started functrace.zsh
+>3 + +
+>Inside function fn
+>2 + ./functrace.zsh:10 + ./functrace.zsh:5
+>Inside autofn
+>2 + ./functrace.zsh:20 + ./autofn:0
+>Inside autofn
+>2 + ./functrace.zsh:21 + ./autofn:0