Sun Mar 27 14:34:46 2016 UTC ()
General KNF and source code cleanups, avoid scattering the
magic string " \t\n" all over the place, slightly improved
syntax error messages, restructured some of the code for
clarity, don't allow IFS to be imported through the environment,
and remove the (never) conditionally compiled ATTY option.
Apart from one or two syntax error messages, and ignoring IFS
if present in the environment, this is intended to have no
user visible changes. (from kre@)


(christos)
diff -r1.97 -r1.98 src/bin/sh/expand.c
diff -r1.47 -r1.48 src/bin/sh/input.c
diff -r1.47 -r1.48 src/bin/sh/var.c
diff -r1.62 -r1.63 src/bin/sh/main.c
diff -r1.6 -r1.7 src/bin/sh/mkinit.sh
diff -r1.2 -r1.3 src/bin/sh/mknodenames.sh
diff -r1.107 -r1.108 src/bin/sh/parser.c
diff -r1.26 -r1.27 src/bin/sh/var.h

cvs diff -r1.97 -r1.98 src/bin/sh/expand.c (expand / switch to context diff)
--- src/bin/sh/expand.c 2016/03/16 15:44:35 1.97
+++ src/bin/sh/expand.c 2016/03/27 14:34:46 1.98
@@ -1,4 +1,4 @@
-/*	$NetBSD: expand.c,v 1.97 2016/03/16 15:44:35 christos Exp $	*/
+/*	$NetBSD: expand.c,v 1.98 2016/03/27 14:34:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
 #else
-__RCSID("$NetBSD: expand.c,v 1.97 2016/03/16 15:44:35 christos Exp $");
+__RCSID("$NetBSD: expand.c,v 1.98 2016/03/27 14:34:46 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -193,7 +193,7 @@
 	int ifs_split = EXP_IFS_SPLIT;
 
 	if (flag & EXP_IFS_SPLIT)
-		ifs = ifsset() ? ifsval() : " \t\n";
+		ifs = ifsval();
 
 	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
 		p = exptilde(p, flag);
@@ -705,7 +705,6 @@
 						STPUTC(CTLESC, expdest);
 					STPUTC(*val++, expdest);
 				}
-
 			}
 		}
 	}
@@ -924,10 +923,7 @@
 		}
 		/* fall through */
 	case '*':
-		if (ifsset() != 0)
-			sep = ifsval()[0];
-		else
-			sep = ' ';
+		sep = ifsval()[0];
 		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
 			STRTODEST(p);
 			if (*ap && sep)
@@ -1011,7 +1007,7 @@
 		return;
 	}
 
-	ifs = ifsset() ? ifsval() : " \t\n";
+	ifs = ifsval();
 
 	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
 		p = string + ifsp->begoff;

cvs diff -r1.47 -r1.48 src/bin/sh/input.c (expand / switch to context diff)
--- src/bin/sh/input.c 2016/01/04 03:00:24 1.47
+++ src/bin/sh/input.c 2016/03/27 14:34:46 1.48
@@ -1,4 +1,4 @@
-/*	$NetBSD: input.c,v 1.47 2016/01/04 03:00:24 christos Exp $	*/
+/*	$NetBSD: input.c,v 1.48 2016/03/27 14:34:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
 #else
-__RCSID("$NetBSD: input.c,v 1.47 2016/01/04 03:00:24 christos Exp $");
+__RCSID("$NetBSD: input.c,v 1.48 2016/03/27 14:34:46 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -453,6 +453,7 @@
 void
 setinputstring(char *string, int push)
 {
+
 	INTOFF;
 	if (push)
 		pushfile();

cvs diff -r1.47 -r1.48 src/bin/sh/var.c (expand / switch to context diff)
--- src/bin/sh/var.c 2016/03/08 23:24:51 1.47
+++ src/bin/sh/var.c 2016/03/27 14:34:46 1.48
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.47 2016/03/08 23:24:51 christos Exp $	*/
+/*	$NetBSD: var.c,v 1.48 2016/03/27 14:34:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: var.c,v 1.47 2016/03/08 23:24:51 christos Exp $");
+__RCSID("$NetBSD: var.c,v 1.48 2016/03/27 14:34:46 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -87,9 +87,6 @@
 
 struct localvar *localvars;
 
-#if ATTY
-struct var vatty;
-#endif
 #ifndef SMALL
 struct var vhistsize;
 struct var vterm;
@@ -103,11 +100,9 @@
 struct var vps4;
 struct var voptind;
 
+char ifs_default[] = " \t\n";
+
 const struct varinit varinit[] = {
-#if ATTY
-	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
-	  NULL },
-#endif
 #ifndef SMALL
 	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
 	  sethistsize },
@@ -162,13 +157,14 @@
 		}
 	}
 
-
 	/*
 	 * PPID is readonly
 	 *	set after processing environ to override anything there
+	 * Always default IFS, ignore any value from environment.
 	 */
 	snprintf(buf, sizeof(buf), "%d", (int)getppid());
 	setvar("PPID", buf, VREADONLY);
