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(" "); }