Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Getting source file and line number of a function.



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@xxxxxxxxx> 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@xxxxxxx> 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@xxxxxxx>                  Software Engineer
>> CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
>> Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070
>>
>
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;
     }


Messages sorted by: Reverse Date, Date, Thread, Author