Module Name:    src
Committed By:   kre
Date:           Tue Jan 22 13:48:28 UTC 2019

Modified Files:
        src/bin/sh: parser.c shell.h show.c

Log Message:
NFCI - DEBUG mode only change.

Add tracing of lexical analyser operations.   This is deliberately
kept out of the normal "all on" set as it makes a *lot* of noise
when enabled (especially in verbose mode) - but when needed, it
helps (evidence for which is coming soon).

As usual, no doc, you need the sources (and of course, a specially
built sh to even be able to enable it.)


To generate a diff of this commit:
cvs rdiff -u -r1.162 -r1.163 src/bin/sh/parser.c
cvs rdiff -u -r1.28 -r1.29 src/bin/sh/shell.h
cvs rdiff -u -r1.51 -r1.52 src/bin/sh/show.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/parser.c
diff -u src/bin/sh/parser.c:1.162 src/bin/sh/parser.c:1.163
--- src/bin/sh/parser.c:1.162	Mon Jan 21 14:24:44 2019
+++ src/bin/sh/parser.c	Tue Jan 22 13:48:28 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: parser.c,v 1.162 2019/01/21 14:24:44 kre Exp $	*/
+/*	$NetBSD: parser.c,v 1.163 2019/01/22 13:48:28 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
 #else
-__RCSID("$NetBSD: parser.c,v 1.162 2019/01/21 14:24:44 kre Exp $");
+__RCSID("$NetBSD: parser.c,v 1.163 2019/01/22 13:48:28 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -63,6 +63,9 @@ __RCSID("$NetBSD: parser.c,v 1.162 2019/
 #ifndef SMALL
 #include "myhistedit.h"
 #endif
+#ifdef DEBUG
+#include "nodenames.h"
+#endif
 
 /*
  * Shell command parser.
@@ -1072,6 +1075,9 @@ xxreadtoken(void)
 
 	if (tokpushback) {
 		tokpushback = 0;
+		CTRACE(DBG_LEXER,
+		    ("xxreadtoken() returns %s (%d) again\n",
+			tokname[lasttoken], lasttoken));
 		return lasttoken;
 	}
 	if (needprompt) {
@@ -1082,64 +1088,92 @@ xxreadtoken(void)
 	startlinno = plinno;
 	for (;;) {	/* until token or start of word found */
 		c = pgetc_macro();
+		CTRACE(DBG_LEXER, ("xxreadtoken() sees '%c' (%#.2x) ",
+		    c&0xFF, c&0x1FF));
 		switch (c) {
 		case ' ': case '\t': case PFAKE:
+			CTRACE(DBG_LEXER, (" ignored\n"));
 			continue;
 		case '#':
 			while ((c = pgetc()) != '\n' && c != PEOF)
 				continue;
+			CTRACE(DBG_LEXER,
+			    ("skipped comment to (not incl) \\n\n"));
 			pungetc();
 			continue;
 
 		case '\n':
 			plinno++;
+			CTRACE(DBG_LEXER, ("newline now @%d\n", plinno));
 			needprompt = doprompt;
 			RETURN(TNL);
 		case PEOF:
+			CTRACE(DBG_LEXER, ("EOF -> TEOF (return)\n"));
 			RETURN(TEOF);
 
 		case '&':
-			if (pgetc_linecont() == '&')
+			if (pgetc_linecont() == '&') {
+				CTRACE(DBG_LEXER,
+				    ("and another  -> TAND (return)\n"));
 				RETURN(TAND);
+			}
 			pungetc();
+			CTRACE(DBG_LEXER, (" -> TBACKGND (return)\n"));
 			RETURN(TBACKGND);
 		case '|':
-			if (pgetc_linecont() == '|')
+			if (pgetc_linecont() == '|') {
+				CTRACE(DBG_LEXER,
+				    ("and another  -> TOR (return)\n"));
 				RETURN(TOR);
+			}
 			pungetc();
+			CTRACE(DBG_LEXER, (" -> TPIPE (return)\n"));
 			RETURN(TPIPE);
 		case ';':
 			switch (pgetc_linecont()) {
 			case ';':
+				CTRACE(DBG_LEXER,
+				    ("and another -> TENDCASE (return)\n"));
 				RETURN(TENDCASE);
 			case '&':
+				CTRACE(DBG_LEXER,
+				    ("and '&' -> TCASEFALL (return)\n"));
 				RETURN(TCASEFALL);
 			default:
 				pungetc();
+				CTRACE(DBG_LEXER, (" -> TSEMI (return)\n"));
 				RETURN(TSEMI);
 			}
 		case '(':
+			CTRACE(DBG_LEXER, (" -> TLP (return)\n"));
 			RETURN(TLP);
 		case ')':
+			CTRACE(DBG_LEXER, (" -> TRP (return)\n"));
 			RETURN(TRP);
 
 		case '\\':
 			switch (pgetc()) {
 			case '\n':
 				startlinno = ++plinno;
+				CTRACE(DBG_LEXER, ("\\\n ignored, now @%d\n",
+				    plinno));
 				if (doprompt)
 					setprompt(2);
 				else
 					setprompt(0);
 				continue;
 			case PEOF:
+				CTRACE(DBG_LEXER,
+				  ("then EOF -> TEOF (return) '\\' dropped\n"));
 				RETURN(TEOF);
 			default:
+				CTRACE(DBG_LEXER, ("not \\\n or EOF: "));
 				pungetc();
 				break;
 			}
 			/* FALLTHROUGH */
 		default:
+			CTRACE(DBG_LEXER, ("getting a word\n"));
 			return readtoken1(c, BASESYNTAX, 0);
 		}
 	}