+	setvar("IFS", ifs_default, VTEXTFIXED);
 }
 #endif
 

cvs diff -r1.62 -r1.63 src/bin/sh/main.c (expand / switch to context diff)
--- src/bin/sh/main.c 2016/03/01 21:10:40 1.62
+++ src/bin/sh/main.c 2016/03/27 14:34:46 1.63
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.62 2016/03/01 21:10:40 martin Exp $	*/
+/*	$NetBSD: main.c,v 1.63 2016/03/27 14:34:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)main.c	8.7 (Berkeley) 7/19/95";
 #else
-__RCSID("$NetBSD: main.c,v 1.62 2016/03/01 21:10:40 martin Exp $");
+__RCSID("$NetBSD: main.c,v 1.63 2016/03/27 14:34:46 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -150,11 +150,7 @@
 				exitshell(exitstatus);
 		}
 		reset();
-		if (exception == EXINT
-#if ATTY
-		 && (! attyset() || equal(termval(), "emacs"))
-#endif
-		 ) {
+		if (exception == EXINT) {
 			out2c('\n');
 			flushout(&errout);
 		}

cvs diff -r1.6 -r1.7 src/bin/sh/mkinit.sh (expand / switch to context diff)
--- src/bin/sh/mkinit.sh 2016/03/08 23:23:31 1.6
+++ src/bin/sh/mkinit.sh 2016/03/27 14:34:46 1.7
@@ -1,5 +1,5 @@
 #! /bin/sh
-#	$NetBSD: mkinit.sh,v 1.6 2016/03/08 23:23:31 christos Exp $
+#	$NetBSD: mkinit.sh,v 1.7 2016/03/27 14:34:46 christos Exp $
 
 # Copyright (c) 2003 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -55,7 +55,7 @@
 			IFS=' 	'
 			set -- $line
 			# ignore duplicates
-			[ "${includes}" != "${includes%* $2 *}" ] && continue
+			[ "${includes}" != "${includes% $2 *}" ] && continue
 			includes="$includes$2 "
 			continue
 			;;

cvs diff -r1.2 -r1.3 src/bin/sh/mknodenames.sh (expand / switch to context diff)
--- src/bin/sh/mknodenames.sh 2016/02/27 18:34:12 1.2
+++ src/bin/sh/mknodenames.sh 2016/03/27 14:34:46 1.3
@@ -7,7 +7,7 @@
 
 NODES=$1
 
-test -t 1 && exec > nodenames.h
+test -t 1 && -z "$2" && exec > nodenames.h
 
 echo "#ifdef DEBUG"
 echo '

cvs diff -r1.107 -r1.108 src/bin/sh/parser.c (expand / switch to context diff)
--- src/bin/sh/parser.c 2016/03/21 02:37:26 1.107
+++ src/bin/sh/parser.c 2016/03/27 14:34:46 1.108
@@ -1,4 +1,4 @@
-/*	$NetBSD: parser.c,v 1.107 2016/03/21 02:37:26 christos Exp $	*/
+/*	$NetBSD: parser.c,v 1.108 2016/03/27 14:34:46 christos 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.107 2016/03/21 02:37:26 christos Exp $");
+__RCSID("$NetBSD: parser.c,v 1.108 2016/03/27 14:34:46 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -117,13 +117,14 @@
 STATIC int xxreadtoken(void);
 STATIC int readtoken1(int, char const *, char *, int);
 STATIC int noexpand(char *);
-STATIC void synexpect(int) __dead;
+STATIC void synexpect(int, const char *) __dead;
 STATIC void synerror(const char *) __dead;
 STATIC void setprompt(int);
 
 
 static const char EOFhere[] = "EOF reading here (<<) document";
 
+
 /*
  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
  * valid parse tree indicating a blank line.)
@@ -156,7 +157,7 @@
 {
 	union node *n1, *n2, *n3;
 	int tok;
-	TRACE(("list: entered\n"));
+	TRACE(("list(%d,%d): entered\n", nlflag, erflag));
 
 	checkkwd = 2;
 	if (nlflag == 0 && tokendlist[peektoken()])
@@ -192,7 +193,7 @@
 		case TBACKGND:
 		case TSEMI:
 			tok = readtoken();
-			/* fall through */
+			/* FALLTHROUGH */
 		case TNL:
 			if (tok == TNL) {
 				parseheredoc();
@@ -209,19 +210,17 @@
 			if (heredoclist)
 				parseheredoc();
 			else
-				pungetc();		/* push back EOF on input */
+				pungetc();	/* push back EOF on input */
 			return n1;
 		default:
 			if (nlflag || erflag)
-				synexpect(-1);
+				synexpect(-1, 0);
 			tokpushback++;
 			return n1;
 		}
 	}
 }
 
