From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1170 invoked from network); 17 Sep 2008 16:40:23 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00,HTML_MESSAGE, WEIRD_PORT autolearn=no version=3.2.5 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 17 Sep 2008 16:40:23 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 7156 invoked from network); 17 Sep 2008 16:40:02 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 17 Sep 2008 16:40:02 -0000 Received: (qmail 19504 invoked by alias); 17 Sep 2008 16:39:51 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 25680 Received: (qmail 19479 invoked from network); 17 Sep 2008 16:39:49 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 17 Sep 2008 16:39:49 -0000 Received: from py-out-1112.google.com (py-out-1112.google.com [64.233.166.178]) by bifrost.dotsrc.org (Postfix) with ESMTP id 1B730802720D for ; Wed, 17 Sep 2008 18:39:38 +0200 (CEST) Received: by py-out-1112.google.com with SMTP id u77so2520985pyb.23 for ; Wed, 17 Sep 2008 09:39:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:cc:in-reply-to:mime-version:content-type:references; bh=R+sDDfeRUb7Ogh/B8ex/XY0NGMIZ4/WwLQ/btklC96A=; b=X66sK5VyblKf19FDtQGBrIHZHbcRd5+pPjN6ZhAeWAhRz6ebr79Xirq0ifnvb0ZGVq T69l42YpKJcB+LOVRu/b8AddY6/dkNSvVUPsseRj7K1IzxbRMMPYib3eGBE5IjXit8C9 /hh8aoDc7Kt4XwT/wHLXnS9ifrjK6R6FXH3JU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:in-reply-to:mime-version :content-type:references; b=VQ/OoLscP6D31skotxUIbLDExoN+mkjTSiDCXRYoyFmtu/ypIq7qd+2b70l0LEsnZc CTtW5cY56WbMLgjhyvDPiaqCuUQxve/VjYJZ/46w9zNW9tpSXp0SgcrMXyD2gtv8Q0qX /Gfx9sgkSIfUVYLauNCf2KIgY8MTFzS3A6Yj0= Received: by 10.114.151.13 with SMTP id y13mr2349161wad.134.1221669576379; Wed, 17 Sep 2008 09:39:36 -0700 (PDT) Received: by 10.114.159.2 with HTTP; Wed, 17 Sep 2008 09:39:36 -0700 (PDT) Message-ID: <6cd6de210809170939p968d36bufda419592a10cb45@mail.gmail.com> Date: Wed, 17 Sep 2008 12:39:36 -0400 From: "Rocky Bernstein" To: "Peter Stephenson" Subject: Re: PATCH: source file info from PS4 Cc: "Zsh hackers list" In-Reply-To: <6005.1221576641@csr.com> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_5861_15142014.1221669576362" References: <6005.1221576641@csr.com> X-Virus-Scanned: ClamAV 0.92.1/8270/Wed Sep 17 15:15:56 2008 on bifrost X-Virus-Status: Clean ------=_Part_5861_15142014.1221669576362 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline On Tue, Sep 16, 2008 at 10:50 AM, Peter Stephenson wrote: > Now we have logic for finding the source file and corresponding line > number of executed code, this adds the prompt escapes %x and %I which > are like %N and %i but for the file where the code was defined. Looks like this has problems when used inside trap DEBUG. Consider this test program: PS4='%x:%I: ' hook() { set -x bug a 5 1 } bug() { typeset source_file="$1" typeset -ir lineno=$2 typeset -ir is_temp=$3 } trap hook DEBUG a=1 b=2 Here is the output I get: zsh ./linebug.sh ./linebug.sh:15: bug a 5 1 ./linebug.sh:19: typeset 'source_file=a' ./linebug.sh:19: typeset -ir 'lineno=5' ./linebug.sh:19: typeset -ir 'is_temp=1' ./linebug.sh:16: bug a 5 1 ./linebug.sh:20: typeset 'source_file=a' ./linebug.sh:20: typeset -ir 'lineno=5' ./linebug.sh:20: typeset -ir 'is_temp=1' Not sure where 19 and 20 are coming from since the program only has 16 lines. And also curious is why they don't change when commands get run. > %x isn't > ideal but upper and lower case %s, %f and %n are all used. It stands > for "execution file", or something. The idea is that you set > PS4='+%x:%I>' > > While doing this, I spotted that we could improve the information > available to funcstack and the interface to doshfunc() by passing in a > Shfunc instead of an Eprog. This is a *much* cleaner interface. Now > the funcstack entry is guaranteed to get the details of the shell > function correct. > > Index: Doc/Zsh/prompt.yo > =================================================================== > RCS file: /cvsroot/zsh/zsh/Doc/Zsh/prompt.yo,v > retrieving revision 1.15 > diff -u -r1.15 prompt.yo > --- Doc/Zsh/prompt.yo 24 Jun 2008 08:44:16 -0000 1.15 > +++ Doc/Zsh/prompt.yo 16 Sep 2008 14:41:10 -0000 > @@ -113,6 +113,11 @@ > shell function given by tt(%N). This is most useful for debugging as part > of tt($PS4). > ) > +item(tt(%I))( > +The line number currently being executed in the file tt(%x). This is > +similar to tt(%i), but the line number is always a line number in the > +file where the code was defined, even if the code is a shell function. > +) > item(tt(%j))( > The number of jobs. > ) > @@ -126,6 +131,11 @@ > the `tt(%)' to specify a number of trailing path components to show; zero > means the full path. A negative integer specifies leading components. > ) > +item(tt(%x))( > +The name of the file containing the source code currently being > +executed. This behaves as tt(%N) except that function and eval command > +names are not shown, instead the file where they were defined. > +) > xitem(tt(%c)) > xitem(tt(%.)) > item(tt(%C))( > Index: Src/exec.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/exec.c,v > retrieving revision 1.151 > diff -u -r1.151 exec.c > --- Src/exec.c 11 Sep 2008 17:14:39 -0000 1.151 > +++ Src/exec.c 16 Sep 2008 14:41:10 -0000 > @@ -518,7 +518,7 @@ > return 127; > > pushnode(args, arg0); > - return doshfunc(shf->node.nam, shf->funcdef, args, shf->node.flags, > 1); > + return doshfunc(shf, args, shf->node.flags, 1); > } > > /* execute an external command */ > @@ -4064,7 +4064,7 @@ > cmdsp = 0; > if ((osfc = sfcontext) == SFC_NONE) > sfcontext = SFC_DIRECT; > - doshfunc(shf->node.nam, shf->funcdef, args, shf->node.flags, 0); > + doshfunc(shf, args, shf->node.flags, 0); > sfcontext = osfc; > free(cmdstack); > cmdstack = ocs; > @@ -4200,18 +4200,20 @@ > > /**/ > mod_export int > -doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int > noreturnval) > +doshfunc(Shfunc shfunc, LinkList doshargs, int flags, int noreturnval) > { > char **tab, **x, *oargv0; > int oldzoptind, oldlastval, oldoptcind, oldnumpipestats, ret; > int *oldpipestats = NULL; > - char saveopts[OPT_SIZE], *oldscriptname = scriptname, *fname = > dupstring(name); > + char saveopts[OPT_SIZE], *oldscriptname = scriptname; > + char *name = shfunc->node.nam; > + char *fname = dupstring(name); > int obreaks, saveemulation ; > + Eprog prog; > struct funcstack fstack; > #ifdef MAX_FUNCTION_DEPTH > static int funcdepth; > #endif > - Shfunc shf; > > pushheap(); > > @@ -4291,14 +4293,10 @@ > fstack.tp = FS_FUNC; > 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); > - } > + fstack.flineno = shfunc->lineno; > + fstack.filename = dupstring(shfunc->filename); > > + prog = shfunc->funcdef; > if (prog->flags & EF_RUN) { > Shfunc shf; > > Index: Src/init.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/init.c,v > retrieving revision 1.96 > diff -u -r1.96 init.c > --- Src/init.c 11 Sep 2008 17:14:39 -0000 1.96 > +++ Src/init.c 16 Sep 2008 14:41:10 -0000 > @@ -149,7 +149,7 @@ > int toksav = tok; > > if (toplevel && > - (getshfunc("preexec") != &dummy_eprog || > + (getshfunc("preexec") || > paramtab->getnode(paramtab, "preexec_functions"))) { > LinkList args; > char *cmdstr; > Index: Src/math.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/math.c,v > retrieving revision 1.33 > diff -u -r1.33 math.c > --- Src/math.c 12 Jun 2008 13:45:06 -0000 1.33 > +++ Src/math.c 16 Sep 2008 14:41:10 -0000 > @@ -868,11 +868,11 @@ > argc <= f->maxargs)) { > if (f->flags & MFF_USERFUNC) { > char *shfnam = f->module ? f->module : n; > - Eprog prog = getshfunc(shfnam); > - if (prog == &dummy_eprog) > + Shfunc shfunc = getshfunc(shfnam); > + if (!shfunc) > zerr("no such function: %s", shfnam); > else { > - doshfunc(n, prog, l, 0, 1); > + doshfunc(shfunc, l, 0, 1); > return lastmathval; > } > } else { > Index: Src/prompt.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/prompt.c,v > retrieving revision 1.53 > diff -u -r1.53 prompt.c > --- Src/prompt.c 15 Sep 2008 16:18:06 -0000 1.53 > +++ Src/prompt.c 16 Sep 2008 14:41:11 -0000 > @@ -725,11 +725,37 @@ > if(Rstring) > stradd(Rstring); > break; > + case 'I': > + if (funcstack && funcstack->tp != FS_SOURCE) { > + /* > + * We're in a function or an eval with > + * EVALLINENO. Calculate the line number in > + * the file. > + */ > + zlong flineno = lineno + funcstack->flineno; > + /* take account of eval line nos. starting at 1 */ > + if (funcstack->tp == FS_EVAL) > + lineno--; > + addbufspc(DIGBUFSIZE); > + sprintf(bp, "%ld", (long)flineno); > + bp += strlen(bp); > + break; > + } > + /* else we're in a file and lineno is already correct */ > + /* FALLTHROUGH */ > case 'i': > addbufspc(DIGBUFSIZE); > sprintf(bp, "%ld", (long)lineno); > bp += strlen(bp); > break; > + case 'x': > + if (funcstack && funcstack->tp != FS_SOURCE) > + promptpath(funcstack->filename ? funcstack->filename : > "", > + arg, 0); > + else > + promptpath(scriptfilename ? scriptfilename : argzero, > + arg, 0); > + break; > case '\0': > return 0; > case Meta: > Index: Src/signals.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/signals.c,v > retrieving revision 1.50 > diff -u -r1.50 signals.c > --- Src/signals.c 11 Aug 2008 19:22:54 -0000 1.50 > +++ Src/signals.c 16 Sep 2008 14:41:11 -0000 > @@ -963,8 +963,7 @@ > } > > if (exittr) { > - dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ? > - ((Shfunc)exitfn)->funcdef : (Eprog) exitfn); > + dotrapargs(SIGEXIT, &exittr, exitfn); > if (exittr & ZSIG_FUNC) > shfunctab->freenode((HashNode)exitfn); > else > @@ -1077,8 +1076,16 @@ > /**/ > int trapisfunc; > > +/* > + * sig is the signal number. > + * *sigtr is the value to be taken as the field in sigtrapped (since > + * that may have changed by this point if we are exiting). > + * sigfn is an Eprog with a non-function eval list, or a Shfunc > + * with a function trap. It may be NULL with an ignored signal. > + */ > + > /**/ > -void > +static void > dotrapargs(int sig, int *sigtr, void *sigfn) > { > LinkList args; > @@ -1153,7 +1160,7 @@ > trapisfunc = isfunc = 1; > > sfcontext = SFC_SIGNAL; > - doshfunc(name, sigfn, args, 0, 1); > + doshfunc((Shfunc)sigfn, args, 0, 1); > sfcontext = osc; > freelinklist(args, (FreeFunc) NULL); > zsfree(name); > @@ -1162,7 +1169,7 @@ > trap_state = TRAP_STATE_PRIMED; > trapisfunc = isfunc = 0; > > - execode(sigfn, 1, 0); > + execode((Eprog)sigfn, 1, 0); > } > runhookdef(AFTERTRAPHOOK, NULL); > > @@ -1215,12 +1222,12 @@ > void > dotrap(int sig) > { > - Eprog funcprog; > + void *funcprog; > > if (sigtrapped[sig] & ZSIG_FUNC) { > HashNode hn = gettrapnode(sig, 0); > if (hn) > - funcprog = ((Shfunc)hn)->funcdef; > + funcprog = hn; > else { > #ifdef DEBUG > dputs("BUG: running function trap which has escaped."); > @@ -1230,7 +1237,11 @@ > } else > funcprog = siglists[sig]; > > - /* Copied from dotrapargs(). */ > + /* > + * Copied from dotrapargs(). > + * (In fact, the gain from duplicating this appears to be virtually > + * zero. Not sure why it's here.) > + */ > if ((sigtrapped[sig] & ZSIG_IGNORED) || !funcprog || errflag) > return; > > Index: Src/utils.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/utils.c,v > retrieving revision 1.199 > diff -u -r1.199 utils.c > --- Src/utils.c 11 Aug 2008 19:22:54 -0000 1.199 > +++ Src/utils.c 16 Sep 2008 14:41:11 -0000 > @@ -35,6 +35,8 @@ > /**/ > mod_export char *scriptname; /* is sometimes a function name */ > > +/* filename of script or other file containing code source e.g. autoload > */ > + > /**/ > mod_export char *scriptfilename; > > @@ -1134,7 +1136,7 @@ > mod_export int > callhookfunc(char *name, LinkList lnklst, int arrayp, int *retval) > { > - Eprog prog; > + Shfunc shfunc; > /* > * Save stopmsg, since user doesn't get a chance to respond > * to a list of jobs generated in a hook. > @@ -1143,8 +1145,8 @@ > > sfcontext = SFC_HOOK; > > - if ((prog = getshfunc(name)) != &dummy_eprog) { > - ret = doshfunc(name, prog, lnklst, 0, 1); > + if ((shfunc = getshfunc(name))) { > + ret = doshfunc(shfunc, lnklst, 0, 1); > stat = 0; > } > > @@ -1159,8 +1161,8 @@ > > if ((arrptr = getaparam(arrnam))) { > for (; *arrptr; arrptr++) { > - if ((prog = getshfunc(*arrptr)) != &dummy_eprog) { > - int newret = doshfunc(arrnam, prog, lnklst, 0, 1); > + if ((shfunc = getshfunc(*arrptr))) { > + int newret = doshfunc(shfunc, lnklst, 0, 1); > if (!ret) > ret = newret; > stat = 0; > @@ -2893,15 +2895,10 @@ > /* Get the definition of a shell function */ > > /**/ > -mod_export Eprog > +mod_export Shfunc > getshfunc(char *nam) > { > - Shfunc shf; > - > - if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, nam))) > - return &dummy_eprog; > - > - return shf->funcdef; > + return (Shfunc) shfunctab->getnode(shfunctab, nam); > } > > /**/ > Index: Src/Modules/zftp.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/Modules/zftp.c,v > retrieving revision 1.48 > diff -u -r1.48 zftp.c > --- Src/Modules/zftp.c 4 Sep 2008 22:23:52 -0000 1.48 > +++ Src/Modules/zftp.c 16 Sep 2008 14:41:11 -0000 > @@ -1469,9 +1469,9 @@ > char lsbuf[ZF_BUFSIZE], *ascbuf = NULL, *optr; > off_t sofar = 0, last_sofar = 0; > readwrite_t read_ptr = zfread, write_ptr = zfwrite; > - Eprog prog; > + Shfunc shfunc; > > - if (progress && (prog = getshfunc("zftp_progress")) != &dummy_eprog) { > + if (progress && (shfunc = getshfunc("zftp_progress"))) { > /* > * progress to set up: ZFTP_COUNT is zero. > * We do this here in case we needed to wait for a RETR > @@ -1480,7 +1480,7 @@ > int osc = sfcontext; > > sfcontext = SFC_HOOK; > - doshfunc("zftp_progress", prog, NULL, 0, 1); > + doshfunc(shfunc, NULL, 0, 1); > sfcontext = osc; > /* Now add in the bit of the file we've got/sent already */ > sofar = last_sofar = startat; > @@ -1608,12 +1608,12 @@ > } else > break; > if (!ret && sofar != last_sofar && progress && > - (prog = getshfunc("zftp_progress")) != &dummy_eprog) { > + (shfunc = getshfunc("zftp_progress"))) { > int osc = sfcontext; > > zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER); > sfcontext = SFC_HOOK; > - doshfunc("zftp_progress", prog, NULL, 0, 1); > + doshfunc(shfunc, NULL, 0, 1); > sfcontext = osc; > last_sofar = sofar; > } > @@ -2364,7 +2364,7 @@ > { > char *ptr, *eptr; > int endc; > - Eprog prog; > + Shfunc shfunc; > > if (zfprefs & ZFPF_DUMB) > return 1; > @@ -2391,11 +2391,11 @@ > * front end. By putting it here, and in close when ZFTP_PWD is unset, > * we at least cover the bases. > */ > - if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) { > + if ((shfunc = getshfunc("zftp_chpwd"))) { > int osc = sfcontext; > > sfcontext = SFC_HOOK; > - doshfunc("zftp_chpwd", prog, NULL, 0, 1); > + doshfunc(shfunc, NULL, 0, 1); > sfcontext = osc; > } > return 0; > @@ -2549,7 +2549,7 @@ > { > int ret = 0, recv = (flags & ZFTP_RECV), getsize = 0, progress = 1; > char *cmd = recv ? "RETR " : (flags & ZFTP_APPE) ? "APPE " : "STOR "; > - Eprog prog; > + Shfunc shfunc; > > /* > * At this point I'd like to set progress to 0 if we're > @@ -2567,7 +2567,7 @@ > for (; *args; args++) { > char *ln, *rest = NULL; > off_t startat = 0; > - if (progress && (prog = getshfunc("zftp_progress")) != > &dummy_eprog) { > + if (progress && (shfunc = getshfunc("zftp_progress"))) { > off_t sz = -1; > /* > * This calls the SIZE command to get the size for remote > @@ -2608,14 +2608,14 @@ > * if and only if we called zfsenddata(); > */ > if (progress && ret != 2 && > - (prog = getshfunc("zftp_progress")) != &dummy_eprog) { > + (shfunc = getshfunc("zftp_progress"))) { > /* progress to finish: ZFTP_TRANSFER set to GF or PF */ > int osc = sfcontext; > > zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"), > ZFPM_READONLY); > sfcontext = SFC_HOOK; > - doshfunc("zftp_progress", prog, NULL, 0, 1); > + doshfunc(shfunc, NULL, 0, 1); > sfcontext = osc; > } > if (rest) { > @@ -2715,7 +2715,7 @@ > zfclose(int leaveparams) > { > char **aptr; > - Eprog prog; > + Shfunc shfunc; > > if (!zfsess->control) > return; > @@ -2766,11 +2766,11 @@ > zfunsetparam(*aptr); > > /* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */ > - if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) { > + if ((shfunc = getshfunc("zftp_chpwd"))) { > int osc = sfcontext; > > sfcontext = SFC_HOOK; > - doshfunc("zftp_chpwd", prog, NULL, 0, 1); > + doshfunc(shfunc, NULL, 0, 1); > sfcontext = osc; > } > } > Index: Src/Zle/compcore.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/Zle/compcore.c,v > retrieving revision 1.96 > diff -u -r1.96 compcore.c > --- Src/Zle/compcore.c 7 Jul 2008 08:33:28 -0000 1.96 > +++ Src/Zle/compcore.c 16 Sep 2008 14:41:12 -0000 > @@ -540,13 +540,13 @@ > static void > callcompfunc(char *s, char *fn) > { > - Eprog prog; > + Shfunc shfunc; > int lv = lastval; > char buf[20]; > > METACHECK(); > > - if ((prog = getshfunc(fn)) != &dummy_eprog) { > + if ((shfunc = getshfunc(fn))) { > char **p, *tmp; > int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; > unsigned int rset, kset; > @@ -814,7 +814,7 @@ > while (*p) > addlinknode(largs, dupstring(*p++)); > } > - doshfunc(fn, prog, largs, 0, 0); > + doshfunc(shfunc, largs, 0, 0); > cfret = lastval; > lastval = olv; > } OLDHEAPS; > Index: Src/Zle/compctl.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/Zle/compctl.c,v > retrieving revision 1.35 > diff -u -r1.35 compctl.c > --- Src/Zle/compctl.c 3 Oct 2007 16:18:38 -0000 1.35 > +++ Src/Zle/compctl.c 16 Sep 2008 14:41:12 -0000 > @@ -3635,12 +3635,12 @@ > } > if (cc->func) { > /* This handles the compctl -K flag. */ > - Eprog prog; > + Shfunc shfunc; > char **r; > int lv = lastval; > > /* Get the function. */ > - if ((prog = getshfunc(cc->func)) != &dummy_eprog) { > + if ((shfunc = getshfunc(cc->func))) { > /* We have it, so build a argument list. */ > LinkList args = newlinklist(); > int osc = sfcontext; > @@ -3664,7 +3664,7 @@ > incompctlfunc = 1; > sfcontext = SFC_COMPLETE; > /* Call the function. */ > - doshfunc(cc->func, prog, args, 0, 1); > + doshfunc(shfunc, args, 0, 1); > sfcontext = osc; > incompctlfunc = 0; > /* And get the result from the reply parameter. */ > @@ -3809,12 +3809,12 @@ > /* generate the user-defined display list: if anything fails, * > * we silently allow the normal completion list to be used. */ > char **yaptr = NULL, *uv = NULL; > - Eprog prog; > + Shfunc shfunc; > > if (cc->ylist[0] == '$' || cc->ylist[0] == '(') { > /* from variable */ > uv = cc->ylist + (cc->ylist[0] == '$'); > - } else if ((prog = getshfunc(cc->ylist)) != &dummy_eprog) { > + } else if ((shfunc = getshfunc(cc->ylist))) { > /* from function: pass completions as arg list */ > LinkList args = newlinklist(); > LinkNode ln; > @@ -3839,7 +3839,7 @@ > if (incompfunc != 1) > incompctlfunc = 1; > sfcontext = SFC_COMPLETE; > - doshfunc(cc->ylist, prog, args, 0, 1); > + doshfunc(shfunc, args, 0, 1); > sfcontext = osc; > incompctlfunc = 0; > uv = "reply"; > Index: Src/Zle/zle_main.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v > retrieving revision 1.115 > diff -u -r1.115 zle_main.c > --- Src/Zle/zle_main.c 8 Sep 2008 06:24:23 -0000 1.115 > +++ Src/Zle/zle_main.c 16 Sep 2008 14:41:12 -0000 > @@ -1304,9 +1304,8 @@ > r = 1; > } else { > Shfunc shf = (Shfunc) shfunctab->getnode(shfunctab, w->u.fnnam); > - Eprog prog = (shf ? shf->funcdef : &dummy_eprog); > > - if(prog == &dummy_eprog) { > + if (!shf) { > /* the shell function doesn't exist */ > char *nm = nicedup(w->u.fnnam, 0); > char *msg = tricat("No such shell function `", nm, "'"); > @@ -1330,7 +1329,7 @@ > makezleparams(0); > sfcontext = SFC_WIDGET; > opts[XTRACE] = 0; > - ret = doshfunc(w->u.fnnam, prog, largs, shf->node.flags, 1); > + ret = doshfunc(shf, largs, shf->node.flags, 1); > opts[XTRACE] = oxt; > sfcontext = osc; > endparamscope(); > Index: Src/Zle/zle_misc.c > =================================================================== > RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v > retrieving revision 1.54 > diff -u -r1.54 zle_misc.c > --- Src/Zle/zle_misc.c 4 May 2008 18:30:04 -0000 1.54 > +++ Src/Zle/zle_misc.c 16 Sep 2008 14:41:12 -0000 > @@ -1358,9 +1358,9 @@ > iremovesuffix(ZLE_INT_T c, int keep) > { > if (suffixfunc) { > - Eprog prog = getshfunc(suffixfunc); > + Shfunc shfunc = getshfunc(suffixfunc); > > - if (prog != &dummy_eprog) { > + if (shfunc) { > LinkList args = newlinklist(); > char buf[20]; > int osc = sfcontext; > @@ -1384,7 +1384,7 @@ > startparamscope(); > makezleparams(0); > sfcontext = SFC_COMPLETE; > - doshfunc(suffixfunc, prog, args, 0, 1); > + doshfunc(shfunc, args, 0, 1); > sfcontext = osc; > endparamscope(); > > Index: Test/E02xtrace.ztst > =================================================================== > RCS file: /cvsroot/zsh/zsh/Test/E02xtrace.ztst,v > retrieving revision 1.7 > diff -u -r1.7 E02xtrace.ztst > --- Test/E02xtrace.ztst 11 Aug 2008 08:40:58 -0000 1.7 > +++ Test/E02xtrace.ztst 16 Sep 2008 14:41:12 -0000 > @@ -90,3 +90,18 @@ > >Tracing: function > ?+xtf:1> local regression_test_dummy_variable > ?+xtf:2> print 'Tracing: function' > + > + echo 'PS4="+%x:%I> " > + fn() { > + print This is fn. > + } > + : > + fn > + ' >fnfile > + $ZTST_testdir/../Src/zsh -fx ./fnfile > +0:Trace output with sourcefile and line number. > +>This is fn. > +?+./fnfile:1> PS4='+%x:%I> ' > +?+./fnfile:5> : > +?+./fnfile:6> fn > +?+./fnfile:3> print This is fn. > > > -- > Peter Stephenson Software Engineer > CSR PLC, Churchill House, Cambridge Business Park, Cowley Road > Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070 > ------=_Part_5861_15142014.1221669576362 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline


On Tue, Sep 16, 2008 at 10:50 AM, Peter Stephenson <pws@csr.com> wrote:
Now we have logic for finding the source file and corresponding line
number of executed code, this adds the prompt escapes %x and %I which
are like %N and %i but for the file where the code was defined.  

Looks like this has problems when used inside trap DEBUG. Consider this test program:

PS4='%x:%I: '
hook() {
    set -x
    bug a 5 1
}
bug() {
  typeset source_file="$1"
  typeset -ir lineno=$2
  typeset -ir is_temp=$3
}
trap hook DEBUG

a=1
b=2

Here is the output I get:

zsh ./linebug.sh
./linebug.sh:15: bug a 5 1
./linebug.sh:19: typeset 'source_file=a'
./linebug.sh:19: typeset -ir 'lineno=5'
./linebug.sh:19: typeset -ir 'is_temp=1'
./linebug.sh:16: bug a 5 1
./linebug.sh:20: typeset 'source_file=a'
./linebug.sh:20: typeset -ir 'lineno=5'
./linebug.sh:20: typeset -ir 'is_temp=1'

Not sure where 19 and 20 are coming from since the program only has 16 lines. And also curious is why they don't change when commands get run.


 
%x isn't
ideal but upper and lower case %s, %f and %n are all used.  It stands
for "execution file", or something.  The idea is that you set
PS4='+%x:%I>'

While doing this, I spotted that we could improve the information
available to funcstack and the interface to doshfunc() by passing in a
Shfunc instead of an Eprog.  This is a *much* cleaner interface.  Now
the funcstack entry is guaranteed to get the details of the shell
function correct.

Index: Doc/Zsh/prompt.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/prompt.yo,v
retrieving revision 1.15
diff -u -r1.15 prompt.yo
--- Doc/Zsh/prompt.yo   24 Jun 2008 08:44:16 -0000      1.15
+++ Doc/Zsh/prompt.yo   16 Sep 2008 14:41:10 -0000
@@ -113,6 +113,11 @@
 shell function given by tt(%N).  This is most useful for debugging as part
 of tt($PS4).
 )
+item(tt(%I))(
+The line number currently being executed in the file tt(%x).  This is
+similar to tt(%i), but the line number is always a line number in the
+file where the code was defined, even if the code is a shell function.
+)
 item(tt(%j))(
 The number of jobs.
 )
@@ -126,6 +131,11 @@
 the `tt(%)' to specify a number of trailing path components to show; zero
 means the full path.  A negative integer specifies leading components.
 )
+item(tt(%x))(
+The name of the file containing the source code currently being
+executed.  This behaves as tt(%N) except that function and eval command
+names are not shown, instead the file where they were defined.
+)
 xitem(tt(%c))
 xitem(tt(%.))
 item(tt(%C))(
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.151
diff -u -r1.151 exec.c
--- Src/exec.c  11 Sep 2008 17:14:39 -0000      1.151
+++ Src/exec.c  16 Sep 2008 14:41:10 -0000
@@ -518,7 +518,7 @@
       return 127;

    pushnode(args, arg0);
-    return doshfunc(shf->node.nam, shf->funcdef, args, shf->node.flags, 1);
+    return doshfunc(shf, args, shf->node.flags, 1);
 }

 /* execute an external command */
@@ -4064,7 +4064,7 @@
    cmdsp = 0;
    if ((osfc = sfcontext) == SFC_NONE)
       sfcontext = SFC_DIRECT;
-    doshfunc(shf->node.nam, shf->funcdef, args, shf->node.flags, 0);
+    doshfunc(shf, args, shf->node.flags, 0);
    sfcontext = osfc;
    free(cmdstack);
    cmdstack = ocs;
@@ -4200,18 +4200,20 @@

 /**/
 mod_export int
-doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
+doshfunc(Shfunc shfunc, LinkList doshargs, int flags, int noreturnval)
 {
    char **tab, **x, *oargv0;
    int oldzoptind, oldlastval, oldoptcind, oldnumpipestats, ret;
    int *oldpipestats = NULL;
-    char saveopts[OPT_SIZE], *oldscriptname = scriptname, *fname = dupstring(name);
+    char saveopts[OPT_SIZE], *oldscriptname = scriptname;
+    char *name = shfunc->node.nam;
+    char *fname = dupstring(name);
    int obreaks, saveemulation ;
+    Eprog prog;
    struct funcstack fstack;
 #ifdef MAX_FUNCTION_DEPTH
    static int funcdepth;
 #endif
-    Shfunc shf;

    pushheap();

@@ -4291,14 +4293,10 @@
    fstack.tp = FS_FUNC;
    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);
-    }
+    fstack.flineno = shfunc->lineno;
+    fstack.filename = dupstring(shfunc->filename);

+    prog = shfunc->funcdef;
    if (prog->flags & EF_RUN) {
       Shfunc shf;

Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.96
diff -u -r1.96 init.c
--- Src/init.c  11 Sep 2008 17:14:39 -0000      1.96
+++ Src/init.c  16 Sep 2008 14:41:10 -0000
@@ -149,7 +149,7 @@
           int toksav = tok;

           if (toplevel &&
-               (getshfunc("preexec") != &dummy_eprog ||
+               (getshfunc("preexec") ||
                paramtab->getnode(paramtab, "preexec_functions"))) {
               LinkList args;
               char *cmdstr;
Index: Src/math.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/math.c,v
retrieving revision 1.33
diff -u -r1.33 math.c
--- Src/math.c  12 Jun 2008 13:45:06 -0000      1.33
+++ Src/math.c  16 Sep 2008 14:41:10 -0000
@@ -868,11 +868,11 @@
                                          argc <= f->maxargs)) {
                   if (f->flags & MFF_USERFUNC) {
                       char *shfnam = f->module ? f->module : n;
-                       Eprog prog = getshfunc(shfnam);
-                       if (prog == &dummy_eprog)
+                       Shfunc shfunc = getshfunc(shfnam);
+                       if (!shfunc)
                           zerr("no such function: %s", shfnam);
                       else {
-                           doshfunc(n, prog, l, 0, 1);
+                           doshfunc(shfunc, l, 0, 1);
                           return lastmathval;
                       }
                   } else {
Index: Src/prompt.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/prompt.c,v
retrieving revision 1.53
diff -u -r1.53 prompt.c
--- Src/prompt.c        15 Sep 2008 16:18:06 -0000      1.53
+++ Src/prompt.c        16 Sep 2008 14:41:11 -0000
@@ -725,11 +725,37 @@
               if(Rstring)
                   stradd(Rstring);
               break;
+           case 'I':
+               if (funcstack && funcstack->tp != FS_SOURCE) {
+                   /*
+                    * We're in a function or an eval with
+                    * EVALLINENO.  Calculate the line number in
+                    * the file.
+                    */
+                   zlong flineno = lineno + funcstack->flineno;
+                   /* take account of eval line nos. starting at 1 */
+                   if (funcstack->tp == FS_EVAL)
+                       lineno--;
+                   addbufspc(DIGBUFSIZE);
+                   sprintf(bp, "%ld", (long)flineno);
+                   bp += strlen(bp);
+                   break;
+               }
+               /* else we're in a file and lineno is already correct */
+               /* FALLTHROUGH */
           case 'i':
               addbufspc(DIGBUFSIZE);
               sprintf(bp, "%ld", (long)lineno);
               bp += strlen(bp);
               break;
+           case 'x':
+               if (funcstack && funcstack->tp != FS_SOURCE)
+                   promptpath(funcstack->filename ? funcstack->filename : "",
+                              arg, 0);
+               else
+                   promptpath(scriptfilename ? scriptfilename : argzero,
+                              arg, 0);
+               break;
           case '\0':
               return 0;
           case Meta:
Index: Src/signals.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/signals.c,v
retrieving revision 1.50
diff -u -r1.50 signals.c
--- Src/signals.c       11 Aug 2008 19:22:54 -0000      1.50
+++ Src/signals.c       16 Sep 2008 14:41:11 -0000
@@ -963,8 +963,7 @@
    }

    if (exittr) {
-       dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ?
-                  ((Shfunc)exitfn)->funcdef : (Eprog) exitfn);
+       dotrapargs(SIGEXIT, &exittr, exitfn);
       if (exittr & ZSIG_FUNC)
           shfunctab->freenode((HashNode)exitfn);
       else
@@ -1077,8 +1076,16 @@
 /**/
 int trapisfunc;

+/*
+ * sig is the signal number.
+ * *sigtr is the value to be taken as the field in sigtrapped (since
+ *   that may have changed by this point if we are exiting).
+ * sigfn is an Eprog with a non-function eval list, or a Shfunc
+ *   with a function trap.  It may be NULL with an ignored signal.
+ */
+
 /**/
-void
+static void
 dotrapargs(int sig, int *sigtr, void *sigfn)
 {
    LinkList args;
@@ -1153,7 +1160,7 @@
       trapisfunc = isfunc = 1;

       sfcontext = SFC_SIGNAL;
-       doshfunc(name, sigfn, args, 0, 1);
+       doshfunc((Shfunc)sigfn, args, 0, 1);
       sfcontext = osc;
       freelinklist(args, (FreeFunc) NULL);
       zsfree(name);
@@ -1162,7 +1169,7 @@
       trap_state = TRAP_STATE_PRIMED;
       trapisfunc = isfunc = 0;

-       execode(sigfn, 1, 0);
+       execode((Eprog)sigfn, 1, 0);
    }
    runhookdef(AFTERTRAPHOOK, NULL);

@@ -1215,12 +1222,12 @@
 void
 dotrap(int sig)
 {
-    Eprog funcprog;
+    void *funcprog;

    if (sigtrapped[sig] & ZSIG_FUNC) {
       HashNode hn = gettrapnode(sig, 0);
       if (hn)
-           funcprog = ((Shfunc)hn)->funcdef;
+           funcprog = hn;
       else {
 #ifdef DEBUG
           dputs("BUG: running function trap which has escaped.");
@@ -1230,7 +1237,11 @@
    } else
       funcprog = siglists[sig];

-    /* Copied from dotrapargs(). */
+    /*
+     * Copied from dotrapargs().
+     * (In fact, the gain from duplicating this appears to be virtually
+     * zero.  Not sure why it's here.)
+     */
    if ((sigtrapped[sig] & ZSIG_IGNORED) || !funcprog || errflag)
       return;

Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.199
diff -u -r1.199 utils.c
--- Src/utils.c 11 Aug 2008 19:22:54 -0000      1.199
+++ Src/utils.c 16 Sep 2008 14:41:11 -0000
@@ -35,6 +35,8 @@
 /**/
 mod_export char *scriptname;     /* is sometimes a function name */

+/* filename of script or other file containing code source e.g. autoload */
+
 /**/
 mod_export char *scriptfilename;

@@ -1134,7 +1136,7 @@
 mod_export int
 callhookfunc(char *name, LinkList lnklst, int arrayp, int *retval)
 {
-    Eprog prog;
+    Shfunc shfunc;
       /*
        * Save stopmsg, since user doesn't get a chance to respond
        * to a list of jobs generated in a hook.
@@ -1143,8 +1145,8 @@

    sfcontext = SFC_HOOK;

-    if ((prog = getshfunc(name)) != &dummy_eprog) {
-       ret = doshfunc(name, prog, lnklst, 0, 1);
+    if ((shfunc = getshfunc(name))) {
+       ret = doshfunc(shfunc, lnklst, 0, 1);
       stat = 0;
    }

@@ -1159,8 +1161,8 @@

       if ((arrptr = getaparam(arrnam))) {
           for (; *arrptr; arrptr++) {
-               if ((prog = getshfunc(*arrptr)) != &dummy_eprog) {
-                   int newret = doshfunc(arrnam, prog, lnklst, 0, 1);
+               if ((shfunc = getshfunc(*arrptr))) {
+                   int newret = doshfunc(shfunc, lnklst, 0, 1);
                   if (!ret)
                       ret = newret;
                   stat = 0;
@@ -2893,15 +2895,10 @@
 /* Get the definition of a shell function */

 /**/
-mod_export Eprog
+mod_export Shfunc
 getshfunc(char *nam)
 {
-    Shfunc shf;
-
-    if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, nam)))
-       return &dummy_eprog;
-
-    return shf->funcdef;
+    return (Shfunc) shfunctab->getnode(shfunctab, nam);
 }

 /**/
Index: Src/Modules/zftp.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/zftp.c,v
retrieving revision 1.48
diff -u -r1.48 zftp.c
--- Src/Modules/zftp.c  4 Sep 2008 22:23:52 -0000       1.48
+++ Src/Modules/zftp.c  16 Sep 2008 14:41:11 -0000
@@ -1469,9 +1469,9 @@
    char lsbuf[ZF_BUFSIZE], *ascbuf = NULL, *optr;
    off_t sofar = 0, last_sofar = 0;
    readwrite_t read_ptr = zfread, write_ptr = zfwrite;
-    Eprog prog;
+    Shfunc shfunc;

-    if (progress && (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
+    if (progress && (shfunc = getshfunc("zftp_progress"))) {
       /*
        * progress to set up:  ZFTP_COUNT is zero.
        * We do this here in case we needed to wait for a RETR
@@ -1480,7 +1480,7 @@
       int osc = sfcontext;

       sfcontext = SFC_HOOK;
-       doshfunc("zftp_progress", prog, NULL, 0, 1);
+       doshfunc(shfunc, NULL, 0, 1);
       sfcontext = osc;
       /* Now add in the bit of the file we've got/sent already */
       sofar = last_sofar = startat;
@@ -1608,12 +1608,12 @@
       } else
           break;
       if (!ret && sofar != last_sofar && progress &&
-           (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
+           (shfunc = getshfunc("zftp_progress"))) {
           int osc = sfcontext;

           zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
           sfcontext = SFC_HOOK;
-           doshfunc("zftp_progress", prog, NULL, 0, 1);
+           doshfunc(shfunc, NULL, 0, 1);
           sfcontext = osc;
           last_sofar = sofar;
       }
@@ -2364,7 +2364,7 @@
 {
    char *ptr, *eptr;
    int endc;
-    Eprog prog;
+    Shfunc shfunc;

    if (zfprefs & ZFPF_DUMB)
       return 1;
@@ -2391,11 +2391,11 @@
     * front end.  By putting it here, and in close when ZFTP_PWD is unset,
     * we at least cover the bases.
     */
-    if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) {
+    if ((shfunc = getshfunc("zftp_chpwd"))) {
       int osc = sfcontext;

       sfcontext = SFC_HOOK;
-       doshfunc("zftp_chpwd", prog, NULL, 0, 1);
+       doshfunc(shfunc, NULL, 0, 1);
       sfcontext = osc;
    }
    return 0;
@@ -2549,7 +2549,7 @@
 {
    int ret = 0, recv = (flags & ZFTP_RECV), getsize = 0, progress = 1;
    char *cmd = recv ? "RETR " : (flags & ZFTP_APPE) ? "APPE " : "STOR ";
-    Eprog prog;
+    Shfunc shfunc;

    /*
     * At this point I'd like to set progress to 0 if we're
@@ -2567,7 +2567,7 @@
    for (; *args; args++) {
       char *ln, *rest = NULL;
       off_t startat = 0;
-       if (progress && (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
+       if (progress && (shfunc = getshfunc("zftp_progress"))) {
           off_t sz = -1;
           /*
            * This calls the SIZE command to get the size for remote
@@ -2608,14 +2608,14 @@
        * if and only if we called zfsenddata();
        */
       if (progress && ret != 2 &&
-           (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
+           (shfunc = getshfunc("zftp_progress"))) {
           /* progress to finish: ZFTP_TRANSFER set to GF or PF */
           int osc = sfcontext;

           zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
                      ZFPM_READONLY);
           sfcontext = SFC_HOOK;
-           doshfunc("zftp_progress", prog, NULL, 0, 1);
+           doshfunc(shfunc, NULL, 0, 1);
           sfcontext = osc;
       }
       if (rest) {
@@ -2715,7 +2715,7 @@
 zfclose(int leaveparams)
 {
    char **aptr;
-    Eprog prog;
+    Shfunc shfunc;

    if (!zfsess->control)
       return;
@@ -2766,11 +2766,11 @@
           zfunsetparam(*aptr);

       /* Now ZFTP_PWD is unset.  It's up to zftp_chpwd to notice. */
-       if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) {
+       if ((shfunc = getshfunc("zftp_chpwd"))) {
           int osc = sfcontext;

           sfcontext = SFC_HOOK;
-           doshfunc("zftp_chpwd", prog, NULL, 0, 1);
+           doshfunc(shfunc, NULL, 0, 1);
           sfcontext = osc;
       }
    }
Index: Src/Zle/compcore.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compcore.c,v
retrieving revision 1.96
diff -u -r1.96 compcore.c
--- Src/Zle/compcore.c  7 Jul 2008 08:33:28 -0000       1.96
+++ Src/Zle/compcore.c  16 Sep 2008 14:41:12 -0000
@@ -540,13 +540,13 @@
 static void
 callcompfunc(char *s, char *fn)
 {
-    Eprog prog;
+    Shfunc shfunc;
    int lv = lastval;
    char buf[20];

    METACHECK();

-    if ((prog = getshfunc(fn)) != &dummy_eprog) {
+    if ((shfunc = getshfunc(fn))) {
       char **p, *tmp;
       int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext;
       unsigned int rset, kset;
@@ -814,7 +814,7 @@
               while (*p)
                   addlinknode(largs, dupstring(*p++));
           }
-           doshfunc(fn, prog, largs, 0, 0);
+           doshfunc(shfunc, largs, 0, 0);
           cfret = lastval;
           lastval = olv;
       } OLDHEAPS;
Index: Src/Zle/compctl.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compctl.c,v
retrieving revision 1.35
diff -u -r1.35 compctl.c
--- Src/Zle/compctl.c   3 Oct 2007 16:18:38 -0000       1.35
+++ Src/Zle/compctl.c   16 Sep 2008 14:41:12 -0000
@@ -3635,12 +3635,12 @@
    }
    if (cc->func) {
       /* This handles the compctl -K flag. */
-       Eprog prog;
+       Shfunc shfunc;
       char **r;
       int lv = lastval;

       /* Get the function. */
-       if ((prog = getshfunc(cc->func)) != &dummy_eprog) {
+       if ((shfunc = getshfunc(cc->func))) {
           /* We have it, so build a argument list. */
           LinkList args = newlinklist();
           int osc = sfcontext;
@@ -3664,7 +3664,7 @@
               incompctlfunc = 1;
           sfcontext = SFC_COMPLETE;
           /* Call the function. */
-           doshfunc(cc->func, prog, args, 0, 1);
+           doshfunc(shfunc, args, 0, 1);
           sfcontext = osc;
           incompctlfunc = 0;
           /* And get the result from the reply parameter. */
@@ -3809,12 +3809,12 @@
       /* generate the user-defined display list: if anything fails, *
        * we silently allow the normal completion list to be used.   */
       char **yaptr = NULL, *uv = NULL;
-       Eprog prog;
+       Shfunc shfunc;

       if (cc->ylist[0] == '$' || cc->ylist[0] == '(') {
           /* from variable */
           uv = cc->ylist + (cc->ylist[0] == '$');
-       } else if ((prog = getshfunc(cc->ylist)) != &dummy_eprog) {
+       } else if ((shfunc = getshfunc(cc->ylist))) {
           /* from function:  pass completions as arg list */
           LinkList args = newlinklist();
           LinkNode ln;
@@ -3839,7 +3839,7 @@
           if (incompfunc != 1)
               incompctlfunc = 1;
           sfcontext = SFC_COMPLETE;
-           doshfunc(cc->ylist, prog, args, 0, 1);
+           doshfunc(shfunc, args, 0, 1);
           sfcontext = osc;
           incompctlfunc = 0;
           uv = "reply";
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.115
diff -u -r1.115 zle_main.c
--- Src/Zle/zle_main.c  8 Sep 2008 06:24:23 -0000       1.115
+++ Src/Zle/zle_main.c  16 Sep 2008 14:41:12 -0000
@@ -1304,9 +1304,8 @@
       r = 1;
    } else {
       Shfunc shf = (Shfunc) shfunctab->getnode(shfunctab, w->u.fnnam);
-       Eprog prog = (shf ? shf->funcdef : &dummy_eprog);

-       if(prog == &dummy_eprog) {
+       if (!shf) {
           /* the shell function doesn't exist */
           char *nm = nicedup(w->u.fnnam, 0);
           char *msg = tricat("No such shell function `", nm, "'");
@@ -1330,7 +1329,7 @@
           makezleparams(0);
           sfcontext = SFC_WIDGET;
           opts[XTRACE] = 0;
-           ret = doshfunc(w->u.fnnam, prog, largs, shf->node.flags, 1);
+           ret = doshfunc(shf, largs, shf->node.flags, 1);
           opts[XTRACE] = oxt;
           sfcontext = osc;
           endparamscope();
Index: Src/Zle/zle_misc.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v
retrieving revision 1.54
diff -u -r1.54 zle_misc.c
--- Src/Zle/zle_misc.c  4 May 2008 18:30:04 -0000       1.54
+++ Src/Zle/zle_misc.c  16 Sep 2008 14:41:12 -0000
@@ -1358,9 +1358,9 @@
 iremovesuffix(ZLE_INT_T c, int keep)
 {
    if (suffixfunc) {
-       Eprog prog = getshfunc(suffixfunc);
+       Shfunc shfunc = getshfunc(suffixfunc);

-       if (prog != &dummy_eprog) {
+       if (shfunc) {
           LinkList args = newlinklist();
           char buf[20];
           int osc = sfcontext;
@@ -1384,7 +1384,7 @@
           startparamscope();
           makezleparams(0);
           sfcontext = SFC_COMPLETE;
-           doshfunc(suffixfunc, prog, args, 0, 1);
+           doshfunc(shfunc, args, 0, 1);
           sfcontext = osc;
           endparamscope();

Index: Test/E02xtrace.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/E02xtrace.ztst,v
retrieving revision 1.7
diff -u -r1.7 E02xtrace.ztst
--- Test/E02xtrace.ztst 11 Aug 2008 08:40:58 -0000      1.7
+++ Test/E02xtrace.ztst 16 Sep 2008 14:41:12 -0000
@@ -90,3 +90,18 @@
 >Tracing: function
 ?+xtf:1> local regression_test_dummy_variable
 ?+xtf:2> print 'Tracing: function'
+
+ echo 'PS4="+%x:%I> "
+ fn() {
+   print This is fn.
+ }
+ :
+ fn
+ ' >fnfile
+ $ZTST_testdir/../Src/zsh -fx ./fnfile
+0:Trace output with sourcefile and line number.
+>This is fn.
+?+./fnfile:1> PS4='+%x:%I> '
+?+./fnfile:5> :
+?+./fnfile:6> fn
+?+./fnfile:3> print This is fn.


--
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

------=_Part_5861_15142014.1221669576362--