@@ -1359,6 +1393,8 @@ parsebackq(VSS *const stack, char * cons
 		cleanup_state_stack(stack);
 		parsebackquote = 0;
 		handler = savehandler;
+		CTRACE(DBG_LEXER, ("parsebackq() err (%d), unwinding\n",
+		    exception));
 		longjmp(handler->loc, 1);
 	}
 	INTOFF;
@@ -1380,7 +1416,8 @@ parsebackq(VSS *const stack, char * cons
 		char *pstr;
 		int line1 = plinno;
 
-		VTRACE(DBG_PARSE, ("parsebackq: repackaging `` as $( )"));
+		VTRACE(DBG_PARSE|DBG_LEXER,
+		    ("parsebackq: repackaging `` as $( )"));
 		/*
 		 * Because the entire `...` is read here, we don't
 		 * need to bother the state stack.  That will be used
@@ -1388,7 +1425,7 @@ parsebackq(VSS *const stack, char * cons
 		 */
 		STARTSTACKSTR(out);
 #ifdef DEBUG
-		for (psavelen = 0;;psavelen++) {
+		for (psavelen = 0;;psavelen++) {	/* } */
 #else
 		for (;;) {
 #endif
@@ -1397,44 +1434,58 @@ parsebackq(VSS *const stack, char * cons
 				needprompt = 0;
 			}
 			pc = pgetc();
+			VTRACE(DBG_LEXER,
+			    ("parsebackq() got '%c'(%#.2x) in `` %s", pc&0xFF,
+				pc&0x1FF, pc == '`' ? "terminator\n" : ""));
 			if (pc == '`')
 				break;
 			switch (pc) {
 			case '\\':
 				pc = pgetc();
+				VTRACE(DBG_LEXER, ("then '%c'(%#.2x) ",
+				    pc&0xFF, pc&0x1FF));
 #ifdef DEBUG
 				psavelen++;
 #endif
 				if (pc == '\n') {   /* keep \ \n for later */
 					plinno++;
+					VTRACE(DBG_LEXER, ("@%d ", plinno));
 					needprompt = doprompt;
 				}
 				if (pc != '\\' && pc != '`' && pc != '$'
-				    && (!ISDBLQUOTE() || pc != '"'))
+				    && (!ISDBLQUOTE() || pc != '"')) {
+					VTRACE(DBG_LEXER, ("keep '\\' "));
 					STPUTC('\\', out);
+				}
 				break;
 
 			case '\n':
 				plinno++;
+				VTRACE(DBG_LEXER, ("@%d ", plinno));
 				needprompt = doprompt;
 				break;
 
 			case PEOF:
 			        startlinno = line1;
+				VTRACE(DBG_LEXER, ("EOF\n", plinno));
 				synerror("EOF in backquote substitution");
  				break;
 
 			default:
 				break;
 			}
+			VTRACE(DBG_LEXER, (".\n", plinno));
 			STPUTC(pc, out);
 		}
 		STPUTC('\0', out);
-		VTRACE(DBG_PARSE, (" read %d", psavelen));
+		VTRACE(DBG_LEXER, ("parsebackq() ``:"));
+		VTRACE(DBG_PARSE|DBG_LEXER, (" read %d", psavelen));
 		psavelen = out - stackblock();
-		VTRACE(DBG_PARSE, (" produced %d\n", psavelen));
+		VTRACE(DBG_PARSE|DBG_LEXER, (" produced %d\n", psavelen));
 		if (psavelen > 0) {
 			pstr = grabstackstr(out);
+			CTRACE(DBG_LEXER, 
+			    ("parsebackq() reprocessing as $(%s)\n", pstr));
 			setinputstring(pstr, 1, line1);
 		}
 	}
@@ -1452,7 +1503,10 @@ parsebackq(VSS *const stack, char * cons
 		saveprompt = 0;
 
 	lno = -plinno;
+	CTRACE(DBG_LEXER, ("parsebackq() parsing embedded command list\n"));
 	n = list(0);
+	CTRACE(DBG_LEXER, ("parsebackq() parsed $() (%d -> %d)\n", -lno,
+	    lno + plinno));
 	lno += plinno;
 
 	if (oldstyle) {
@@ -1468,6 +1522,7 @@ parsebackq(VSS *const stack, char * cons
 		 * Start reading from old file again, ignoring any pushed back
 		 * tokens left from the backquote parsing
 		 */
+		CTRACE(DBG_LEXER, ("parsebackq() back to previous input\n"));
 		popfile();
 		tokpushback = 0;
 	}
@@ -1514,10 +1569,12 @@ parseredir(const char *out,  int c)
 	fd = (*out == '\0') ? -1 : number(out);
 
 	np = stalloc(sizeof(struct nfile));
+	VTRACE(DBG_LEXER, ("parseredir after '%s%c' ", out, c));
 	if (c == '>') {
 		if (fd < 0)
 			fd = 1;
 		c = pgetc_linecont();
+		VTRACE(DBG_LEXER, ("is '%c'(%#.2x) ", c&0xFF, c&0x1FF));
 		if (c == '>')
 			np->type = NAPPEND;
 		else if (c == '|')
@@ -1526,12 +1583,15 @@ parseredir(const char *out,  int c)
 			np->type = NTOFD;
 		else {
 			np->type = NTO;
+			VTRACE(DBG_LEXER, ("unwanted ", c));
 			pungetc();
 		}
 	} else {	/* c == '<' */
 		if (fd < 0)
 			fd = 0;
-		switch (c = pgetc_linecont()) {
+		c = pgetc_linecont();
+		VTRACE(DBG_LEXER, ("is '%c'(%#.2x) ", c&0xFF, c&0x1FF));
+		switch (c) {
 		case '<':
 			if (sizeof (struct nfile) != sizeof (struct nhere)) {
 				np = stalloc(sizeof(struct nhere));
@@ -1542,6 +1602,8 @@ parseredir(const char *out,  int c)
 			heredoc->here = np;
 			heredoc->startline = plinno;
 			if ((c = pgetc_linecont()) == '-') {
+				CTRACE(DBG_LEXER, ("and '%c'(%#.2x) ",
+				    c & 0xFF, c & 0x1FF));
 				heredoc->striptabs = 1;
 			} else {
 				heredoc->striptabs = 0;
@@ -1559,12 +1621,16 @@ parseredir(const char *out,  int c)
 
 		default:
 			np->type = NFROM;
+			VTRACE(DBG_LEXER, ("unwanted('%c'0#.2x)", c&0xFF,
+			    c&0x1FF));
 			pungetc();
 			break;
 		}
 	}
 	np->nfile.fd = fd;
 
+	VTRACE(DBG_LEXER, (" ->%"PRIdsNT" fd=%d\n", NODETYPENAME(np->type),fd));
+
 	redirnode = np;		/* this is the "value" of TRENODE */
 }
 
@@ -1579,12 +1645,14 @@ readcstyleesc(char *out)
 	unsigned int v;
 
 	c = pgetc();
+	VTRACE(DBG_LEXER, ("CSTR(\\%c)(\\%#x)", c&0xFF, c&0x1FF));
 	switch (c) {
 	case '\0':
 	case PEOF:
 		synerror("Unterminated quoted string");
 	case '\n':
 		plinno++;
+		VTRACE(DBG_LEXER, ("@%d ", plinno));
 		if (doprompt)
 			setprompt(2);
 		else
@@ -1689,6 +1757,7 @@ readcstyleesc(char *out)
 		synerror("Unknown $'' escape sequence");
 	}
 	vc = (char)v;
+	VTRACE(DBG_LEXER, ("->%u(%#x)['%c']", v, v, vc&0xFF));
 
 	/*
 	 * If we managed to create a \n from a \ sequence (no matter how)
@@ -1697,6 +1766,7 @@ readcstyleesc(char *out)
 	 * causes LINENO increments.
 	 */
 	if (vc == '\n') {
+		VTRACE(DBG_LEXER, ("CTLCNL."));
 		USTPUTC(CTLCNL, out);
 		return out;
 	}
@@ -1706,6 +1776,7 @@ readcstyleesc(char *out)
 	 * POSIX says we should skip till the closing quote.
 	 */
 	if (vc == '\0') {
+		CTRACE(DBG_LEXER, ("\\0: skip to '", v, v, vc&0xFF));
 		while ((c = pgetc()) != '\'') {
 			if (c == '\\')
 				c = pgetc();
@@ -1722,6 +1793,8 @@ readcstyleesc(char *out)
 		pungetc();
 		return out;
 	}
+	CVTRACE(DBG_LEXER, NEEDESC(vc), ("CTLESC-"));
+	VTRACE(DBG_LEXER, ("'%c'(%#.2x)", vc&0xFF, vc&0x1FF));
 	if (NEEDESC(vc))
 		USTPUTC(CTLESC, out);
 	USTPUTC(vc, out);
@@ -1759,6 +1832,14 @@ readtoken1(int firstc, char const *syn, 
 
 	syntax = syn;
 
+#ifdef DEBUG
+#define SYNTAX      (	syntax == BASESYNTAX ? "BASE"	:		\
+			syntax == DQSYNTAX   ? "DQ"	:		\
+			syntax == SQSYNTAX   ? "SQ"	:		\
+			syntax == ARISYNTAX  ? "ARI"	:		\
+					"???"			)
+#endif
+
 	startlinno = plinno;
 	varnest = 0;
 	quoted = 0;
@@ -1770,6 +1851,10 @@ readtoken1(int firstc, char const *syn, 
 	parenlevel = 0;
 	elided_nl = 0;
 
+	CTRACE(DBG_LEXER, ("readtoken1(%c) syntax=%s %s%s(quoted=%x)\n",
+	    firstc&0xFF, SYNTAX, magicq ? "magic quotes" : "",
+	    ISDBLQUOTE()?" ISDBLQUOTE":"", quoted));
+
 	STARTSTACKSTR(out);
 
 	for (c = firstc ;; c = pgetc_macro()) {	/* until of token */
@@ -1778,14 +1863,18 @@ readtoken1(int firstc, char const *syn, 
 		CHECKSTRSPACE(6, out);	/* permit 6 calls to USTPUTC */
 		switch (syntax[c]) {
 		case CFAKE:
+			VTRACE(DBG_LEXER, ("CFAKE"));
 			if (syntax == BASESYNTAX && varnest == 0)
 				break;
+			VTRACE(DBG_LEXER, (","));
 			continue;
 		case CNL:	/* '\n' */
+			VTRACE(DBG_LEXER, ("CNL"));
 			if (syntax == BASESYNTAX && varnest == 0)
 				break;	/* exit loop */
 			USTPUTC(c, out);
 			plinno++;
+			VTRACE(DBG_LEXER, ("@%d,", plinno));
 			if (doprompt)
 				setprompt(2);
 			else
@@ -1797,20 +1886,27 @@ readtoken1(int firstc, char const *syn, 
 				out = readcstyleesc(out);
 				continue;
 			}
+			VTRACE(DBG_LEXER, ("ESC:"));
 			USTPUTC(CTLESC, out);
 			/* FALLTHROUGH */
 		case CWORD:
+			VTRACE(DBG_LEXER, ("'%c'", c));
 			USTPUTC(c, out);
 			continue;
 
 		case CCTL:
+			CVTRACE(DBG_LEXER, !magicq || ISDBLQUOTE(),
+			    ("%s%sESC:",!magicq?"!m":"",ISDBLQUOTE()?"DQ":""));
 			if (!magicq || ISDBLQUOTE())
 				USTPUTC(CTLESC, out);
+			VTRACE(DBG_LEXER, ("'%c'", c));
 			USTPUTC(c, out);
 			continue;
 		case CBACK:	/* backslash */
 			c = pgetc();
+			VTRACE(DBG_LEXER, ("\\'%c'(%#.2x)", c&0xFF, c&0x1FF));
 			if (c == PEOF) {
+				VTRACE(DBG_LEXER, ("EOF, keep \\ "));
 				USTPUTC('\\', out);
 				pungetc();
 				continue;
@@ -1818,12 +1914,15 @@ readtoken1(int firstc, char const *syn, 
 			if (c == '\n') {
 				plinno++;
 				elided_nl++;
+				VTRACE(DBG_LEXER, ("eli \\n (%d) @%d ",
+				    elided_nl, plinno));
 				if (doprompt)
 					setprompt(2);
 				else
 					setprompt(0);
 				continue;
 			}
+			CVTRACE(DBG_LEXER, quotef==0, (" QF=1 "));
 			quotef = 1;	/* current token is quoted */
 			if (ISDBLQUOTE() && c != '\\' && c != '`' &&
 			    c != '$' && (c != '"' || magicq)) {
@@ -1834,9 +1933,13 @@ readtoken1(int firstc, char const *syn, 
 				 * Otherwise the \ has done its work, and
 				 * is dropped.
 				 */
+				VTRACE(DBG_LEXER, ("ESC:'\\'"));
 				USTPUTC(CTLESC, out);
 				USTPUTC('\\', out);
 			}
+			CVTRACE(DBG_LEXER, NEEDESC(c) || !magicq,
+			    ("%sESC:", NEEDESC(c) ? "+" : "m"));
+			VTRACE(DBG_LEXER, ("'%c'(%#.2x)", c&0xFF, c&0x1FF));
 			if (NEEDESC(c))
 				USTPUTC(CTLESC, out);
 			else if (!magicq) {
@@ -1848,36 +1951,51 @@ readtoken1(int firstc, char const *syn, 
 			continue;
 		case CSQUOTE:
 			if (syntax != SQSYNTAX) {
+				CVTRACE(DBG_LEXER, !magicq, (" CQM "));
 				if (!magicq)
 					USTPUTC(CTLQUOTEMARK, out);
+				CVTRACE(DBG_LEXER, quotef==0, (" QF=1 "));
 				quotef = 1;
 				TS_PUSH();
 				syntax = SQSYNTAX;
 				quoted = SQ;
+				VTRACE(DBG_LEXER, (" TS_PUSH(SQ)"));
 				continue;
 			}
 			if (magicq && arinest == 0 && varnest == 0) {
 				/* Ignore inside quoted here document */
+				VTRACE(DBG_LEXER, ("<<'>>"));
 				USTPUTC(c, out);
 				continue;
 			}
 			/* End of single quotes... */
 			TS_POP();
+			VTRACE(DBG_LEXER, ("SQ TS_POP->%s ", SYNTAX));
+			CVTRACE(DBG_LEXER, syntax == BASESYNTAX, (" CQE "));
 			if (syntax == BASESYNTAX)
 				USTPUTC(CTLQUOTEEND, out);
 			continue;
 		case CDQUOTE:
 			if (magicq && arinest == 0 && varnest == 0) {
+				VTRACE(DBG_LEXER, ("<<\">>"));
 				/* Ignore inside here document */
 				USTPUTC(c, out);
 				continue;
 			}
+			CVTRACE(DBG_LEXER, quotef==0, (" QF=1 "));
 			quotef = 1;
 			if (arinest) {
 				if (ISDBLQUOTE()) {
+					VTRACE(DBG_LEXER,
+					    (" CQE ari(%d", arinest));
 					USTPUTC(CTLQUOTEEND, out);
 					TS_POP();
+					VTRACE(DBG_LEXER, ("%d)TS_POP->%s ",
+					    arinest, SYNTAX));
 				} else {
+					VTRACE(DBG_LEXER,
+					  (" ari(%d) %s TS_PUSH->DQ CQM ",
+					   arinest, SYNTAX));
 					TS_PUSH();
 					syntax = DQSYNTAX;
 					SETDBLQUOTE();
@@ -1885,12 +2003,17 @@ readtoken1(int firstc, char const *syn, 
 				}
 				continue;
 			}
+			CVTRACE(DBG_LEXER, magicq, (" MQignDQ "));
 			if (magicq)
 				continue;
 			if (ISDBLQUOTE()) {
 				TS_POP();
+				VTRACE(DBG_LEXER,
+				    (" DQ TS_POP->%s CQE ", SYNTAX));
 				USTPUTC(CTLQUOTEEND, out);
 			} else {
+				VTRACE(DBG_LEXER,
+				    (" %s TS_POP->DQ CQM ", SYNTAX));
 				TS_PUSH();
 				syntax = DQSYNTAX;
 				SETDBLQUOTE();
@@ -1898,27 +2021,34 @@ readtoken1(int firstc, char const *syn, 
 			}
 			continue;
 		case CVAR:	/* '$' */
+			VTRACE(DBG_LEXER, ("'$'..."));
 			out = insert_elided_nl(out);
 			PARSESUB();		/* parse substitution */
 			continue;
 		case CENDVAR:	/* CLOSEBRACE */
 			if (varnest > 0 && !ISDBLQUOTE()) {
+				VTRACE(DBG_LEXER, ("vn=%d !DQ", varnest));
 				TS_POP();
+				VTRACE(DBG_LEXER, (" TS_POP->%s CEV ", SYNTAX));
 				USTPUTC(CTLENDVAR, out);
 			} else {
+				VTRACE(DBG_LEXER, ("'%c'", c));
 				USTPUTC(c, out);
 			}
 			out = insert_elided_nl(out);
 			continue;
 		case CLP:	/* '(' in arithmetic */
 			parenlevel++;
+			VTRACE(DBG_LEXER, ("'('(%d)", parenlevel));
 			USTPUTC(c, out);
 			continue;;
 		case CRP:	/* ')' in arithmetic */
 			if (parenlevel > 0) {
 				USTPUTC(c, out);
 				--parenlevel;
+				VTRACE(DBG_LEXER, ("')'(%d)", parenlevel));
 			} else {
+				VTRACE(DBG_LEXER, ("')'(%d)", parenlevel));
 				if (pgetc_linecont() == /*(*/ ')') {
 					out = insert_elided_nl(out);
 					if (--arinest == 0) {
@@ -1940,16 +2070,22 @@ readtoken1(int firstc, char const *syn, 
 			}
 			continue;
 		case CBQUOTE:	/* '`' */
+			VTRACE(DBG_LEXER, ("'`' -> parsebackq()\n"));
 			out = parsebackq(stack, out, &bqlist, 1, magicq);
+			VTRACE(DBG_LEXER, ("parsebackq() -> readtoken1: "));
 			continue;
 		case CEOF:		/* --> c == PEOF */
+			VTRACE(DBG_LEXER, ("EOF "));
 			break;		/* will exit loop */
 		default:
+			VTRACE(DBG_LEXER, ("['%c'(%#.2x)]", c&0xFF, c&0x1FF));
 			if (varnest == 0 && !ISDBLQUOTE())
 				break;	/* exit loop */
 			USTPUTC(c, out);
+			VTRACE(DBG_LEXER, (","));
 			continue;
 		}
+		VTRACE(DBG_LEXER, (" END TOKEN\n", c&0xFF, c&0x1FF));
 		break;	/* break from switch -> break from for loop too */
 	}
 
@@ -1983,7 +2119,7 @@ readtoken1(int firstc, char const *syn, 
 		}
 	}
 
-	VTRACE(DBG_PARSE,
+	VTRACE(DBG_PARSE|DBG_LEXER,
 	    ("readtoken1 %sword \"%s\", completed%s (%d) left %d enl\n",
 	    (quotef ? "quoted " : ""), out, (bqlist ? " with cmdsubs" : ""),
 	    len, elided_nl));
@@ -2010,16 +2146,21 @@ parsesub: {
 	static const char types[] = "}-+?=";
 
 	c = pgetc_linecont();
+	VTRACE(DBG_LEXER, ("\"$%c\"(%#.2x)", c&0xFF, c&0x1FF));
 	if (c == '(' /*)*/) {	/* $(command) or $((arith)) */
 		if (pgetc_linecont() == '(' /*')'*/ ) {
+			VTRACE(DBG_LEXER, ("\"$((\" ARITH "));
 			out = insert_elided_nl(out);
 			PARSEARITH();
 		} else {
+			VTRACE(DBG_LEXER, ("\"$(\" CSUB->parsebackq()\n"));
 			out = insert_elided_nl(out);
 			pungetc();
 			out = parsebackq(stack, out, &bqlist, 0, magicq);
+			VTRACE(DBG_LEXER, ("parseback()->readtoken1(): "));
 		}
 	} else if (c == OPENBRACE || is_name(c) || is_special(c)) {
+		VTRACE(DBG_LEXER, (" $EXP:CTLVAR "));
 		USTPUTC(CTLVAR, out);
 		typeloc = out - stackblock();
 		USTPUTC(VSNORMAL, out);
@@ -2064,13 +2205,16 @@ parsesub: {
 			}
 			else
 				subtype = 0;
+			VTRACE(DBG_LEXER, ("${ st=%d ", subtype));
 		}
 		if (is_name(c)) {
 			p = out;
 			do {
+				VTRACE(DBG_LEXER, ("%c", c));
 				STPUTC(c, out);
 				c = pgetc_linecont();
 			} while (is_in_name(c));
+
 #if 0
 			if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) {
 				int i;
@@ -2095,15 +2239,18 @@ parsesub: {
 #endif
 		} else if (is_digit(c)) {
 			do {
+				VTRACE(DBG_LEXER, ("%c", c));
 				STPUTC(c, out);
 				c = pgetc_linecont();
 			} while (subtype != VSNORMAL && is_digit(c));
 		}
 		else if (is_special(c)) {
+			VTRACE(DBG_LEXER, ("\"$%c", c));
 			USTPUTC(c, out);
 			c = pgetc_linecont();
 		}
 		else {
+			VTRACE(DBG_LEXER, ("\"$%c(%#.2x)??\n", c&0xFF,c&0x1FF));
  badsub:
 			cleanup_state_stack(stack);
 			synerror("Bad substitution");
@@ -2145,6 +2292,7 @@ parsesub: {
 			flags |= VSQUOTE;
 		if (subtype >= VSTRIMLEFT && subtype <= VSTRIMRIGHTMAX)
 			flags |= VSPATQ;
+		VTRACE(DBG_LEXER, (" st%d:%x", subtype, flags));
 		*(stackblock() + typeloc) = subtype | flags;
 		if (subtype != VSNORMAL) {
 			TS_PUSH();
@@ -2154,14 +2302,21 @@ parsesub: {
 				syntax = BASESYNTAX;
 				quoted = 0;
 			}
+			VTRACE(DBG_LEXER, (" TS_PUSH->%s vn=%d%s ",
+			    SYNTAX, varnest, quoted ? " Q" : ""));
 		}
 	} else if (c == '\'' && syntax == BASESYNTAX) {
 		USTPUTC(CTLQUOTEMARK, out);
+		VTRACE(DBG_LEXER, (" CSTR \"$'\" CQM "));
+		CVTRACE(DBG_LEXER, quotef==0, ("QF=1 "));
 		quotef = 1;
 		TS_PUSH();
 		syntax = SQSYNTAX;
 		quoted = CQ;
+		VTRACE(DBG_LEXER, ("%s->TS_PUSH()->SQ ", SYNTAX));
 	} else {
+		VTRACE(DBG_LEXER, ("$unk -> '$' (pushback '%c'%#.2x)",
+			c & 0xFF, c & 0x1FF));
 		USTPUTC('$', out);
 		pungetc();
 	}
@@ -2192,12 +2347,14 @@ parsearith: {
 	} else
 #endif
 	{
+		VTRACE(DBG_LEXER, (" CTLARI%c ", ISDBLQUOTE()?'"':'_'));
 		USTPUTC(CTLARI, out);
 		if (ISDBLQUOTE())
 			USTPUTC('"',out);
 		else
 			USTPUTC(' ',out);
 
+		VTRACE(DBG_LEXER, ("%s->TS_PUSH->ARI(1)", SYNTAX));
 		TS_PUSH();
 		syntax = ARISYNTAX;
 		arinest = 1;
@@ -2370,6 +2527,8 @@ pgetc_linecont(void)
 		if (c == '\n') {
 			plinno++;
 			elided_nl++;
+			VTRACE(DBG_LEXER, ("\"\\n\"drop(el=%d@%d)",
+			    elided_nl, plinno));
 			if (doprompt)
 				setprompt(2);
 			else

Index: src/bin/sh/shell.h
diff -u src/bin/sh/shell.h:1.28 src/bin/sh/shell.h:1.29
--- src/bin/sh/shell.h:1.28	Mon Jan 21 14:29:12 2019
+++ src/bin/sh/shell.h	Tue Jan 22 13:48:28 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: shell.h,v 1.28 2019/01/21 14:29:12 kre Exp $	*/
+/*	$NetBSD: shell.h,v 1.29 2019/01/22 13:48:28 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -179,10 +179,11 @@ extern	int		ShNest;
 #define	DBG_HISTORY	(1LL << 16)		/* h */
 #define	DBG_SIG		(1LL << 17)		/* s */
 #define	DBG_MATCH	(1LL << 18)		/* g (glob) */
+#define	DBG_LEXER	(1LL << 19)		/* l */
 
 /*
- * reserved extras: b=builtins l=alias
- * still free:  d k n q u y
+ * reserved extras: b=builtins y=alias
+ * still free:  d k n q u
  */
 
 	/* use VTRACE(DBG_ALWAYS, (...)) to test this one */

Index: src/bin/sh/show.c
diff -u src/bin/sh/show.c:1.51 src/bin/sh/show.c:1.52
--- src/bin/sh/show.c:1.51	Mon Jan 21 14:29:12 2019
+++ src/bin/sh/show.c	Tue Jan 22 13:48:28 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: show.c,v 1.51 2019/01/21 14:29:12 kre Exp $	*/
+/*	$NetBSD: show.c,v 1.52 2019/01/22 13:48:28 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: show.c,v 1.51 2019/01/21 14:29:12 kre Exp $");
+__RCSID("$NetBSD: show.c,v 1.52 2019/01/22 13:48:28 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -1063,6 +1063,7 @@ static struct debug_flag {
 	{ 'h',	DBG_HISTORY	},	/* history & cmd line editing */
 	{ 'i',	DBG_INPUT	},	/* shell input routines */
 	{ 'j',	DBG_JOBS	},	/* job control, structures */
+	{ 'l',	DBG_LEXER	},	/* lexical analysis */
 	{ 'm',	DBG_MEM		},	/* memory management */
 	{ 'o',	DBG_OUTPUT	},	/* output routines */
 	{ 'p',	DBG_PROCS	},	/* process management, fork, ... */
@@ -1083,7 +1084,7 @@ static struct debug_flag {
 	{ '$',	DBG_PID		},	/* prefix trace lines with sh pid */
 	{ '^',	DBG_NEST	},	/* show shell nesting level */
 
-			/* alpha options only */
+			/* alpha options only - but not DBG_LEXER */
 	{ '_',	DBG_PARSE | DBG_EVAL | DBG_EXPAND | DBG_JOBS | DBG_SIG |
 		    DBG_PROCS | DBG_REDIR | DBG_CMDS | DBG_ERRS |
 		    DBG_WAIT | DBG_TRAP | DBG_VARS | DBG_MEM | DBG_MATCH |

Reply via email to