* Getting source file and line number of a function. @ 2008-07-27 1:06 Rocky Bernstein 2008-07-28 8:34 ` Peter Stephenson 0 siblings, 1 reply; 13+ messages in thread From: Rocky Bernstein @ 2008-07-27 1:06 UTC (permalink / raw) To: zsh-workers I see that zsh has now has array variables functrace and funcstack. Functrace stack gives a function name and a line offset from the function. But for many things involving location reporting, it would more be desirable to have a filename and absolute line location. Alternatively, if there were a way to get the filename and line number of the beginning of a given function, one can do some arithmetic to get the absolute position. Is there currently a way to get this information. Should I try at submitting a patch? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-07-27 1:06 Getting source file and line number of a function Rocky Bernstein @ 2008-07-28 8:34 ` Peter Stephenson 2008-07-28 12:46 ` Rocky Bernstein 0 siblings, 1 reply; 13+ messages in thread From: Peter Stephenson @ 2008-07-28 8:34 UTC (permalink / raw) To: zsh-workers "Rocky Bernstein" wrote: > I see that zsh has now has array variables functrace and > funcstack. Functrace stack gives a function name and a line offset > from the function. But for many things involving location reporting, > it would more be desirable to have a filename and absolute line > location. > > Alternatively, if there were a way to get the filename and line number > of the beginning of a given function, one can do some arithmetic to > get the absolute position. > > Is there currently a way to get this information. Should I try at > submitting a patch? It would be useful to have information referred to the autoload file, and I've wondered about how to do it, but I don't think it's trivial with the current way line numbers work. We would probably need to add an extra internal variable for file line numbers, and present another variable (or array, if in the funcstack style) to users to distinguish the two. -- Peter Stephenson <pws@csr.com> Software Engineer CSR PLC, Churchill House, Cambridge Business Park, Cowley Road Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-07-28 8:34 ` Peter Stephenson @ 2008-07-28 12:46 ` Rocky Bernstein 2008-07-30 2:31 ` Rocky Bernstein 2008-08-09 18:21 ` Peter Stephenson 0 siblings, 2 replies; 13+ messages in thread From: Rocky Bernstein @ 2008-07-28 12:46 UTC (permalink / raw) To: zsh-workers [-- Attachment #1: Type: text/plain, Size: 3419 bytes --] Patch should be added. It's not the only way to do this and it changes the functrace (which could easily be addressed, so there might be some discussion. Comments about how the patch works are below. For the little that I've tried, it seems to work. Of course there are other line number weirdnesses I haven't worked out yet. One thing more easily addressed is the fact that sourcing a file doesn't show in functrace and I think it should. I think sourcing is in fact like a function call. In fact one can write "source" as a function which does a read/eval of the file name. In looking at the code in surrounding the patch one question I have is how the strings allocated for funcstack->name and funcstack->caller get freed? This is relevant if one extends source to do the same thing. Thanks. On Mon, Jul 28, 2008 at 4:34 AM, Peter Stephenson <pws@csr.com> wrote: > "Rocky Bernstein" wrote: >> I see that zsh has now has array variables functrace and >> funcstack. Functrace stack gives a function name and a line offset >> from the function. But for many things involving location reporting, >> it would more be desirable to have a filename and absolute line >> location. >> >> Alternatively, if there were a way to get the filename and line number >> of the beginning of a given function, one can do some arithmetic to >> get the absolute position. >> >> Is there currently a way to get this information. Should I try at >> submitting a patch? > > It would be useful to have information referred to the autoload file, > and I've wondered about how to do it, but I don't think it's trivial > with the current way line numbers work. We would probably need to add > an extra internal variable for file line numbers, and present another > variable (or array, if in the funcstack style) to users to distinguish > the two. This is more or less the approach I tried. There is a variable called scriptname which I think is a little misleading. It is the name of the file when not in a function but gets set to a function name when that is run. So I added a variable called scriptfilename which mirrors scriptname but doesn't get changed when a function is run. When functions are defined, I save the current file, scriptfilename, and line number, lineno, in the shfunc structure. As for the C funcstack list, rather than remove any of the existing information, I added two more fields for the filename and absolute line number. Right now I changed the functrace routine in Src/Modules/parameter.c to use these new fields rather than the old ones. If one wants the function name rather than the file name, one can always use funcstack which has that. So right now you can't easily get the line number relative to the beginning of the function, although it's there. bash can show the new information, file name and starting line number using declare -F *fn* (Actually, shopt extdebug also has to be set.) It might be helpful to add that, and this would be one way to get the old function offset information. Another way would be to turn functrace into a builtin function and pass (an optional?) parameter indicating what flavor of information you want. Or a 3rd routine/variable could be used. > > -- > Peter Stephenson <pws@csr.com> Software Engineer > CSR PLC, Churchill House, Cambridge Business Park, Cowley Road > Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070 > [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: functrace-patch.diff --] [-- Type: text/x-diff; name=functrace-patch.diff, Size: 4418 bytes --] Index: Src/exec.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/exec.c,v retrieving revision 1.134 diff -u -r1.134 exec.c --- Src/exec.c 17 Jul 2008 11:27:57 -0000 1.134 +++ Src/exec.c 28 Jul 2008 01:48:40 -0000 @@ -3913,6 +3913,8 @@ shf = (Shfunc) zalloc(sizeof(*shf)); shf->funcdef = prog; shf->node.flags = 0; + shf->filename = ztrdup(scriptfilename); + shf->lineno = lineno; if (!names) { /* @@ -4123,6 +4125,7 @@ #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif + Shfunc shf; pushheap(); @@ -4193,7 +4196,15 @@ fstack.lineno = lineno; fstack.prev = funcstack; funcstack = &fstack; - + if (oargv0 && (shf = (Shfunc) shfunctab->getnode(shfunctab, oargv0))) { + fstack.flineno = shf->lineno + lineno; + fstack.filename = dupstring(shf->filename); + } else { + fstack.flineno = lineno; + fstack.filename = dupstring(fstack.caller); + } + + if (prog->flags & EF_RUN) { Shfunc shf; Index: Src/init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.86 diff -u -r1.86 init.c --- Src/init.c 17 Jul 2008 11:27:57 -0000 1.86 +++ Src/init.c 28 Jul 2008 01:48:41 -0000 @@ -334,6 +334,7 @@ } opts[INTERACTIVE] &= 1; argzero = *argv; + scriptfilename = argzero; argv++; } while (*argv) @@ -1096,8 +1097,20 @@ loops = 0; dosetopt(SHINSTDIN, 0, 1); scriptname = s; + scriptfilename = s; 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; @@ -1105,6 +1118,7 @@ popheap(); } else loop(0, 0); /* loop through the file to be sourced */ + /* funcstack = funcstack->prev; */ sourcelevel--; /* restore the current shell state */ Index: Src/utils.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/utils.c,v retrieving revision 1.197 diff -u -r1.197 utils.c --- Src/utils.c 17 Jul 2008 11:27:57 -0000 1.197 +++ Src/utils.c 28 Jul 2008 01:48:42 -0000 @@ -33,7 +33,8 @@ /* 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 { Index: Src/zsh.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v retrieving revision 1.138 diff -u -r1.138 zsh.h --- Src/zsh.h 12 Jun 2008 13:45:06 -0000 1.138 +++ Src/zsh.h 28 Jul 2008 01:48:43 -0000 @@ -1059,6 +1059,8 @@ struct shfunc { struct hashnode node; + char *filename; /* Name of file located in */ + int lineno; /* line number in above file */ Eprog funcdef; /* function definition */ }; @@ -1077,8 +1079,10 @@ 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 */ + int flineno; /* line number in file */ + int lineno; /* line offset from beginning of function */ }; /* node in list of function call wrappers */ cvs diff: Diffing Src/Builtins cvs diff: Diffing Src/Modules Index: Src/Modules/parameter.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v retrieving revision 1.45 diff -u -r1.45 parameter.c --- Src/Modules/parameter.c 5 Sep 2007 16:16:17 -0000 1.45 +++ Src/Modules/parameter.c 28 Jul 2008 01:48:46 -0000 @@ -528,8 +528,8 @@ for (f = funcstack, p = ret; f; f = f->prev, p++) { char *colonpair; - colonpair = zhalloc(strlen(f->caller) + (f->lineno > 9999 ? 24 : 6)); - sprintf(colonpair, "%s:%d", f->caller, f->lineno); + colonpair = zhalloc(strlen(f->filename) + (f->flineno > 9999 ? 24 : 6)); + sprintf(colonpair, "%s:%d", f->filename, f->flineno); *p = colonpair; } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-07-28 12:46 ` Rocky Bernstein @ 2008-07-30 2:31 ` Rocky Bernstein 2008-07-30 8:22 ` Peter Stephenson 2008-08-09 18:21 ` Peter Stephenson 1 sibling, 1 reply; 13+ messages in thread From: Rocky Bernstein @ 2008-07-30 2:31 UTC (permalink / raw) To: zsh-workers [-- Attachment #1: Type: text/plain, Size: 3850 bytes --] Attached is slight improvement on the patch posted before - it adds source files to be put in functrace. I'm not sure how functrace strings get freed; an explicit free() doesn't work However see my next post regarding trap DEBUG. On Mon, Jul 28, 2008 at 8:46 AM, Rocky Bernstein <rocky.bernstein@gmail.com> wrote: > Patch should be added. It's not the only way to do this and it changes > the functrace (which could easily be addressed, so there might be some > discussion. > > Comments about how the patch works are below. For the little that I've > tried, it seems to work. Of course there are other line number > weirdnesses I haven't worked out yet. > > One thing more easily addressed is the fact that sourcing a file > doesn't show in functrace and I think it should. I think sourcing is > in fact like a function call. In fact one can write "source" as a > function which does a read/eval of the file name. > > In looking at the code in surrounding the patch one question I have is > how the strings allocated for funcstack->name and funcstack->caller > get freed? This is relevant if one extends source to do the same > thing. > > Thanks. > > > On Mon, Jul 28, 2008 at 4:34 AM, Peter Stephenson <pws@csr.com> wrote: >> "Rocky Bernstein" wrote: >>> I see that zsh has now has array variables functrace and >>> funcstack. Functrace stack gives a function name and a line offset >>> from the function. But for many things involving location reporting, >>> it would more be desirable to have a filename and absolute line >>> location. >>> >>> Alternatively, if there were a way to get the filename and line number >>> of the beginning of a given function, one can do some arithmetic to >>> get the absolute position. >>> >>> Is there currently a way to get this information. Should I try at >>> submitting a patch? >> >> It would be useful to have information referred to the autoload file, >> and I've wondered about how to do it, but I don't think it's trivial >> with the current way line numbers work. We would probably need to add >> an extra internal variable for file line numbers, and present another >> variable (or array, if in the funcstack style) to users to distinguish >> the two. > > This is more or less the approach I tried. There is a variable called > scriptname which I think is a little misleading. It is the name of the > file when not in a function but gets set to a function name when that > is run. So I added a variable called scriptfilename which mirrors > scriptname but doesn't get changed when a function is run. > > When functions are defined, I save the current file, scriptfilename, > and line number, lineno, in the shfunc structure. As for the C > funcstack list, rather than remove any of the existing information, I > added two more fields for the filename and absolute line number. Right > now I changed the functrace routine in Src/Modules/parameter.c to use > these new fields rather than the old ones. If one wants the function > name rather than the file name, one can always use funcstack which has > that. So right now you can't easily get the line number relative to > the beginning of the function, although it's there. > > bash can show the new information, file name and starting line number using > > declare -F *fn* > > (Actually, shopt extdebug also has to be set.) It might be helpful to > add that, and this would be one way to get the old function offset > information. Another way would be to turn functrace into a builtin > function and pass (an optional?) parameter indicating what flavor of > information you want. Or a 3rd routine/variable could be used. > >> >> -- >> Peter Stephenson <pws@csr.com> Software Engineer >> CSR PLC, Churchill House, Cambridge Business Park, Cowley Road >> Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070 >> > [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: functrace.diff --] [-- Type: text/x-diff; name=functrace.diff, Size: 4621 bytes --] cvs diff -u cvs diff: Diffing . Index: exec.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/exec.c,v retrieving revision 1.134 diff -u -r1.134 exec.c --- exec.c 17 Jul 2008 11:27:57 -0000 1.134 +++ exec.c 30 Jul 2008 02:21:43 -0000 @@ -3913,6 +3913,8 @@ shf = (Shfunc) zalloc(sizeof(*shf)); shf->funcdef = prog; shf->node.flags = 0; + shf->filename = ztrdup(scriptfilename); + shf->lineno = lineno; if (!names) { /* @@ -4123,6 +4125,7 @@ #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif + Shfunc shf; pushheap(); @@ -4193,7 +4196,15 @@ fstack.lineno = lineno; fstack.prev = funcstack; funcstack = &fstack; - + if (oargv0 && (shf = (Shfunc) shfunctab->getnode(shfunctab, oargv0))) { + fstack.flineno = shf->lineno + lineno; + fstack.filename = dupstring(shf->filename); + } else { + fstack.flineno = lineno; + fstack.filename = dupstring(fstack.caller); + } + + if (prog->flags & EF_RUN) { Shfunc shf; Index: init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.86 diff -u -r1.86 init.c --- init.c 17 Jul 2008 11:27:57 -0000 1.86 +++ init.c 30 Jul 2008 02:21:43 -0000 @@ -334,6 +334,7 @@ } opts[INTERACTIVE] &= 1; argzero = *argv; + scriptfilename = argzero; argv++; } while (*argv) @@ -1065,8 +1066,10 @@ int oldshst, osubsh, oloops; FILE *obshin; char *old_scriptname = scriptname, *us; + const char *old_scriptfilename = scriptfilename; unsigned char *ocs; int ocsp; + struct funcstack fstack; if (!s || (!(prog = try_source_file((us = unmeta(s)))) && @@ -1096,8 +1099,17 @@ loops = 0; dosetopt(SHINSTDIN, 0, 1); scriptname = s; + scriptfilename = s; sourcelevel++; + fstack.name = "source"; + fstack.caller = dupstring(scriptname); + fstack.flineno = oldlineno; + fstack.lineno = oldlineno; + fstack.filename = dupstring(old_scriptfilename); + fstack.prev = funcstack; + funcstack = &fstack; + if (prog) { pushheap(); errflag = 0; @@ -1105,6 +1117,8 @@ popheap(); } else loop(0, 0); /* loop through the file to be sourced */ + funcstack = funcstack->prev; + scriptfilename = old_scriptfilename; sourcelevel--; /* restore the current shell state */ Index: utils.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/utils.c,v retrieving revision 1.197 diff -u -r1.197 utils.c --- utils.c 17 Jul 2008 11:27:57 -0000 1.197 +++ utils.c 30 Jul 2008 02:21:45 -0000 @@ -33,7 +33,8 @@ /* 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 { Index: zsh.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v retrieving revision 1.138 diff -u -r1.138 zsh.h --- zsh.h 12 Jun 2008 13:45:06 -0000 1.138 +++ zsh.h 30 Jul 2008 02:21:46 -0000 @@ -1059,6 +1059,8 @@ struct shfunc { struct hashnode node; + char *filename; /* Name of file located in */ + int lineno; /* line number in above file */ Eprog funcdef; /* function definition */ }; @@ -1077,8 +1079,10 @@ 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 */ + int flineno; /* line number in file */ + int lineno; /* line offset from beginning of function */ }; /* node in list of function call wrappers */ cvs diff: Diffing Builtins cvs diff: Diffing Modules Index: Modules/parameter.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v retrieving revision 1.45 diff -u -r1.45 parameter.c --- Modules/parameter.c 5 Sep 2007 16:16:17 -0000 1.45 +++ Modules/parameter.c 30 Jul 2008 02:21:46 -0000 @@ -528,8 +528,8 @@ for (f = funcstack, p = ret; f; f = f->prev, p++) { char *colonpair; - colonpair = zhalloc(strlen(f->caller) + (f->lineno > 9999 ? 24 : 6)); - sprintf(colonpair, "%s:%d", f->caller, f->lineno); + colonpair = zhalloc(strlen(f->filename) + (f->flineno > 9999 ? 24 : 6)); + sprintf(colonpair, "%s:%d", f->filename, f->flineno); *p = colonpair; } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-07-30 2:31 ` Rocky Bernstein @ 2008-07-30 8:22 ` Peter Stephenson 0 siblings, 0 replies; 13+ messages in thread From: Peter Stephenson @ 2008-07-30 8:22 UTC (permalink / raw) To: zsh-workers "Rocky Bernstein" wrote: > Attached is slight improvement on the patch posted before - it adds > source files to be put in functrace. I'm still working on the original---there's a lot that needs doing because getting all the different parts right is complicated. I'm still wondering how to get the line numbers for autoloaded functions correct (this seems to be an existing problem no one had noticed). So you'd better wait until I have a revised version of that before modifying it. -- Peter Stephenson <pws@csr.com> Software Engineer CSR PLC, Churchill House, Cambridge Business Park, Cowley Road Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-07-28 12:46 ` Rocky Bernstein 2008-07-30 2:31 ` Rocky Bernstein @ 2008-08-09 18:21 ` Peter Stephenson 2008-08-10 1:11 ` Rocky Bernstein 2008-08-11 14:00 ` Richard Hartmann 1 sibling, 2 replies; 13+ messages in thread From: Peter Stephenson @ 2008-08-09 18:21 UTC (permalink / raw) To: zsh-workers On Mon, 28 Jul 2008 08:46:43 -0400 "Rocky Bernstein" <rocky.bernstein@gmail.com> wrote: > Patch should be added. It's not the only way to do this and it changes > the functrace (which could easily be addressed, so there might be some > discussion. I've finally got something that's at least consistent. Whether it does what is needed is another matter, but I suspect it's at least going in the right direction. It's a little different from Rocky's original. Instead of hijacking $functrace, I've added another array, $funcfiletrace. I've made their behaviours' parallel one another, i.e. they're always the same length. What was really doing my brain in was working out what was supposed to be relative to what, given that I wanted to keep $functrace doing what it always did unless that really proved to be senseless (and I don't think it did). Eventually, I realised $functrace doesn't give you the current context, it gives you the calling context (i.e. if you want the current $LINENO or function name you get it some other way---the may be more work to do here about the name part). So I've made $funcfiletrace do the same, except that it's the context where the function was originally defined, not the point of the current call. Example below. In more detail, this modified version checks for a NULL scriptfilename, sets and also restores it in some more places (in particular autoload files), frees the filename from the Shfunc structure, tries to ensure that that is NULL if there isn't a name (that meant tracking down some more places where Shfunc's are created), handles NULL filenames in parameter.c, and fixes up an additional oddity with autoload (we don't know on the first execution of the function where the file is, so we need to fix up funcstack when it's already in use). I haven't done anything about the sourced script tracing yet. It's probably a good idea; we should obviously make sure it's consistent. There could be more stuff I've missed. For example, I haven't looked at whether ksh-style autoloads need something different. It's perfectly possible we'll need additional variables in zsh/parameter. It would be nice to have some way of telling what sort of context we were in (function defined in line or autloaded, sourced file, script). For now I'm happy if this looks like it's going the right way. Anyway, here's an example script showing this in action: ## start print Started functrace.zsh zmodload zsh/parameter print $LINENO; print $functrace; print $funcfiletrace fn() { print Inside function $0 print $LINENO; print $functrace; print $funcfiletrace } fn fpath=(. $fpath) echo 'print Inside $0 print $LINENO; print $functrace; print $funcfiletrace ' >autofn autoload autofn autofn autofn ## end Output: ## start Started functrace.zsh 4 Inside function fn 2 ../functrace.zsh:11 ../functrace.zsh:6 Inside autofn 2 ../functrace.zsh:21 ./autofn:0 Inside autofn 2 ../functrace.zsh:22 ./autofn:0 ## end Notes: - (As I said above) only when we're inside a function do $functrace and $funcfiletrace come alive, and then they give the calling context. - $functrace says where the function got called. $funcfiletrace says where the function got defined. - The line number 0 for the autoloaded function is not an error. The file is autofn; this is a zsh autoload, so the line that started the definition was not in the file at all. In other words, this is telling you the function was autoloaded from the entire contents of that file. It's a relative path here because it got picked up from "." in fpath; that's an unusual case in practice, so although it's true that the file name could be ambiguous I haven't felt like sanitizing the path. - The two autofn's are there to check the problem I noted above with the use of funcstack the first time. Index: Src/exec.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/exec.c,v retrieving revision 1.138 diff -u -r1.138 exec.c --- Src/exec.c 7 Aug 2008 16:25:16 -0000 1.138 +++ Src/exec.c 9 Aug 2008 18:10:14 -0000 @@ -191,7 +191,7 @@ parse_string(char *s) { Eprog p; - int oldlineno = lineno; + zlong oldlineno = lineno; lexsave(); inpush(s, INP_LINENO, NULL); @@ -1016,7 +1016,8 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ zwarn("%s: function not defined by file", n); locallevel++; popheap(); + zsfree(fname); return NULL; } } @@ -4133,6 +4148,7 @@ else shf->funcdef = dupeprog(stripkshdef(prog, shf->node.nam), 0); shf->node.flags &= ~PM_UNDEFINED; + shf->filename = fname; } popheap(); @@ -4172,6 +4188,7 @@ #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif + Shfunc shf; pushheap(); @@ -4243,6 +4260,15 @@ 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 @@ /**/ 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 @@ r = parse_string(d); scriptname = oldscriptname; + if (fname) + *fname = ztrdup(buf); + zfree(d, len + 1); return r; Index: Src/hashtable.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/hashtable.c,v retrieving revision 1.27 diff -u -r1.27 hashtable.c --- Src/hashtable.c 1 Nov 2007 10:59:40 -0000 1.27 +++ Src/hashtable.c 9 Aug 2008 18:10:14 -0000 @@ -852,6 +852,7 @@ zsfree(shf->node.nam); if (shf->funcdef) freeeprog(shf->funcdef); + zsfree(shf->filename); zfree(shf, sizeof(struct shfunc)); } Index: Src/init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.91 diff -u -r1.91 init.c --- Src/init.c 7 Aug 2008 16:25:16 -0000 1.91 +++ Src/init.c 9 Aug 2008 18:10:14 -0000 @@ -268,7 +268,7 @@ /* -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 @@ } opts[INTERACTIVE] &= 1; argzero = *argv; + scriptfilename = argzero; argv++; } while (*argv) @@ -1051,10 +1052,12 @@ 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 @@ loops = 0; dosetopt(SHINSTDIN, 0, 1); scriptname = s; + scriptfilename = s; /* * The special return behaviour of traps shouldn't @@ -1096,6 +1100,17 @@ 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 @@ popheap(); } else loop(0, 0); /* loop through the file to be sourced */ + /* funcstack = funcstack->prev; */ sourcelevel--; trap_state = otrap_state; @@ -1126,6 +1142,7 @@ if (!exit_pending) retflag = 0; scriptname = old_scriptname; + scriptfilename = old_scriptfilename; free(cmdstack); cmdstack = ocs; cmdsp = ocsp; Index: Src/parse.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/parse.c,v retrieving revision 1.70 diff -u -r1.70 parse.c --- Src/parse.c 1 Jul 2008 18:38:40 -0000 1.70 +++ Src/parse.c 9 Aug 2008 18:10:15 -0000 @@ -720,7 +720,8 @@ static int par_pline(int *complex) { - int p, line = lineno; + int p; + zlong line = lineno; p = ecadd(0); @@ -1414,8 +1415,9 @@ 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 @@ 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 @@ 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; Index: Src/utils.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/utils.c,v retrieving revision 1.198 diff -u -r1.198 utils.c --- Src/utils.c 31 Jul 2008 08:44:21 -0000 1.198 +++ Src/utils.c 9 Aug 2008 18:10:17 -0000 @@ -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 { Index: Src/zsh.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v retrieving revision 1.140 diff -u -r1.140 zsh.h --- Src/zsh.h 7 Aug 2008 16:25:16 -0000 1.140 +++ Src/zsh.h 9 Aug 2008 18:10:18 -0000 @@ -1061,6 +1061,8 @@ 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 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 */ Index: Src/Modules/parameter.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v retrieving revision 1.45 diff -u -r1.45 parameter.c --- Src/Modules/parameter.c 5 Sep 2007 16:16:17 -0000 1.45 +++ Src/Modules/parameter.c 9 Aug 2008 18:10:18 -0000 @@ -286,7 +286,7 @@ 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 @@ 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 funcfiletrace special parameter. */ + +/**/ +static char ** +funcfiletracegetfn(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 @@ { funcstackgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array functrace_gsu = { functracegetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array funcfiletrace_gsu = +{ funcfiletracegetfn, arrsetfn, stdunsetfn }; static const struct gsu_array reswords_gsu = { reswordsgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array disreswords_gsu = @@ -1807,6 +1837,8 @@ scanpmfunctions), SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, &functrace_gsu, NULL, NULL), + SPECIALPMDEF("funcfiletrace", PM_ARRAY|PM_READONLY, + &funcfiletrace_gsu, NULL, NULL), SPECIALPMDEF("galiases", 0, &pmgaliases_gsu, getpmgalias, scanpmgaliases), SPECIALPMDEF("history", PM_READONLY, -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-09 18:21 ` Peter Stephenson @ 2008-08-10 1:11 ` Rocky Bernstein 2008-08-11 19:32 ` Peter Stephenson 2008-08-11 14:00 ` Richard Hartmann 1 sibling, 1 reply; 13+ messages in thread From: Rocky Bernstein @ 2008-08-10 1:11 UTC (permalink / raw) To: zsh-workers Great! Let me know when code is committed into CVS which includes tracking source calls, and I'll revise the zshdb code then. Ditto for instruction skipping and/or showing the command to be run. Thanks. On Sat, Aug 9, 2008 at 2:21 PM, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: > On Mon, 28 Jul 2008 08:46:43 -0400 > "Rocky Bernstein" <rocky.bernstein@gmail.com> wrote: >> Patch should be added. It's not the only way to do this and it changes >> the functrace (which could easily be addressed, so there might be some >> discussion. > > I've finally got something that's at least consistent. Whether it does > what is needed is another matter, but I suspect it's at least going in > the right direction. It's a little different from Rocky's original. > > Instead of hijacking $functrace, I've added another array, > $funcfiletrace. I've made their behaviours' parallel one another, > i.e. they're always the same length. > > What was really doing my brain in was working out what was supposed to > be relative to what, given that I wanted to keep $functrace doing what > it always did unless that really proved to be senseless (and I don't > think it did). Eventually, I realised $functrace doesn't give you the > current context, it gives you the calling context (i.e. if you want the > current $LINENO or function name you get it some other way---the may be > more work to do here about the name part). So I've made $funcfiletrace > do the same, except that it's the context where the function was > originally defined, not the point of the current call. Example below. > > In more detail, this modified version checks for a NULL scriptfilename, > sets and also restores it in some more places (in particular autoload > files), frees the filename from the Shfunc structure, tries to ensure > that that is NULL if there isn't a name (that meant tracking down some > more places where Shfunc's are created), handles NULL filenames in > parameter.c, and fixes up an additional oddity with autoload (we don't > know on the first execution of the function where the file is, so we > need to fix up funcstack when it's already in use). > > I haven't done anything about the sourced script tracing yet. It's > probably a good idea; we should obviously make sure it's consistent. > > There could be more stuff I've missed. For example, I haven't looked at > whether ksh-style autoloads need something different. It's perfectly > possible we'll need additional variables in zsh/parameter. It would be > nice to have some way of telling what sort of context we were in > (function defined in line or autloaded, sourced file, script). For now > I'm happy if this looks like it's going the right way. > > Anyway, here's an example script showing this in action: > > > ## start > print Started functrace.zsh > zmodload zsh/parameter > > print $LINENO; print $functrace; print $funcfiletrace > > fn() { > print Inside function $0 > print $LINENO; print $functrace; print $funcfiletrace > } > > fn > > fpath=(. $fpath) > > echo 'print Inside $0 > print $LINENO; print $functrace; print $funcfiletrace > ' >autofn > > autoload autofn > > autofn > autofn > ## end > > > Output: > > > ## start > Started functrace.zsh > 4 > > > Inside function fn > 2 > ../functrace.zsh:11 > ../functrace.zsh:6 > Inside autofn > 2 > ../functrace.zsh:21 > ./autofn:0 > Inside autofn > 2 > ../functrace.zsh:22 > ./autofn:0 > ## end > > > Notes: > - (As I said above) only when we're inside a function do $functrace and > $funcfiletrace come alive, and then they give the calling context. > > - $functrace says where the function got called. $funcfiletrace says where > the function got defined. > > - The line number 0 for the autoloaded function is not an error. The > file is autofn; this is a zsh autoload, so the line that started > the definition was not in the file at all. In other words, this > is telling you the function was autoloaded from the entire contents of > that file. It's a relative path here because it got picked up from > "." in fpath; that's an unusual case in practice, so although it's > true that the file name could be ambiguous I haven't felt like > sanitizing the path. > > - The two autofn's are there to check the problem I noted above with > the use of funcstack the first time. > > > Index: Src/exec.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/exec.c,v > retrieving revision 1.138 > diff -u -r1.138 exec.c > --- Src/exec.c 7 Aug 2008 16:25:16 -0000 1.138 > +++ Src/exec.c 9 Aug 2008 18:10:14 -0000 > @@ -191,7 +191,7 @@ > parse_string(char *s) > { > Eprog p; > - int oldlineno = lineno; > + zlong oldlineno = lineno; > > lexsave(); > inpush(s, INP_LINENO, NULL); > @@ -1016,7 +1016,8 @@ > 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 @@ > 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 @@ > 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 @@ > { > 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 @@ > 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 @@ > zwarn("%s: function not defined by file", n); > locallevel++; > popheap(); > + zsfree(fname); > return NULL; > } > } > @@ -4133,6 +4148,7 @@ > else > shf->funcdef = dupeprog(stripkshdef(prog, shf->node.nam), 0); > shf->node.flags &= ~PM_UNDEFINED; > + shf->filename = fname; > } > popheap(); > > @@ -4172,6 +4188,7 @@ > #ifdef MAX_FUNCTION_DEPTH > static int funcdepth; > #endif > + Shfunc shf; > > pushheap(); > > @@ -4243,6 +4260,15 @@ > 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 @@ > > /**/ > 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 @@ > r = parse_string(d); > scriptname = oldscriptname; > > + if (fname) > + *fname = ztrdup(buf); > + > zfree(d, len + 1); > > return r; > Index: Src/hashtable.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/hashtable.c,v > retrieving revision 1.27 > diff -u -r1.27 hashtable.c > --- Src/hashtable.c 1 Nov 2007 10:59:40 -0000 1.27 > +++ Src/hashtable.c 9 Aug 2008 18:10:14 -0000 > @@ -852,6 +852,7 @@ > zsfree(shf->node.nam); > if (shf->funcdef) > freeeprog(shf->funcdef); > + zsfree(shf->filename); > zfree(shf, sizeof(struct shfunc)); > } > > Index: Src/init.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/init.c,v > retrieving revision 1.91 > diff -u -r1.91 init.c > --- Src/init.c 7 Aug 2008 16:25:16 -0000 1.91 > +++ Src/init.c 9 Aug 2008 18:10:14 -0000 > @@ -268,7 +268,7 @@ > /* -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 @@ > } > opts[INTERACTIVE] &= 1; > argzero = *argv; > + scriptfilename = argzero; > argv++; > } > while (*argv) > @@ -1051,10 +1052,12 @@ > 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 @@ > loops = 0; > dosetopt(SHINSTDIN, 0, 1); > scriptname = s; > + scriptfilename = s; > > /* > * The special return behaviour of traps shouldn't > @@ -1096,6 +1100,17 @@ > 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 @@ > popheap(); > } else > loop(0, 0); /* loop through the file to be sourced */ > + /* funcstack = funcstack->prev; */ > sourcelevel--; > > trap_state = otrap_state; > @@ -1126,6 +1142,7 @@ > if (!exit_pending) > retflag = 0; > scriptname = old_scriptname; > + scriptfilename = old_scriptfilename; > free(cmdstack); > cmdstack = ocs; > cmdsp = ocsp; > Index: Src/parse.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/parse.c,v > retrieving revision 1.70 > diff -u -r1.70 parse.c > --- Src/parse.c 1 Jul 2008 18:38:40 -0000 1.70 > +++ Src/parse.c 9 Aug 2008 18:10:15 -0000 > @@ -720,7 +720,8 @@ > static int > par_pline(int *complex) > { > - int p, line = lineno; > + int p; > + zlong line = lineno; > > p = ecadd(0); > > @@ -1414,8 +1415,9 @@ > 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 @@ > 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 @@ > 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; > Index: Src/utils.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/utils.c,v > retrieving revision 1.198 > diff -u -r1.198 utils.c > --- Src/utils.c 31 Jul 2008 08:44:21 -0000 1.198 > +++ Src/utils.c 9 Aug 2008 18:10:17 -0000 > @@ -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 { > Index: Src/zsh.h > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v > retrieving revision 1.140 > diff -u -r1.140 zsh.h > --- Src/zsh.h 7 Aug 2008 16:25:16 -0000 1.140 > +++ Src/zsh.h 9 Aug 2008 18:10:18 -0000 > @@ -1061,6 +1061,8 @@ > > 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 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 */ > Index: Src/Modules/parameter.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v > retrieving revision 1.45 > diff -u -r1.45 parameter.c > --- Src/Modules/parameter.c 5 Sep 2007 16:16:17 -0000 1.45 > +++ Src/Modules/parameter.c 9 Aug 2008 18:10:18 -0000 > @@ -286,7 +286,7 @@ > 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 @@ > 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 funcfiletrace special parameter. */ > + > +/**/ > +static char ** > +funcfiletracegetfn(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 @@ > { funcstackgetfn, arrsetfn, stdunsetfn }; > static const struct gsu_array functrace_gsu = > { functracegetfn, arrsetfn, stdunsetfn }; > +static const struct gsu_array funcfiletrace_gsu = > +{ funcfiletracegetfn, arrsetfn, stdunsetfn }; > static const struct gsu_array reswords_gsu = > { reswordsgetfn, arrsetfn, stdunsetfn }; > static const struct gsu_array disreswords_gsu = > @@ -1807,6 +1837,8 @@ > scanpmfunctions), > SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, > &functrace_gsu, NULL, NULL), > + SPECIALPMDEF("funcfiletrace", PM_ARRAY|PM_READONLY, > + &funcfiletrace_gsu, NULL, NULL), > SPECIALPMDEF("galiases", 0, > &pmgaliases_gsu, getpmgalias, scanpmgaliases), > SPECIALPMDEF("history", PM_READONLY, > -- > Peter Stephenson <p.w.stephenson@ntlworld.com> > Web page now at http://homepage.ntlworld.com/p.w.stephenson/ > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-10 1:11 ` Rocky Bernstein @ 2008-08-11 19:32 ` Peter Stephenson 2008-08-11 19:39 ` Rocky Bernstein 0 siblings, 1 reply; 13+ messages in thread From: Peter Stephenson @ 2008-08-11 19:32 UTC (permalink / raw) To: zsh-workers "Rocky Bernstein" wrote: > Great! Let me know when code is committed into CVS which includes > tracking source calls, and I'll revise the zshdb code then. > > Ditto for instruction skipping and/or showing the command to be run. I've committed the source code tracing, but I decided "funcsourcetrace" was a better name than "funcfiletrace", since "file" doesn't really distinguish the purpose of the new variable. I've added a test and fixed a couple of additional bugs. The test is fairly simple and it's quite possible that extending it would reveal further problems. The instruction skipping using "setopt ERR_EXIT" is also there. -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-11 19:32 ` Peter Stephenson @ 2008-08-11 19:39 ` Rocky Bernstein 2008-08-11 19:51 ` Peter Stephenson 0 siblings, 1 reply; 13+ messages in thread From: Rocky Bernstein @ 2008-08-11 19:39 UTC (permalink / raw) To: zsh-workers funcsourcetrace contains entries for source'd files, right? On Mon, Aug 11, 2008 at 3:32 PM, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: > "Rocky Bernstein" wrote: >> Great! Let me know when code is committed into CVS which includes >> tracking source calls, and I'll revise the zshdb code then. >> >> Ditto for instruction skipping and/or showing the command to be run. > > I've committed the source code tracing, but I decided "funcsourcetrace" > was a better name than "funcfiletrace", since "file" doesn't really > distinguish the purpose of the new variable. I've added a test and > fixed a couple of additional bugs. The test is fairly simple and it's > quite possible that extending it would reveal further problems. > > The instruction skipping using "setopt ERR_EXIT" is also there. > > -- > Peter Stephenson <p.w.stephenson@ntlworld.com> > Web page now at http://homepage.ntlworld.com/p.w.stephenson/ > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-11 19:39 ` Rocky Bernstein @ 2008-08-11 19:51 ` Peter Stephenson 2008-08-11 20:01 ` Rocky Bernstein 0 siblings, 1 reply; 13+ messages in thread From: Peter Stephenson @ 2008-08-11 19:51 UTC (permalink / raw) To: Rocky Bernstein; +Cc: zsh-workers, pws "Rocky Bernstein" wrote: > funcsourcetrace contains entries for source'd files, right? It's still just the information for the source of functions. I haven't modified it to know about sourced files yet. -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-11 19:51 ` Peter Stephenson @ 2008-08-11 20:01 ` Rocky Bernstein 0 siblings, 0 replies; 13+ messages in thread From: Rocky Bernstein @ 2008-08-11 20:01 UTC (permalink / raw) To: zsh-workers Ok. I think I'll hold off updating until that happens. On Mon, Aug 11, 2008 at 3:51 PM, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: > "Rocky Bernstein" wrote: >> funcsourcetrace contains entries for source'd files, right? > > It's still just the information for the source of functions. I haven't > modified it to know about sourced files yet. > > -- > Peter Stephenson <p.w.stephenson@ntlworld.com> > Web page now at http://homepage.ntlworld.com/p.w.stephenson/ > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-09 18:21 ` Peter Stephenson 2008-08-10 1:11 ` Rocky Bernstein @ 2008-08-11 14:00 ` Richard Hartmann 2008-08-13 20:51 ` Peter Stephenson 1 sibling, 1 reply; 13+ messages in thread From: Richard Hartmann @ 2008-08-11 14:00 UTC (permalink / raw) To: Peter Stephenson; +Cc: zsh-workers On Sat, Aug 9, 2008 at 20:21, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: [stuff about $funcfiletrace] This just gave me an idea: Why not enhance `whence` so it is able to tell in what file and starting on what line a function has been defined? Richard ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Getting source file and line number of a function. 2008-08-11 14:00 ` Richard Hartmann @ 2008-08-13 20:51 ` Peter Stephenson 0 siblings, 0 replies; 13+ messages in thread From: Peter Stephenson @ 2008-08-13 20:51 UTC (permalink / raw) To: zsh-workers On Mon, 11 Aug 2008 16:00:21 +0200 "Richard Hartmann" <richih.mailinglist@gmail.com> wrote: > On Sat, Aug 9, 2008 at 20:21, Peter Stephenson > <p.w.stephenson@ntlworld.com> wrote: > > [stuff about $funcfiletrace] (which now really is called that...) > This just gave me an idea: Why not enhance `whence` so it is able to > tell in what file and starting on what line a function has been defined? Just to note I haven't forgot this yet (haven't looked at if or where it fits without messing up the format). I think it would be useful to provide an associative array in zsh/parameter with this information to get at it easily, something like $functionsources (since the assoc array with the functions is called $functions). -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-08-13 20:52 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-07-27 1:06 Getting source file and line number of a function Rocky Bernstein 2008-07-28 8:34 ` Peter Stephenson 2008-07-28 12:46 ` Rocky Bernstein 2008-07-30 2:31 ` Rocky Bernstein 2008-07-30 8:22 ` Peter Stephenson 2008-08-09 18:21 ` Peter Stephenson 2008-08-10 1:11 ` Rocky Bernstein 2008-08-11 19:32 ` Peter Stephenson 2008-08-11 19:39 ` Rocky Bernstein 2008-08-11 19:51 ` Peter Stephenson 2008-08-11 20:01 ` Rocky Bernstein 2008-08-11 14:00 ` Richard Hartmann 2008-08-13 20:51 ` Peter Stephenson
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).