about summary refs log tree commit diff
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.tar.xz
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