zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: redirection and xtrace output
@ 2000-02-19 19:19 Bart Schaefer
  2000-02-20  1:18 ` PATCH: " Bart Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Bart Schaefer @ 2000-02-19 19:19 UTC (permalink / raw)
  To: zsh-workers

This patch introduces a global FILE *xtrerr which is used for (hopefully)
all xtrace output.  Normally it just points to stderr, but during execcmd()
it's fdopened on a dup of fileno(stderr) before redirections are performed,
then restored before returning.

There's probably some test that I haven't figured out yet that would permit
changing xtrerr only if fd 2 is actually being redirected.  Or maybe there
isn't any reason to reclaim the file descriptor, and we should just open
xtrerr once in init_io() and leave it open forever?

There is still one problem with this:  The xtrace output of ( ... ) and
{ ... } constructs is NOT redirected with stderr, which it should be. I
suspect that's a matter of restoring xtrerr = stderr in entersubsh(), but
I wasn't sure exactly where.

Index: Src/builtin.c
===================================================================
@@ -351,13 +351,13 @@
     /* display execution trace information, if required */
     if (xtr) {
 	printprompt4();
-	fprintf(stderr, "%s", name);
+	fprintf(xtrerr, "%s", name);
 	if (xarg)
-	    fprintf(stderr, " %s", xarg);
+	    fprintf(xtrerr, " %s", xarg);
 	while (*oargv)
-	    fprintf(stderr, " %s", *oargv++);
-	fputc('\n', stderr);
-	fflush(stderr);
+	    fprintf(xtrerr, " %s", *oargv++);
+	fputc('\n', xtrerr);
+	fflush(xtrerr);
     }
     /* call the handler function, and return its return value */
     return (*(bn->handlerfunc)) (name, argv, ops, bn->funcid);
Index: Src/cond.c
===================================================================
@@ -50,12 +50,12 @@
     switch (ctype) {
     case COND_NOT:
 	if (tracingcond)
-	    fprintf(stderr, " %s", condstr[ctype]);
+	    fprintf(xtrerr, " %s", condstr[ctype]);
 	return !evalcond(state);
     case COND_AND:
 	if (evalcond(state)) {
 	    if (tracingcond)
-		fprintf(stderr, " %s", condstr[ctype]);
+		fprintf(xtrerr, " %s", condstr[ctype]);
 	    return evalcond(state);
 	} else {
 	    state->pc = pcode + (WC_COND_SKIP(code) + 1);
@@ -64,7 +64,7 @@
     case COND_OR:
 	if (!evalcond(state)) {
 	    if (tracingcond)
-		fprintf(stderr, " %s", condstr[ctype]);
+		fprintf(xtrerr, " %s", condstr[ctype]);
 	    return evalcond(state);
 	} else {
 	    state->pc = pcode + (WC_COND_SKIP(code) + 1);
@@ -136,9 +136,9 @@
 		singsub(&rt);
 		untokenize(rt);
 	    }
-	    fprintf(stderr, " %s %s %s", left, condstr[ctype], rt);
+	    fprintf(xtrerr, " %s %s %s", left, condstr[ctype], rt);
 	} else
-	    fprintf(stderr, " -%c %s", ctype, left);
+	    fprintf(xtrerr, " -%c %s", ctype, left);
     }
 
     if (ctype >= COND_EQ && ctype <= COND_GE) {
@@ -410,10 +410,10 @@
     for (aptr = args; *aptr; aptr++)
 	untokenize(*aptr);
     if (inf) {
-	fprintf(stderr, " %s %s %s", args[0], name, args[1]);
+	fprintf(xtrerr, " %s %s %s", args[0], name, args[1]);
     } else {
-	fprintf(stderr, " %s", name);
+	fprintf(xtrerr, " %s", name);
 	while (*args)
-	    fprintf(stderr, " %s", *args++);
+	    fprintf(xtrerr, " %s", *args++);
     }
 }
Index: Src/exec.c
===================================================================
@@ -1195,12 +1195,12 @@
 
 	for (node = firstnode(list); node; incnode(node)) {
 	    *ptr++ = (char *)getdata(node);
-	    zputs(getdata(node), stderr);
+	    zputs(getdata(node), xtrerr);
 	    if (nextnode(node))
-		fputc(' ', stderr);
+		fputc(' ', xtrerr);
 	}
-	fputc('\n', stderr);
-	fflush(stderr);
+	fputc('\n', xtrerr);
+	fflush(xtrerr);
     } else {
 	for (node = firstnode(list); node; incnode(node))
 	    *ptr++ = (char *)getdata(node);
@@ -1404,7 +1404,7 @@
 	name = ecgetstr(state, 1);
 	untokenize(name);
 	if (xtr)
-	    fprintf(stderr, "%s=", name);
+	    fprintf(xtrerr, "%s=", name);
 	if ((isstr = (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR))) {
 	    vl = newlinklist();
 	    addlinknode(vl, ecgetstr(state, 1));
@@ -1437,7 +1437,7 @@
 		val = ztrdup(ugetnode(vl));
 	    }
 	    if (xtr)
-		fprintf(stderr, "%s ", val);
+		fprintf(xtrerr, "%s ", val);
 	    if (export && !strchr(name, '[')) {
 		if (export < 0 && isset(RESTRICTED) &&
 		    (pm = (Param) paramtab->removenode(paramtab, name)) &&
@@ -1470,10 +1470,10 @@
 
 	*ptr = NULL;
 	if (xtr) {
-	    fprintf(stderr, "( ");
+	    fprintf(xtrerr, "( ");
 	    for (ptr = arr; *ptr; ptr++)
-		fprintf(stderr, "%s ", *ptr);
-	    fprintf(stderr, ") ");
+		fprintf(xtrerr, "%s ", *ptr);
+	    fprintf(xtrerr, ") ");
 	}
 	setaparam(name, arr);
 	if (errflag) {
@@ -1698,8 +1698,8 @@
 		    else
 			lastval = cmdoutval;
 		    if (isset(XTRACE)) {
-			fputc('\n', stderr);
-			fflush(stderr);
+			fputc('\n', xtrerr);
+			fflush(xtrerr);
 		    }
 		    return;
 		}
@@ -1935,6 +1935,12 @@
 	goto err;
     }
 
+    /* Make a copy of stderr for xtrace output before redirecting */
+    fflush(xtrerr);
+    if (xtrerr == stderr &&
+	!(xtrerr = fdopen(movefd(dup(fileno(stderr))), "w")))
+	xtrerr = stderr;
+
     /* Add pipeline input/output to mnodes */
     if (input)
 	addfd(forked, save, mfds, 0, input, 0);
@@ -2088,7 +2094,7 @@
 	    for (i = 0; i < 10; i++)
 		if (save[i] != -2)
 		    zclose(save[i]);
-	    return;
+	    goto done;
 	}
 	/*
 	 * If nullexec is 2, we have variables to add with the redirections
@@ -2098,8 +2104,8 @@
 	    addvars(state, varspc, 0);
 	lastval = errflag ? errflag : cmdoutval;
 	if (isset(XTRACE)) {
-	    fputc('\n', stderr);
-	    fflush(stderr);
+	    fputc('\n', xtrerr);
+	    fflush(xtrerr);
 	}
     } else if (isset(EXECOPT) && !errflag) {
 	/*
@@ -2138,7 +2144,7 @@
 		    restore_params(restorelist, removelist);
 		    lastval = 1;
 		    fixfds(save);
-		    return;
+		    goto done;
 		}
 	    }
 
@@ -2239,6 +2245,14 @@
     if (forked)
 	_exit(lastval);
     fixfds(save);
+
+ done:
+    if (xtrerr != stderr) {
+	fil = fileno(xtrerr);
+	fclose(xtrerr);
+	zclose(fil);
+	xtrerr = stderr;
+    }
 }
 
 /* Arrange to have variables restored. */
@@ -2870,13 +2884,13 @@
     state->pc--;
     if (isset(XTRACE)) {
 	printprompt4();
-	fprintf(stderr, "[[");
+	fprintf(xtrerr, "[[");
 	tracingcond++;
     }
     stat = !evalcond(state);
     if (isset(XTRACE)) {
-	fprintf(stderr, " ]]\n");
-	fflush(stderr);
+	fprintf(xtrerr, " ]]\n");
+	fflush(xtrerr);
 	tracingcond--;
     }
     return stat;
@@ -2893,18 +2907,18 @@
 
     if (isset(XTRACE)) {
 	printprompt4();
-	fprintf(stderr, "((");
+	fprintf(xtrerr, "((");
     }
     e = ecgetstr(state, 1);
     singsub(&e);
     if (isset(XTRACE))
-	fprintf(stderr, " %s", e);
+	fprintf(xtrerr, " %s", e);
 
     val = mathevali(e);
 
     if (isset(XTRACE)) {
-	fprintf(stderr, " ))\n");
-	fflush(stderr);
+	fprintf(xtrerr, " ))\n");
+	fflush(xtrerr);
     }
     errflag = 0;
     return !val;
@@ -3017,11 +3031,11 @@
 	if (args)
 	    for (lptr = firstnode(args); lptr; incnode(lptr)) {
 		if (lptr != firstnode(args))
-		    fputc(' ', stderr);
-		fprintf(stderr, "%s", (char *)getdata(lptr));
+		    fputc(' ', xtrerr);
+		fprintf(xtrerr, "%s", (char *)getdata(lptr));
 	    }
-	fputc('\n', stderr);
-	fflush(stderr);
+	fputc('\n', xtrerr);
+	fflush(xtrerr);
     }
     ocs = cmdstack;
     ocsp = cmdsp;
Index: Src/init.c
===================================================================
@@ -331,6 +331,9 @@
 	SHTTY = -1;
     }
 
+    /* Send xtrace output to stderr -- see execcmd() */
+    xtrerr = stderr;
+
     /* Make sure the tty is opened read/write. */
     if (isatty(0)) {
 	zsfree(ttystrname);
Index: Src/loop.c
===================================================================
RCS file: /extra/cvsroot/zsh/zsh-3.1/Src/loop.c,v
retrieving revision 1.21
diff -u -r1.21 loop.c
--- loop.c	2000/02/06 18:42:31	1.21
+++ loop.c	2000/02/19 18:53:58
@@ -66,8 +66,8 @@
 	    char *str2 = dupstring(str);
 	    untokenize(str2);
 	    printprompt4();
-	    fprintf(stderr, "%s\n", str2);
-	    fflush(stderr);
+	    fprintf(xtrerr, "%s\n", str2);
+	    fflush(xtrerr);
 	}
 	if (!errflag)
 	    matheval(str);
@@ -105,8 +105,8 @@
 		if (*str) {
 		    if (isset(XTRACE)) {
 			printprompt4();
-			fprintf(stderr, "%s\n", str);
-			fflush(stderr);
+			fprintf(xtrerr, "%s\n", str);
+			fflush(xtrerr);
 		    }
 		    val = mathevali(str);
 		} else
@@ -125,8 +125,8 @@
 		break;
 	    if (isset(XTRACE)) {
 		printprompt4();
-		fprintf(stderr, "%s=%s\n", name, str);
-		fflush(stderr);
+		fprintf(xtrerr, "%s=%s\n", name, str);
+		fflush(xtrerr);
 	    }
 	    setsparam(name, ztrdup(str));
 	}
@@ -144,8 +144,8 @@
 	    str = dupstring(advance);
 	    if (isset(XTRACE)) {
 		printprompt4();
-		fprintf(stderr, "%s\n", str);
-		fflush(stderr);
+		fprintf(xtrerr, "%s\n", str);
+		fflush(xtrerr);
 	    }
 	    singsub(&str);
 	    if (!errflag)
@@ -517,8 +517,8 @@
 	    pat2 = dupstring(pat);
 	    untokenize(pat2);
 	    printprompt4();
-	    fprintf(stderr, "case %s (%s)\n", word, pat2);
-	    fflush(stderr);
+	    fprintf(xtrerr, "case %s (%s)\n", word, pat2);
+	    fflush(xtrerr);
 	    state->pc++;
 	} else
 	    state->pc += 2;
Index: Src/utils.c
===================================================================
@@ -791,9 +791,14 @@
 /* This prints the XTRACE prompt. */
 
 /**/
+FILE *xtrerr = 0;
+
+/**/
 void
 printprompt4(void)
 {
+    if (!xtrerr)
+	xtrerr = stderr;
     if (prompt4) {
 	int l;
 	char *s = dupstring(prompt4);
@@ -801,7 +806,7 @@
 	unmetafy(s, &l);
 	s = unmetafy(promptexpand(metafy(s, l, META_NOALLOC), 0, NULL, NULL), &l);
 
-	fprintf(stderr, "%s", s);
+	fprintf(xtrerr, "%s", s);
     }
 }
 

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 2+ messages in thread

* PATCH: Re: redirection and xtrace output
  2000-02-19 19:19 PATCH: redirection and xtrace output Bart Schaefer
@ 2000-02-20  1:18 ` Bart Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2000-02-20  1:18 UTC (permalink / raw)
  To: zsh-workers

