Module Name:    src
Committed By:   kre
Date:           Sat Jun 15 06:07:14 UTC 2024

Modified Files:
        src/bin/sh: jobs.c

Log Message:
When generating the text that identifies the command for the job tree
from the parse tree data, be more intelligent about where we stick ';'
characters.

Previously, given:

        (sleep 2 & sleep 3 & sleep 10&) & jobs -l

The output would be something like

[1] + 23631 Running           (sleep 2 &; sleep 3 &; sleep 10 &)

That's nonsense (even if clear enough).   After this change the
output will be:

[1] + 12116 Running           (sleep 2 & sleep 3 & sleep 10 &)

There are a few other cases where an incorrect ';' will also be suppressed.


To generate a diff of this commit:
cvs rdiff -u -r1.120 -r1.121 src/bin/sh/jobs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/jobs.c
diff -u src/bin/sh/jobs.c:1.120 src/bin/sh/jobs.c:1.121
--- src/bin/sh/jobs.c:1.120	Sat Jun 15 05:18:48 2024
+++ src/bin/sh/jobs.c	Sat Jun 15 06:07:14 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: jobs.c,v 1.120 2024/06/15 05:18:48 kre Exp $	*/
+/*	$NetBSD: jobs.c,v 1.121 2024/06/15 06:07:14 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: jobs.c,v 1.120 2024/06/15 05:18:48 kre Exp $");
+__RCSID("$NetBSD: jobs.c,v 1.121 2024/06/15 06:07:14 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -111,7 +111,7 @@ STATIC int dowait(int, struct job *, str
 #define WSILENT 4
 STATIC int jobstatus(const struct job *, int);
 STATIC int waitproc(int, struct job *, int *);
-STATIC void cmdtxt(union node *);
+STATIC int cmdtxt(union node *, int);
 STATIC void cmdlist(union node *, int);
 STATIC void cmdputs(const char *);
 inline static void cmdputi(int);
@@ -1720,7 +1720,7 @@ commandtext(struct procstat *ps, union n
 	else
 		len = sizeof(ps->cmd) / 10;
 	cmdnleft = len;
-	cmdtxt(n);
+	(void)cmdtxt(n, 1);
 	if (cmdnleft <= 0) {
 		char *p = ps->cmd + len - 4;
 		p[0] = '.';
@@ -1736,8 +1736,16 @@ commandtext(struct procstat *ps, union n
 }
 
 
-STATIC void
-cmdtxt(union node *n)
+/*
+ * Generate a string describing tree node n & its descendants (recursive calls)
+ *
+ * Return true (non-zero) if the output is complete (ends with an operator)
+ * so no ';' need be added before the following command.  Return false (zero)
+ * if a ';' is needed to terminate the output if it is followed by something
+ * which is not an operator.
+ */
+STATIC int
+cmdtxt(union node *n, int top)
 {
 	union node *np;
 	struct nodelist *lp;
@@ -1745,111 +1753,120 @@ cmdtxt(union node *n)
 	int i;
 
 	if (n == NULL || cmdnleft <= 0)
-		return;
+		return 1;
 	switch (n->type) {
 	case NSEMI:
-		cmdtxt(n->nbinary.ch1);
-		cmdputs("; ");
-		cmdtxt(n->nbinary.ch2);
-		break;
+		if (!cmdtxt(n->nbinary.ch1, 0))
+			cmdputs(";");
+		cmdputs(" ");
+		return cmdtxt(n->nbinary.ch2, 0);
 	case NAND:
-		cmdtxt(n->nbinary.ch1);
+		(void)cmdtxt(n->nbinary.ch1, 0);
 		cmdputs(" && ");
-		cmdtxt(n->nbinary.ch2);
-		break;
+		return cmdtxt(n->nbinary.ch2, 0);
 	case NOR:
-		cmdtxt(n->nbinary.ch1);
+		(void) cmdtxt(n->nbinary.ch1, 0);
 		cmdputs(" || ");
-		cmdtxt(n->nbinary.ch2);
-		break;
+		return cmdtxt(n->nbinary.ch2, 0);
 	case NDNOT:
 		cmdputs("! ");
 		/* FALLTHROUGH */
 	case NNOT:
 		cmdputs("! ");
-		cmdtxt(n->nnot.com);
+		return cmdtxt(n->nnot.com, 0);
 		break;
 	case NPIPE:
 		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
-			cmdtxt(lp->n);
+			(void) cmdtxt(lp->n, 0);
 			if (lp->next)
 				cmdputs(" | ");
 		}
-		if (n->npipe.backgnd)
+		if (!top && n->npipe.backgnd) {
 			cmdputs(" &");
-		break;
+			return 1;
+		}
+		return 0;
 	case NSUBSHELL:
 		cmdputs("(");
-		cmdtxt(n->nredir.n);
+		(void) cmdtxt(n->nredir.n, 0);
 		cmdputs(")");
-		break;
+		return 0;
 	case NREDIR:
 	case NBACKGND:
-		cmdtxt(n->nredir.n);
-		break;
+		return cmdtxt(n->nredir.n, top);
 	case NIF:
 		cmdputs("if ");
-		cmdtxt(n->nif.test);
-		cmdputs("; then ");
-		cmdtxt(n->nif.ifpart);
+		if (!cmdtxt(n->nif.test, 0))
+			cmdputs(";");
+		cmdputs(" then ");
+		i = cmdtxt(n->nif.ifpart, 0);
 		if (n->nif.elsepart) {
-			cmdputs("; else ");
-			cmdtxt(n->nif.elsepart);
-		}
-		cmdputs("; fi");
-		break;
+			if (i == 0)
+				cmdputs(";");
+			cmdputs(" else ");
+			i = cmdtxt(n->nif.elsepart, 0);
+		}
+		if (i == 0)
+			cmdputs(";");
+		cmdputs(" fi");
+		return 0;
 	case NWHILE:
 		cmdputs("while ");
 		goto until;
 	case NUNTIL:
 		cmdputs("until ");
  until:
-		cmdtxt(n->nbinary.ch1);
-		cmdputs("; do ");
-		cmdtxt(n->nbinary.ch2);
-		cmdputs("; done");
-		break;
+		if (!cmdtxt(n->nbinary.ch1, 0))
+			cmdputs(";");
+		cmdputs(" do ");
+		if (!cmdtxt(n->nbinary.ch2, 0))
+			cmdputs(";");
+		cmdputs(" done");
+		return 0;
 	case NFOR:
 		cmdputs("for ");
 		cmdputs(n->nfor.var);
 		cmdputs(" in ");
 		cmdlist(n->nfor.args, 1);
 		cmdputs("; do ");
-		cmdtxt(n->nfor.body);
-		cmdputs("; done");
-		break;
+		if (!cmdtxt(n->nfor.body, 0))
+			cmdputs(";");
+		cmdputs(" done");
+		return 0;
 	case NCASE:
 		cmdputs("case ");
 		cmdputs(n->ncase.expr->narg.text);
 		cmdputs(" in ");
 		for (np = n->ncase.cases; np; np = np->nclist.next) {
-			cmdtxt(np->nclist.pattern);
+			(void) cmdtxt(np->nclist.pattern, 0);
 			cmdputs(") ");
-			cmdtxt(np->nclist.body);
+			(void) cmdtxt(np->nclist.body, 0);
 			switch (n->type) {	/* switch (not if) for later */
 			case NCLISTCONT:
-				cmdputs(";& ");
+				cmdputs(" ;& ");
 				break;
 			default:
-				cmdputs(";; ");
+				cmdputs(" ;; ");
 				break;
 			}
 		}
 		cmdputs("esac");
-		break;
+		return 0;
 	case NDEFUN:
 		cmdputs(n->narg.text);
 		cmdputs("() { ... }");
-		break;
+		return 0;
 	case NCMD:
 		cmdlist(n->ncmd.args, 1);
 		cmdlist(n->ncmd.redirect, 0);
-		if (n->ncmd.backgnd)
+		if (!top && n->ncmd.backgnd) {
 			cmdputs(" &");
-		break;
+			return 1;
+		}
+		return 0;
 	case NARG:
 		cmdputs(n->narg.text);
-		break;
+		return 0;
 	case NTO:
 		p = ">";  i = 1;  goto redir;
 	case NCLOBBER:
@@ -1874,17 +1891,18 @@ cmdtxt(union node *n)
 			else
 				cmdputi(n->ndup.dupfd);
 		} else {
-			cmdtxt(n->nfile.fname);
+			(void) cmdtxt(n->nfile.fname, 0);
 		}
-		break;
+		return 0;
 	case NHERE:
 	case NXHERE:
 		cmdputs("<<...");
-		break;
+		return 0;
 	default:
 		cmdputs("???");
-		break;
+		return 0;
 	}
+	return 0;
 }
 
 STATIC void
@@ -1893,7 +1911,7 @@ cmdlist(union node *np, int sep)
 	for (; np; np = np->narg.next) {
 		if (!sep)
 			cmdputs(" ");
-		cmdtxt(np);
+		(void) cmdtxt(np, 0);
 		if (sep && np->narg.next)
 			cmdputs(" ");
 	}

Reply via email to