-
-
 STATIC union node *
 andor(void)
 {
@@ -248,8 +247,6 @@
 	}
 }
 
-
-
 STATIC union node *
 pipeline(void)
 {
@@ -332,7 +329,7 @@
 		n1->type = NIF;
 		n1->nif.test = list(0, 0);
 		if (readtoken() != TTHEN)
-			synexpect(TTHEN);
+			synexpect(TTHEN, 0);
 		n1->nif.ifpart = list(0, 0);
 		n2 = n1;
 		while (readtoken() == TELIF) {
@@ -341,7 +338,7 @@
 			n2->type = NIF;
 			n2->nif.test = list(0, 0);
 			if (readtoken() != TTHEN)
-				synexpect(TTHEN);
+				synexpect(TTHEN, 0);
 			n2->nif.ifpart = list(0, 0);
 		}
 		if (lasttoken == TELSE)
@@ -351,7 +348,7 @@
 			tokpushback++;
 		}
 		if (readtoken() != TFI)
-			synexpect(TFI);
+			synexpect(TFI, 0);
 		checkkwd = 1;
 		break;
 	case TWHILE:
@@ -362,11 +359,11 @@
 		n1->nbinary.ch1 = list(0, 0);
 		if ((got=readtoken()) != TDO) {
 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
-			synexpect(TDO);
+			synexpect(TDO, 0);
 		}
 		n1->nbinary.ch2 = list(0, 0);
 		if (readtoken() != TDONE)
-			synexpect(TDONE);
+			synexpect(TDONE, 0);
 		checkkwd = 1;
 		break;
 	}
@@ -389,7 +386,7 @@
 			*app = NULL;
 			n1->nfor.args = ap;
 			if (lasttoken != TNL && lasttoken != TSEMI)