On Feb 19,  7:19pm, Bart Schaefer wrote:
} Subject: PATCH: redirection and xtrace output
}
} This patch introduces a global FILE *xtrerr which is used for (hopefully)
} all xtrace output.
} 
} There is still one problem with this:  The xtrace output of ( ... ) and
} { ... } constructs is NOT redirected with stderr, which it should be.

There was actually one other problem:  When tracing an external command,
the call to closem() was killing fileno(xtrerr) before it was flushed,
so some trace output didn't appear.

The following fixes all these problems, and also catches cases I missed
where execcmd() could return without closing/restoring xtrerr.  It took
me a ridiculously long time to figure out the right test to use for the
( ... ) and { ... } cases, but it turned out to be quite simple.  In the
process I created a test script; I arbitrarily numbered it after the cd
test, becaue it didn't seem to be in the same category as the others.

Index: Src/exec.c
===================================================================
@@ -129,7 +129,7 @@
 /**/
 mod_export Funcstack funcstack;
 
-#define execerr() if (!forked) { lastval = 1; return; } else _exit(1)
+#define execerr() if (!forked) { lastval = 1; goto done; } else _exit(1)
 
 static LinkList args;
 static int doneps4;
@@ -473,6 +473,7 @@
     }
 
     argv = makecline(args);
