Module Name: src Committed By: kre Date: Thu Mar 16 13:21:59 UTC 2017
Modified Files: src/bin/sh: show.c show.h Log Message: Undo local changes not intended to be committed (and certainly not with that commit message) in the previous update. This stuff works, and will probably appear sometime, but not right now. To generate a diff of this commit: cvs rdiff -u -r1.35 -r1.36 src/bin/sh/show.c cvs rdiff -u -r1.8 -r1.9 src/bin/sh/show.h 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/show.c diff -u src/bin/sh/show.c:1.35 src/bin/sh/show.c:1.36 --- src/bin/sh/show.c:1.35 Thu Mar 16 13:09:06 2017 +++ src/bin/sh/show.c Thu Mar 16 13:21:59 2017 @@ -1,11 +1,9 @@ -/* $NetBSD: show.c,v 1.35 2017/03/16 13:09:06 kre Exp $ */ +/* $NetBSD: show.c,v 1.36 2017/03/16 13:21:59 kre Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * - * Copyright (c) 2016,2017 The NetBSD Foundation, Inc. All rights reserved. - * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * @@ -17,16 +15,14 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University, the NetBSD Foundation, nor the - * names of their contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS, FOUNDATION, AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * IN NO EVENT SHALL THE REGENTS, FOUNDATION OR CONTRIBUTORS BE LIABLE + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -41,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; #else -__RCSID("$NetBSD: show.c,v 1.35 2017/03/16 13:09:06 kre Exp $"); +__RCSID("$NetBSD: show.c,v 1.36 2017/03/16 13:21:59 kre Exp $"); #endif #endif /* not lint */ @@ -49,10 +45,6 @@ __RCSID("$NetBSD: show.c,v 1.35 2017/03/ #include <stdarg.h> #include <stdlib.h> #include <unistd.h> -#include <fcntl.h> -#include <errno.h> - -#include <sys/uio.h> #include "shell.h" #include "parser.h" @@ -60,903 +52,390 @@ __RCSID("$NetBSD: show.c,v 1.35 2017/03/ #include "mystring.h" #include "show.h" #include "options.h" -#include "redir.h" -#include "error.h" - -#if defined(DEBUG) && !defined(DBG_PID) -/* - * If this is compiled, it means this is being compiled in a shell that still - * has an older shell.h (a simpler TRACE() mechanism than is coming soon.) - * - * Compensate for as much of that as is missing and is needed here - * to compile and operate at all. After the other changes have appeared, - * this little block can (and should be) deleted (sometime). - * - * Try to avoid waiting 22 years... - */ -#define DBG_PID 1 -#define DBG_NEST 2 - -/* decide at compile time for now (DBG_NEST won't work) */ -static int DFlags = DBG_PID; -static int ShNest = 0; -#endif - +#ifndef SMALL #define DEFINE_NODENAMES #include "nodenames.h" - -#define TR_STD_WIDTH 60 /* tend to fold lines wider than this */ -#define TR_IOVECS 10 /* number of lines or trace (max) / write */ - -typedef struct traceinfo { - int tfd; /* file descriptor for open trace file */ - int nxtiov; /* the buffer we should be writing to */ - char lastc; /* the last non-white character output */ - uint8_t supr; /* char classes to supress after \n */ - pid_t pid; /* process id of process that opened that file */ - size_t llen; /* number of chars in current output line */ - size_t blen; /* chars used in current buffer being filled */ - char * tracefile; /* name of the tracefile */ - struct iovec lines[TR_IOVECS]; /* filled, flling, pending buffers */ -} TFILE; - -/* These are auto turned off when non white space is printed */ -#define SUP_NL 0x01 /* don't print \n */ -#define SUP_SP 0x03 /* supress spaces */ -#define SUP_WSP 0x04 /* supress all white space */ - -#ifdef DEBUG -TFILE tracedata, *tracetfile; -FILE *tracefile; /* just for histedit */ #endif -#ifdef DEBUG -static void shtree(union node *, int, int, int, TFILE *); -static void shcmd(union node *, TFILE *); -static void shsubsh(union node *, TFILE *); -static void shredir(union node *, TFILE *, int); -static void sharg(union node *, TFILE *); -static void indent(int, TFILE *); -static void trstring(const char *); -static void trace_putc(char, TFILE *); -static void trace_puts(const char *, TFILE *); -static void trace_flush(TFILE *, int); -static char *trace_id(TFILE *); - -inline static int trlinelen(TFILE *); -#endif - -/* - * These functions are the externally visible interface - */ +FILE *tracefile; #ifdef DEBUG -void -opentrace(void) -{ - char *s; - int fd; - int i; - pid_t pid; - - if (debug != 1) { - /* leave open because libedit might be using it */ - if (tracefile) - fflush(tracefile); - if (tracetfile) - trace_flush(tracetfile, 1); - return; - } - pid = getpid(); - if (asprintf(&s, "trace.%jd", (intmax_t)pid) <= 0) { - debug = 0; - error("Cannot asprintf tracefilename"); - }; - - fd = open(s, O_WRONLY|O_APPEND|O_CREAT, 0666); - if (fd == -1) { - debug = 0; - error("Can't open tracefile: %s (%s)\n", s, strerror(errno)); - } - fd = to_upper_fd(fd); - if (fd <= 2) { - (void) close(fd); - debug = 0; - error("Attempt to use fd %d as tracefile thwarted\n", fd); - } - - /* - * This stuff is just so histedit has a FILE * to use - */ - if (tracefile) - (void) fclose(tracefile); /* also closes tfd */ - tracefile = fdopen(fd, "a"); /* don't care if it is NULL */ - if (tracefile) /* except here... */ - setlinebuf(tracefile); - - /* - * Now the real tracing setup - */ - if (tracedata.tfd > 0 && tracedata.tfd != fd) - (void) close(tracedata.tfd); /* usually done by fclose() */ - tracedata.tfd = fd; - tracedata.pid = pid; - tracedata.nxtiov = 0; - tracedata.blen = 0; - tracedata.llen = 0; - tracedata.lastc = '\0'; - tracedata.supr = SUP_NL | SUP_WSP; - -#define replace(f, v) do { \ - if (tracedata.f != NULL) \ - free(tracedata.f); \ - tracedata.f = v; \ - } while (/*CONSTCOND*/ 0) - - replace(tracefile, s); - - for (i = 0; i < TR_IOVECS; i++) { - replace(lines[i].iov_base, NULL); - tracedata.lines[i].iov_len = 0; - } - -#undef replace - - tracetfile = &tracedata; - - trace_puts("\nTracing started.\n", tracetfile); -} - -void -trace(const char *fmt, ...) -{ - va_list va; - char *s; - - if (debug != 1 || !tracetfile) - return; - va_start(va, fmt); - (void) vasprintf(&s, fmt, va); - va_end(va); - - trace_puts(s, tracetfile); - free(s); - if (tracetfile->llen == 0) - trace_flush(tracetfile, 0); -} - -void -tracev(const char *fmt, va_list va) -{ - va_list ap; - char *s; - - if (debug != 1 || !tracetfile) - return; - va_copy(ap, va); - (void) vasprintf(&s, fmt, ap); - va_end(ap); - - trace_puts(s, tracetfile); - free(s); - if (tracetfile->llen == 0) - trace_flush(tracetfile, 0); -} - - -void -trputs(const char *s) -{ - if (debug != 1 || !tracetfile) - return; - trace_puts(s, tracetfile); -} - -void -trputc(int c) -{ - if (debug != 1 || !tracetfile) - return; - trace_putc(c, tracetfile); -} +static int shtree(union node *, int, int, char *, FILE*); +static int shcmd(union node *, FILE *); +static int shsubsh(union node *, FILE *); +static int shredir(union node *, FILE *, int); +static int sharg(union node *, FILE *); +static int indent(int, char *, FILE *); +static void trstring(char *); void showtree(union node *n) { - TFILE *fp; + FILE *fp; - if ((fp = tracetfile) == NULL) - return; + fp = tracefile ? tracefile : stdout; - trace_puts("showtree(", fp); + trputs("showtree("); if (n == NULL) - trace_puts("NULL", fp); + trputs("NULL"); else if (n == NEOF) - trace_puts("NEOF", fp); - else - trace("%p", n); - trace_puts(") called\n", fp); + trputs("NEOF"); + trputs(") called\n"); if (n != NULL && n != NEOF) - shtree(n, 1, 1, 1, fp); + shtree(n, 1, 1, NULL, fp); } -void -trargs(char **ap) -{ - if (debug != 1 || !tracetfile) - return; - while (*ap) { - trstring(*ap++); - if (*ap) - trace_putc(' ', tracetfile); - else - trace_putc('\n', tracetfile); - } -} -#endif - - -/* - * Beyond here we just have the implementation of all of that - */ - -#ifdef DEBUG - -inline static int -trlinelen(TFILE * fp) -{ - return fp->llen; -} - -static void -shtree(union node *n, int ind, int ilvl, int nl, TFILE *fp) +static int +shtree(union node *n, int ind, int nl, char *pfx, FILE *fp) { struct nodelist *lp; const char *s; + int len; if (n == NULL) { if (nl) - trace_putc('\n', fp); - return; + fputc('\n', fp); + return 0; } - indent(ind, fp); + len = indent(ind, pfx, fp); switch (n->type) { case NSEMI: - s = NULL; + s = "; "; + len += 2; goto binop; case NAND: s = " && "; + len += 4; goto binop; case NOR: s = " || "; + len += 4; binop: - shtree(n->nbinary.ch1, 0, ilvl, 0, fp); - if (s != NULL) - trace_puts(s, fp); - if (trlinelen(fp) >= TR_STD_WIDTH) { - trace_putc('\n', fp); - indent(ind < 0 ? 2 : ind + 1, fp); - } else if (s == NULL) { - if (fp->lastc != '&') - trace_puts("; ", fp); - else - trace_putc(' ', fp); + len += shtree(n->nbinary.ch1, 0, 0, NULL, fp); + fputs(s, fp); + if (len >= 60) { + putc('\n', fp); + len = indent(ind < 0 ? 2 : ind + 1, pfx, fp); } - shtree(n->nbinary.ch2, 0, ilvl, nl, fp); + len += shtree(n->nbinary.ch2, 0, nl, NULL, fp); break; case NCMD: - shcmd(n, fp); - if (n->ncmd.backgnd) - trace_puts(" &", fp); - if (nl && trlinelen(fp) > 0) - trace_putc('\n', fp); + len += shcmd(n, fp); + if (nl && len > 0) + len = 0, putc('\n', fp); break; case NPIPE: for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - shtree(lp->n, 0, ilvl, 0, fp); + len += shcmd(lp->n, fp); if (lp->next) { - trace_puts(" |", fp); - if (trlinelen(fp) >= TR_STD_WIDTH) { - trace_putc('\n', fp); - indent((ind < 0 ? ilvl : ind) + 1, fp); - } else - trace_putc(' ', fp); + len += 3, fputs(" | ", fp); + if (len >= 60) { + fputc('\n', fp); + len = indent(ind < 0 ? 2 : ind + 1, + pfx, fp); + } } } if (n->npipe.backgnd) - trace_puts(" &", fp); - if (nl || trlinelen(fp) >= TR_STD_WIDTH) - trace_putc('\n', fp); + len += 2, fputs(" &", fp); + if (nl || len >= 60) + len = 0, fputc('\n', fp); break; - case NBACKGND: case NSUBSHELL: - shsubsh(n, fp); - if (n->type == NBACKGND) - trace_puts(" &", fp); - if (nl && trlinelen(fp) > 0) - trace_putc('\n', fp); - break; - case NDEFUN: - trace_puts(n->narg.text, fp); - trace_puts("() {\n", fp); - indent(ind, fp); - shtree(n->narg.next, (ind < 0 ? ilvl : ind) + 1, ilvl+1, 1, fp); - indent(ind, fp); - trace_puts("}\n", fp); - break; - case NNOT: - trace_puts("! ", fp); - shtree(n->nnot.com, -1, ilvl, nl, fp); - break; - case NREDIR: - shtree(n->nredir.n, -1, ilvl, 0, fp); - shredir(n->nredir.redirect, fp, n->nredir.n == NULL); - if (nl) - trace_putc('\n', fp); - break; - - case NIF: - itsif: - trace_puts("if ", fp); - shtree(n->nif.test, -1, ilvl, 0, fp); - if (trlinelen(fp) > 0 && trlinelen(fp) < TR_STD_WIDTH) { - if (fp->lastc != '&') - trace_puts(" ;", fp); - } else - indent(ilvl, fp); - trace_puts(" then ", fp); - if (nl || trlinelen(fp) > TR_STD_WIDTH - 24) - indent(ilvl+1, fp); - shtree(n->nif.ifpart, -1, ilvl + 1, 0, fp); - if (trlinelen(fp) > 0 && trlinelen(fp) < TR_STD_WIDTH) { - if (fp->lastc != '&') - trace_puts(" ;", fp); - } else - indent(ilvl, fp); - if (n->nif.elsepart && n->nif.elsepart->type == NIF) { - if (nl || trlinelen(fp) > TR_STD_WIDTH - 24) - indent(ilvl, fp); - n = n->nif.elsepart; - trace_puts(" el", fp); - goto itsif; - } - if (n->nif.elsepart) { - if (nl || trlinelen(fp) > TR_STD_WIDTH - 24) - indent(ilvl+1, fp); - trace_puts(" else ", fp); - shtree(n->nif.elsepart, -1, ilvl + 1, 0, fp); - if (fp->lastc != '&') - trace_puts(" ;", fp); - } - trace_puts(" fi", fp); - if (nl) - trace_putc('\n', fp); - break; - - case NWHILE: - trace_puts("while ", fp); - goto aloop; - case NUNTIL: - trace_puts("until ", fp); - aloop: - shtree(n->nbinary.ch1, -1, ilvl, 0, fp); - if (trlinelen(fp) > 0 && trlinelen(fp) < TR_STD_WIDTH) { - if (fp->lastc != '&') - trace_puts(" ;", fp); - } else - trace_putc('\n', fp); - trace_puts(" do ", fp); - shtree(n->nbinary.ch1, -1, ilvl + 1, 1, fp); - trace_puts(" done ", fp); - if (nl) - trace_putc('\n', fp); - break; - - case NFOR: - trace_puts("for ", fp); - trace_puts(n->nfor.var, fp); - if (n->nfor.args) { - union node *argp; - - trace_puts(" in ", fp); - for (argp = n->nfor.args; argp; argp=argp->narg.next) { - sharg(argp, fp); - trace_putc(' ', fp); - } - if (trlinelen(fp) > 0 && trlinelen(fp) < TR_STD_WIDTH) { - if (fp->lastc != '&') - trace_putc(';', fp); - } else - trace_putc('\n', fp); - } - trace_puts(" do ", fp); - shtree(n->nfor.body, -1, ilvl + 1, 0, fp); - if (fp->lastc != '&') - trace_putc(';', fp); - trace_puts(" done", fp); - if (nl) - trace_putc('\n', fp); - break; - - case NCASE: - trace_puts("case ", fp); - sharg(n->ncase.expr, fp); - trace_puts(" in", fp); - if (nl) - trace_putc('\n', fp); - { - union node *cp; - - for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) { - union node *patp; - - if (nl || trlinelen(fp) > TR_STD_WIDTH - 16) - indent(ilvl, fp); - else - trace_putc(' ', fp); - trace_putc('(', fp); - patp = cp->nclist.pattern; - while (patp != NULL) { - trace_putc(' ', fp); - sharg(patp, fp); - trace_putc(' ', fp); - if ((patp = patp->narg.next) != NULL) - trace_putc('|', fp); - } - trace_putc(')', fp); - if (nl) - indent(ilvl + 1, fp); - else - trace_putc(' ', fp); - shtree(cp->nclist.body, -1, ilvl+2, 0, fp); - trace_puts(" ;;", fp); - if (nl) - trace_putc('\n', fp); - } - } - if (nl) { - trace_putc('\n', fp); - indent(ind, fp); - } else - trace_putc(' ', fp); - trace_puts("esac", fp); + len += shsubsh(n, fp); + if (nl && len > 0) + len = 0, putc('\n', fp); + break; + default: +#ifdef NODETYPENAME + len += fprintf(fp, "<node type %d [%s]>", n->type, + NODETYPENAME(n->type)); +#else + len += fprintf(fp, "<node type %d>", n->type); +#endif if (nl) - trace_putc('\n', fp); - break; - - default: { - char *str; - - asprintf(&str, "<node type %d [%s]>", n->type, - NODETYPENAME(n->type)); - trace_puts(str, fp); - free(str); - if (nl) - trace_putc('\n', fp); - } + len = 0, putc('\n', fp); break; } + return len; } -static void -shcmd(union node *cmd, TFILE *fp) + +static int +shcmd(union node *cmd, FILE *fp) { union node *np; int first; + int len = 0; first = 1; for (np = cmd->ncmd.args ; np ; np = np->narg.next) { if (! first) - trace_putc(' ', fp); - sharg(np, fp); + len++, fputc(' ', fp); + len += sharg(np, fp); first = 0; } - shredir(cmd->ncmd.redirect, fp, first); + return len + shredir(cmd, fp, first); } -static void -shsubsh(union node *cmd, TFILE *fp) +static int +shsubsh(union node *cmd, FILE *fp) { - trace_puts(" ( ", fp); - shtree(cmd->nredir.n, -1, 3, 0, fp); - trace_puts(" ) ", fp); - shredir(cmd->ncmd.redirect, fp, 1); + int len = 6; + + fputs(" ( ", fp); + len += shtree(cmd->nredir.n, -1, 0, NULL, fp); + fputs(" ) ", fp); + len += shredir(cmd, fp, 1); + + return len; } -static void -shredir(union node *np, TFILE *fp, int first) +static int +shredir(union node *cmd, FILE *fp, int first) { + union node *np; const char *s; int dftfd; + int len = 0; char buf[106]; - for ( ; np ; np = np->nfile.next) { + for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { if (! first) - trace_putc(' ', fp); + len++, fputc(' ', fp); switch (np->nfile.type) { - case NTO: s = ">"; dftfd = 1; break; - case NCLOBBER: s = ">|"; dftfd = 1; break; - case NAPPEND: s = ">>"; dftfd = 1; break; - case NTOFD: s = ">&"; dftfd = 1; break; - case NFROM: s = "<"; dftfd = 0; break; - case NFROMFD: s = "<&"; dftfd = 0; break; - case NFROMTO: s = "<>"; dftfd = 0; break; - case NXHERE: /* FALLTHROUGH */ - case NHERE: s = "<<"; dftfd = 0; break; - default: s = "*error*"; dftfd = 0; break; - } - if (np->nfile.fd != dftfd) { - sprintf(buf, "%d", np->nfile.fd); - trace_puts(buf, fp); - } - trace_puts(s, fp); + case NTO: s = ">"; dftfd = 1; len += 1; break; + case NCLOBBER: s = ">|"; dftfd = 1; len += 2; break; + case NAPPEND: s = ">>"; dftfd = 1; len += 2; break; + case NTOFD: s = ">&"; dftfd = 1; len += 2; break; + case NFROM: s = "<"; dftfd = 0; len += 1; break; + case NFROMFD: s = "<&"; dftfd = 0; len += 2; break; + case NFROMTO: s = "<>"; dftfd = 0; len += 2; break; + case NXHERE: /* FALLTHROUGH */ + case NHERE: s = "<<"; dftfd = 0; len += 2; break; + default: s = "*error*"; dftfd = 0; len += 7; break; + } + if (np->nfile.fd != dftfd) + len += fprintf(fp, "%d", np->nfile.fd); + fputs(s, fp); if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { - if (np->ndup.vname) - sharg(np->ndup.vname, fp); - else { - sprintf(buf, "%d", np->ndup.dupfd); - trace_puts(buf, fp); - } + len += fprintf(fp, "%d", np->ndup.dupfd); } else if (np->nfile.type == NHERE || np->nfile.type == NXHERE) { if (np->nfile.type == NHERE) - trace_putc('\\', fp); - trace_puts("!!!\n", fp); + fputc('\\', fp); + fputs("!!!\n", fp); s = np->nhere.doc->narg.text; if (strlen(s) > 100) { memmove(buf, s, 100); buf[100] = '\0'; - strcat(buf, " ...\n"); + strcat(buf, " ..."); s = buf; } - trace_puts(s, fp); - trace_puts("!!! ", fp); + fputs(s, fp); + fputs("!!!", fp); + len = 3; } else { - sharg(np->nfile.fname, fp); + len += sharg(np->nfile.fname, fp); } first = 0; } + return len; } -static void -sharg(union node *arg, TFILE *fp) + + +static int +sharg(union node *arg, FILE *fp) { - char *p, *s; + char *p; struct nodelist *bqlist; - int subtype = 0; - int quoted = 0; + int subtype; + int len = 0; if (arg->type != NARG) { - asprintf(&s, "<node type %d> ! NARG\n", arg->type); - trace_puts(s, fp); - abort(); /* no need to free s, better not to */ + fprintf(fp, "<node type %d>\n", arg->type); + abort(); } - bqlist = arg->narg.backquote; for (p = arg->narg.text ; *p ; p++) { switch (*p) { case CTLESC: - trace_putc('\\', fp); - trace_putc(*++p, fp); + putc(*++p, fp); + len++; break; - case CTLVAR: + putc('$', fp); + putc('{', fp); + len += 2; subtype = *++p; - if (!quoted != !(subtype & VSQUOTE)) - trace_putc('"', fp); - trace_putc('$', fp); - trace_putc('{', fp); - if ((subtype & VSTYPE) == VSLENGTH) - trace_putc('#', fp); + if (subtype == VSLENGTH) + len++, putc('#', fp); while (*++p != '=') - trace_putc(*p, fp); + len++, putc(*p, fp); if (subtype & VSNUL) - trace_putc(':', fp); + len++, putc(':', fp); switch (subtype & VSTYPE) { case VSNORMAL: - /* { */ - trace_putc('}', fp); - if (!quoted != !(subtype & VSQUOTE)) - trace_putc('"', fp); + putc('}', fp); + len++; break; case VSMINUS: - trace_putc('-', fp); + putc('-', fp); + len++; break; case VSPLUS: - trace_putc('+', fp); + putc('+', fp); + len++; break; case VSQUESTION: - trace_putc('?', fp); + putc('?', fp); + len++; break; case VSASSIGN: - trace_putc('=', fp); + putc('=', fp); + len++; break; - case VSTRIMLEFTMAX: - trace_putc('#', fp); - /* FALLTHRU */ case VSTRIMLEFT: - trace_putc('#', fp); + putc('#', fp); + len++; + break; + case VSTRIMLEFTMAX: + putc('#', fp); + putc('#', fp); + len += 2; break; - case VSTRIMRIGHTMAX: - trace_putc('%', fp); - /* FALLTHRU */ case VSTRIMRIGHT: - trace_putc('%', fp); + putc('%', fp); + len++; break; - case VSLENGTH: + case VSTRIMRIGHTMAX: + putc('%', fp); + putc('%', fp); + len += 2; break; - default: { - char str[32]; - - snprintf(str, sizeof str, - "<subtype %d>", subtype); - trace_puts(str, fp); - } + case VSLENGTH: break; + default: + len += fprintf(fp, "<subtype %d>", subtype); } break; case CTLENDVAR: - /* { */ - trace_putc('}', fp); - if (!quoted != !(subtype & VSQUOTE)) - trace_putc('"', fp); - subtype = 0; - break; - - case CTLBACKQ|CTLQUOTE: - if (!quoted) - trace_putc('"', fp); - /* FALLTHRU */ + putc('}', fp); + len++; + break; case CTLBACKQ: - trace_putc('$', fp); - trace_putc('(', fp); - if (bqlist) { - shtree(bqlist->n, -1, 3, 0, fp); - bqlist = bqlist->next; - } else - trace_puts("???", fp); - trace_putc(')', fp); - if (!quoted && *p == (CTLBACKQ|CTLQUOTE)) - trace_putc('"', fp); - break; - - case CTLQUOTEMARK: - if (subtype != 0 || !quoted) { - trace_putc('"', fp); - quoted++; - } - break; - case CTLQUOTEEND: - trace_putc('"', fp); - quoted--; - break; - case CTLARI: - trace_puts("$(( ", fp); - break; - case CTLENDARI: - trace_puts(" ))", fp); + case CTLBACKQ|CTLQUOTE: + putc('$', fp); + putc('(', fp); + len += shtree(bqlist->n, -1, 0, NULL, fp) + 3; + putc(')', fp); break; - default: - if (*p == '$') - trace_putc('\\', fp); - trace_putc(*p, fp); + putc(*p, fp); + len++; break; } } - if (quoted) - trace_putc('"', fp); + return len; } -static void -indent(int amount, TFILE *fp) +static int +indent(int amount, char *pfx, FILE *fp) { int i; + int len = 0; - if (amount <= 0) - return; - - amount <<= 2; /* indent slots -> chars */ - - i = trlinelen(fp); - fp->supr = SUP_NL; - if (i > amount) { - trace_putc('\n', fp); - i = 0; - } - fp->supr = 0; - for (; i < amount - 7 ; i++) { - trace_putc('\t', fp); - i |= 7; - } - while (i < amount) { - trace_putc(' ', fp); - i++; + /* + * in practice, pfx is **always** NULL + * but here, we assume if it were not, at least strlen(pfx) < 8 + * if that is invalid, output will look messy + */ + for (i = 0 ; i < amount ; i++) { + if (pfx && i == amount - 1) + fputs(pfx, fp); + putc('\t', fp); + len |= 7; + len++; } - fp->supr = SUP_WSP; + return len; } +#endif -static void -trace_putc(char c, TFILE *fp) -{ - char *p; - if (c == '\0') - return; - if (debug == 0 || fp == NULL) - return; - if (fp->llen == 0) { - if (fp->blen != 0) - abort(); +/* + * Debugging stuff. + */ - if ((fp->supr & SUP_NL) && c == '\n') - return; - if ((fp->supr & (SUP_WSP|SUP_SP)) && c == ' ') - return; - if ((fp->supr & SUP_WSP) && c == '\t') - return; - if (fp->nxtiov >= TR_IOVECS - 1) /* should be rare */ - trace_flush(fp, 0); - p = trace_id(fp); - if (p != NULL) { - fp->lines[fp->nxtiov].iov_base = p; - fp->lines[fp->nxtiov].iov_len = strlen(p); - fp->nxtiov++; - } - } else if (fp->blen && fp->blen >= fp->lines[fp->nxtiov].iov_len) { - fp->blen = 0; - if (++fp->nxtiov >= TR_IOVECS) - trace_flush(fp, 0); - } - if (fp->lines[fp->nxtiov].iov_len == 0) { - p = (char *)malloc(2 * TR_STD_WIDTH); - if (p == NULL) { - trace_flush(fp, 1); - debug = 0; - return; - } - *p = '\0'; - fp->lines[fp->nxtiov].iov_base = p; - fp->lines[fp->nxtiov].iov_len = 2 * TR_STD_WIDTH; - fp->blen = 0; - } - - p = (char *)fp->lines[fp->nxtiov].iov_base + fp->blen++; - *p++ = c; - *p = 0; - - if (c != ' ' && c != '\t' && c != '\n') { - fp->lastc = c; - fp->supr = 0; - } - - if (c == '\n') { - fp->lines[fp->nxtiov++].iov_len = fp->blen; - fp->blen = 0; - fp->llen = 0; - fp->supr |= SUP_NL; +#ifdef DEBUG +void +trputc(int c) +{ + if (debug != 1 || !tracefile) return; - } - - if (c == '\t') - fp->llen |= 7; - fp->llen++; + putc(c, tracefile); } +#endif void -trace_flush(TFILE *fp, int all) +trace(const char *fmt, ...) { - int niov, i; - ssize_t written; +#ifdef DEBUG + va_list va; - niov = fp->nxtiov; - if (all && fp->blen > 0) { - fp->lines[niov].iov_len = fp->blen; - fp->blen = 0; - fp->llen = 0; - niov++; - } - if (niov == 0) - return; - if (fp->blen > 0 && --niov == 0) + if (debug != 1 || !tracefile) return; - written = writev(fp->tfd, fp->lines, niov); - for (i = 0; i < niov; i++) { - free(fp->lines[i].iov_base); - fp->lines[i].iov_base = NULL; - fp->lines[i].iov_len = 0; - } - if (written == -1) { - if (fp->blen > 0) { - free(fp->lines[niov].iov_base); - fp->lines[niov].iov_base = NULL; - fp->lines[niov].iov_len = 0; - } - debug = 0; - fp->blen = 0; - fp->llen = 0; - return; - } - if (fp->blen > 0) { - fp->lines[0].iov_base = fp->lines[niov].iov_base; - fp->lines[0].iov_len = fp->lines[niov].iov_len; - fp->lines[niov].iov_base = NULL; - fp->lines[niov].iov_len = 0; - } - fp->nxtiov = 0; + va_start(va, fmt); + (void) vfprintf(tracefile, fmt, va); + va_end(va); +#endif } void -trace_puts(const char *s, TFILE *fp) +tracev(const char *fmt, va_list va) { - char c; - - while ((c = *s++) != '\0') - trace_putc(c, fp); +#ifdef DEBUG + va_list ap; + if (debug != 1 || !tracefile) + return; + va_copy(ap, va); + (void) vfprintf(tracefile, fmt, ap); + va_end(ap); +#endif } -inline static char * -trace_id(TFILE *tf) -{ - int i; - char indent[16]; - char *p; - if (DFlags & DBG_NEST) { - p = indent; - for (i = 0; i < 6; i++) - *p++ = (i < ShNest) ? '#' : ' '; - while (i++ < ShNest && p < &indent[sizeof indent - 1]) - *p++ = '#'; - *p = '\0'; - } else - indent[0] = '\0'; - - if (DFlags & DBG_PID) { - i = getpid(); - (void) asprintf(&p, "%5d%c%s\t", i, - i == tf->pid ? ':' : '=', indent); - return p; - } else if (DFlags & DBG_NEST) { - *p++ = '\t'; - *p = '\0'; - (void) asprintf(&p, "%s\t", indent); - return p; - } - return NULL; +#ifdef DEBUG +void +trputs(const char *s) +{ + if (debug != 1 || !tracefile) + return; + fputs(s, tracefile); } -/* - * Used only from trargs(), which itself is used only to print - * arg lists (argv[]) either that were passed into this shell, or - * the arg list about to be given to some other command (incl - * builtins, and functions) as their argv[]. If any of the CTL* - * chars seem to appear, they really should be just treated as data, - * not special... But this is just debug, so, who cares! - */ + static void -trstring(const char *s) +trstring(char *s) { - const char *p; + char *p; char c; - TFILE *fp; - if (debug != 1 || !tracetfile) + if (debug != 1 || !tracefile) return; - fp = tracetfile; - trace_putc('"', fp); + putc('"', tracefile); for (p = s ; *p ; p++) { switch (*p) { case '\n': c = 'n'; goto backslash; @@ -969,22 +448,78 @@ trstring(const char *s) case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; case CTLBACKQ: c = 'q'; goto backslash; case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; - backslash: trace_putc('\\', fp); - trace_putc(c, fp); +backslash: putc('\\', tracefile); + putc(c, tracefile); break; default: if (*p >= ' ' && *p <= '~') - trace_putc(*p, fp); + putc(*p, tracefile); else { - trace_putc('\\', fp); - trace_putc(*p >> 6 & 03, fp); - trace_putc(*p >> 3 & 07, fp); - trace_putc(*p & 07, fp); + putc('\\', tracefile); + putc(*p >> 6 & 03, tracefile); + putc(*p >> 3 & 07, tracefile); + putc(*p & 07, tracefile); } break; } } - trace_putc('"', fp); + putc('"', tracefile); +} +#endif + + +void +trargs(char **ap) +{ +#ifdef DEBUG + if (debug != 1 || !tracefile) + return; + while (*ap) { + trstring(*ap++); + if (*ap) + putc(' ', tracefile); + else + putc('\n', tracefile); + } +#endif } + +#ifdef DEBUG +void +opentrace(void) +{ + char s[100]; +#ifdef O_APPEND + int flags; +#endif + + if (debug != 1) { + if (tracefile) + fflush(tracefile); + /* leave open because libedit might be using it */ + return; + } + snprintf(s, sizeof(s), "./trace.%d", (int)getpid()); + if (tracefile) { + if (!freopen(s, "a", tracefile)) { + fprintf(stderr, "Can't re-open %s\n", s); + tracefile = NULL; + debug = 0; + return; + } + } else { + if ((tracefile = fopen(s, "a")) == NULL) { + fprintf(stderr, "Can't open %s\n", s); + debug = 0; + return; + } + } +#ifdef O_APPEND + if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) + fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); +#endif + setlinebuf(tracefile); + fputs("\nTracing started.\n", tracefile); +} #endif /* DEBUG */ Index: src/bin/sh/show.h diff -u src/bin/sh/show.h:1.8 src/bin/sh/show.h:1.9 --- src/bin/sh/show.h:1.8 Thu Mar 16 13:09:06 2017 +++ src/bin/sh/show.h Thu Mar 16 13:21:59 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: show.h,v 1.8 2017/03/16 13:09:06 kre Exp $ */ +/* $NetBSD: show.h,v 1.9 2017/03/16 13:21:59 kre Exp $ */ /*- * Copyright (c) 1995 @@ -33,12 +33,12 @@ #include <stdarg.h> -#ifdef DEBUG union node; void showtree(union node *); void trace(const char *, ...); void tracev(const char *, va_list); void trargs(char **); +#ifdef DEBUG void trputc(int); void trputs(const char *); void opentrace(void);