-				synexpect(-1);
+				synexpect(-1, 0);
 		} else {
 			static char argvars[5] = {
 			    CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
@@ -413,17 +410,17 @@
 		else if (t == TBEGIN)
 			t = TEND;
 		else
-			synexpect(-1);
+			synexpect(-1, 0);
 		n1->nfor.body = list(0, 0);
 		if (readtoken() != t)
-			synexpect(t);
+			synexpect(t, 0);
 		checkkwd = 1;
 		break;
 	case TCASE:
 		n1 = stalloc(sizeof(struct ncase));
 		n1->type = NCASE;
 		if (readtoken() != TWORD)
-			synexpect(TWORD);
+			synexpect(TWORD, 0);
 		n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
 		n2->type = NARG;
 		n2->narg.text = wordtext;
@@ -431,7 +428,7 @@
 		n2->narg.next = NULL;
 		while (readtoken() == TNL);
 		if (lasttoken != TWORD || ! equal(wordtext, "in"))
-			synerror("expecting \"in\"");
+			synexpect(-1, "in");
 		cpp = &n1->ncase.cases;
 		noalias = 1;
 		checkkwd = 2, readtoken();
@@ -464,7 +461,7 @@
 			ap->narg.next = NULL;
 			noalias = 0;
 			if (lasttoken != TRP) {
-				synexpect(TRP);
+				synexpect(TRP, 0);
 			}
 			cp->nclist.body = list(0, 0);
 
@@ -472,7 +469,7 @@
 			if ((t = readtoken()) != TESAC) {
 				if (t != TENDCASE) {
 					noalias = 0;
-					synexpect(TENDCASE);
+					synexpect(TENDCASE, 0);
 				} else {
 					noalias = 1;
 					checkkwd = 2;
@@ -491,13 +488,13 @@
 		n1->nredir.n = list(0, 0);
 		n1->nredir.redirect = NULL;
 		if (readtoken() != TRP)
-			synexpect(TRP);
+			synexpect(TRP, 0);
 		checkkwd = 1;
 		break;
 	case TBEGIN:
 		n1 = list(0, 0);
 		if (readtoken() != TEND)
-			synexpect(TEND);
+			synexpect(TEND, 0);
 		checkkwd = 1;
 		break;
 	/* Handle an empty command like other simple commands.  */
@@ -507,7 +504,7 @@
 		 * should certainly be disallowed in the case of `if ;'.
 		 */
 		if (!redir)
-			synexpect(-1);
+			synexpect(-1, 0);
 	case TAND:
 	case TOR:
 	case TNL:
@@ -524,7 +521,7 @@
 		}
 		/* FALLTHROUGH */
 	default:
-		synexpect(-1);
+		synexpect(-1, 0);
 		/* NOTREACHED */
 	}
 
@@ -603,7 +600,7 @@
 					    && rpp == orig_rpp) {
 			/* We have a function */
 			if (readtoken() != TRP)
-				synexpect(TRP);
+				synexpect(TRP, 0);
 			funclinno = plinno;
 			rmescapes(n->narg.text);
 			if (!goodname(n->narg.text))
@@ -677,7 +674,7 @@
 	union node *n = redirnode;
 
 	if (readtoken() != TWORD)
-		synexpect(-1);
+		synexpect(-1, 0);
 	if (n->type == NHERE) {
 		struct heredoc *here = heredoc;
 		struct heredoc *p;
@@ -852,28 +849,14 @@
 				continue;
 			pungetc();
 			continue;
-		case '\\':
-			switch (pgetc()) {
-			case '\n':
-				startlinno = ++plinno;
-				if (doprompt)
-					setprompt(2);
-				else
-					setprompt(0);
-				continue;
-			case PEOF:
-				RETURN(TEOF);
-			default:
-				pungetc();
-				break;
-			}
-			goto breakloop;
+
 		case '\n':
 			plinno++;
 			needprompt = doprompt;
 			RETURN(TNL);
 		case PEOF:
 			RETURN(TEOF);
+
 		case '&':
 			if (pgetc() == '&')
 				RETURN(TAND);
@@ -893,12 +876,27 @@
 			RETURN(TLP);
 		case ')':
 			RETURN(TRP);
+
+		case '\\':
+			switch (pgetc()) {
+			case '\n':
+				startlinno = ++plinno;
+				if (doprompt)
+					setprompt(2);
+				else
+					setprompt(0);
+				continue;
+			case PEOF:
+				RETURN(TEOF);
+			default:
+				pungetc();
+				break;
+			}
+			/* FALLTHROUGH */
 		default:
-			goto breakloop;
+			return readtoken1(c, BASESYNTAX, NULL, 0);
 		}
 	}
-breakloop:
-	return readtoken1(c, BASESYNTAX, NULL, 0);
 #undef RETURN
 }
 
@@ -1209,7 +1207,7 @@
 	else {
 		if (readtoken() != TRP) {
 			cleanup_state_stack(stack);
-			synexpect(TRP);
+			synexpect(TRP, 0);
 		}
 	}
 
@@ -1263,9 +1261,8 @@
 	startlinno = plinno;
 	varnest = 0;
 	quoted = 0;
-	if (syntax == DQSYNTAX) {
+	if (syntax == DQSYNTAX)
 		SETDBLQUOTE();
-	}
 	quotef = 0;
 	bqlist = NULL;
 	arinest = 0;
@@ -1273,16 +1270,6 @@
 
 	STARTSTACKSTR(out);
 	loop: {	/* for each line, until end of word */
-#if ATTY
-		if (c == '\034' && doprompt
-		 && attyset() && ! equal(termval(), "emacs")) {
-			attyline();
-			if (syntax == BASESYNTAX)
-				return readtoken();
-			c = pgetc();
-			goto loop;
-		}
-#endif
 		CHECKEND();	/* set c to PEOF if at end of here document */
 		for (;;) {	/* until end of line or end of word */
 			CHECKSTRSPACE(4, out);	/* permit 4 calls to USTPUTC */
@@ -1779,7 +1766,7 @@
 
 int
 goodname(char *name)
-	{
+{
 	char *p;
 
 	p = name;
@@ -1800,16 +1787,28 @@
  */
 
 STATIC void
-synexpect(int token)
+synexpect(int token, const char *text)
 {
 	char msg[64];
+	char *p;
 
-	if (token >= 0) {
-		fmtstr(msg, 64, "%s unexpected (expecting %s)",
-			tokname[lasttoken], tokname[token]);
-	} else {
-		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
-	}
+	if (lasttoken == TWORD) {
+		size_t len = strlen(wordtext);
+
+		if (len <= 13)
+			fmtstr(msg, 34, "Word \"%.13s\" unexpected", wordtext);
+		else
+			fmtstr(msg, 34,
+			    "Word \"%.10s...\" unexpected", wordtext);
+	} else
+		fmtstr(msg, 34, "%s unexpected", tokname[lasttoken]);
+
+	p = strchr(msg, '\0');
+	if (text)
+		fmtstr(p, 30, " (expecting \"%.10s\")", text);
+	else if (token >= 0)
+		fmtstr(p, 30, " (expecting %s)",  tokname[token]);
+
 	synerror(msg);
 	/* NOTREACHED */
 }
@@ -1818,12 +1817,7 @@
 STATIC void
 synerror(const char *msg)
 {
-	if (commandname)
-		outfmt(&errout, "%s: %d: ", commandname, startlinno);
-	else
-		outfmt(&errout, "%s: ", getprogname());
-	outfmt(&errout, "Syntax error: %s\n", msg);
-	error(NULL);
+	error("%d: Syntax error: %s\n", startlinno, msg);
 	/* NOTREACHED */
 }
 
@@ -1844,7 +1838,7 @@
  */
 const char *
 getprompt(void *unused)
-	{
+{
 	switch (whichprompt) {
 	case 0:
 		return "";
@@ -1856,4 +1850,3 @@
 		return "<internal prompt error>";
 	}
 }
-

cvs diff -r1.26 -r1.27 src/bin/sh/var.h (expand / switch to context diff)
--- src/bin/sh/var.h 2015/05/26 21:35:15 1.26
+++ src/bin/sh/var.h 2016/03/27 14:34:46 1.27
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.h,v 1.26 2015/05/26 21:35:15 christos Exp $	*/
+/*	$NetBSD: var.h,v 1.27 2016/03/27 14:34:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -70,10 +70,8 @@
 
 extern struct localvar *localvars;
 
-#if ATTY
-extern struct var vatty;
-#endif
 extern struct var vifs;
+extern char ifs_default[];
 extern struct var vmail;
 extern struct var vmpath;
 extern struct var vpath;
@@ -92,8 +90,8 @@
  * for unset variables.
  */
 
-#define ifsval()	(vifs.text + 4)
 #define ifsset()	((vifs.flags & VUNSET) == 0)
+#define ifsval()	(ifsset() ? (vifs.text + 4) : ifs_default)
 #define mailval()	(vmail.text + 5)
 #define mpathval()	(vmpath.text + 9)
 #define pathval()	(vpath.text + 5)
@@ -106,9 +104,6 @@
 #define termval()	(vterm.text + 5)
 #endif
 
-#if ATTY
-#define attyset()	((vatty.flags & VUNSET) == 0)
-#endif
 #define mpathset()	((vmpath.flags & VUNSET) == 0)
 
 void initvar(void);