+    closem(3);
     child_unblock();
     if ((int) strlen(arg0) >= PATH_MAX) {
 	zerr("command too long: %s", arg0, 0);
@@ -1937,9 +1938,12 @@
 
     /* Make a copy of stderr for xtrace output before redirecting */
     fflush(xtrerr);
-    if (xtrerr == stderr &&
-	!(xtrerr = fdopen(movefd(dup(fileno(stderr))), "w")))
-	xtrerr = stderr;
+    if (xtrerr == stderr && (type < WC_SUBSH || type == WC_TIMED)) {
+	if (!(xtrerr = fdopen(movefd(dup(fileno(stderr))), "w")))
+	    xtrerr = stderr;
+	else
+	    fdtable[fileno(xtrerr)] = 3;
+    }
 
     /* Add pipeline input/output to mnodes */
     if (input)
Index: Test/.distfiles
===================================================================
@@ -3,5 +3,5 @@
     ztst.zsh
     01grammar.ztst 02alias.ztst 03quoting.ztst 04redirect.ztst
     05command.ztst 06arith.ztst 07cond.ztst 08traps.ztst 09funcdef.ztst
-    10prompt.ztst 50cd.ztst
+    10prompt.ztst 50cd.ztst 51xtrace.ztst
 '

--- /dev/null	Tue May  5 13:32:27 1998
+++ Test/51xtrace.ztst	Sat Feb 19 16:53:07 2000
@@ -0,0 +1,60 @@
+# Test that xtrace output is correctly generated
+
+%prep
+  mkdir xtrace.tmp && cd xtrace.tmp
+
+%test
+
+  set -x
+  print 'Tracing: builtin'
+  print 'Tracing: builtin 2>file' 2>xtrace.err
+  cat <<<'Tracing: external'
+  cat <<<'Tracing: external 2>file' 2>>xtrace.err
+  ( print 'Tracing: ( builtin )' )
+  ( print 'Tracing: ( builtin ) 2>file' ) 2>>xtrace.err
+  ( cat <<<'Tracing: ( external )' )
+  ( cat <<<'Tracing: ( external ) 2>file' ) 2>>xtrace.err
+  { print 'Tracing: { builtin }' }
+  { print 'Tracing: { builtin } 2>file' } 2>>xtrace.err
+  { cat <<<'Tracing: { external }' }
+  { cat <<<'Tracing: { external } 2>file' } 2>>xtrace.err
+  repeat 1 do print 'Tracing: do builtin done'; done
+  repeat 1 do print 'Tracing: do builtin done 2>file'; done 2>>xtrace.err
+  repeat 1 do cat <<<'Tracing: do external done'; done
+  repeat 1 do cat <<<'Tracing: do external done'; done 2>>xtrace.err
+  set +x
+  cat xtrace.err
+0:xtrace with and without redirection
+>Tracing: builtin
+>Tracing: builtin 2>file
+>Tracing: external
+>Tracing: external 2>file
+>Tracing: ( builtin )
+>Tracing: ( builtin ) 2>file
+>Tracing: ( external )
+>Tracing: ( external ) 2>file
+>Tracing: { builtin }
+>Tracing: { builtin } 2>file
+>Tracing: { external }
+>Tracing: { external } 2>file
+>Tracing: do builtin done
+>Tracing: do builtin done 2>file
+>Tracing: do external done
+>Tracing: do external done
+>+ZTST_execchunk:2> print Tracing: ( builtin ) 2>file
+>+ZTST_execchunk:2> cat
+>+ZTST_execchunk:2> print Tracing: { builtin } 2>file
+>+ZTST_execchunk:2> cat
+>+ZTST_execchunk:2> print Tracing: do builtin done 2>file
+>+ZTST_execchunk:2> cat
+?+ZTST_execchunk:2> print Tracing: builtin
+?+ZTST_execchunk:2> print Tracing: builtin 2>file
+?+ZTST_execchunk:2> cat
+?+ZTST_execchunk:2> cat
+?+ZTST_execchunk:2> print Tracing: ( builtin )
+?+ZTST_execchunk:2> cat
+?+ZTST_execchunk:2> print Tracing: { builtin }
+?+ZTST_execchunk:2> cat
+?+ZTST_execchunk:2> print Tracing: do builtin done
+?+ZTST_execchunk:2> cat
+?+ZTST_execchunk:2> set +x

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2000-02-20  1:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-02-19 19:19 PATCH: redirection and xtrace output Bart Schaefer
2000-02-20  1:18 ` PATCH: " Bart Schaefer

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