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 unified 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,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: expand.c,v 1.97 2016/03/16 15:44:35 christos Exp $ */ 1/* $NetBSD: expand.c,v 1.98 2016/03/27 14:34:46 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; 38static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
39#else 39#else
40__RCSID("$NetBSD: expand.c,v 1.97 2016/03/16 15:44:35 christos Exp $"); 40__RCSID("$NetBSD: expand.c,v 1.98 2016/03/27 14:34:46 christos Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/time.h> 45#include <sys/time.h>
46#include <sys/stat.h> 46#include <sys/stat.h>
47#include <errno.h> 47#include <errno.h>
48#include <dirent.h> 48#include <dirent.h>
49#include <unistd.h> 49#include <unistd.h>
50#include <pwd.h> 50#include <pwd.h>
51#include <limits.h> 51#include <limits.h>
52#include <stdlib.h> 52#include <stdlib.h>
53#include <stdio.h> 53#include <stdio.h>
@@ -183,27 +183,27 @@ expandarg(union node *arg, struct arglis @@ -183,27 +183,27 @@ expandarg(union node *arg, struct arglis
183 * Otherwise treat $@ like $* since no splitting will be performed. 183 * Otherwise treat $@ like $* since no splitting will be performed.
184 */ 184 */
185 185
186STATIC void 186STATIC void
187argstr(char *p, int flag) 187argstr(char *p, int flag)
188{ 188{
189 char c; 189 char c;
190 int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */ 190 int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
191 int firsteq = 1; 191 int firsteq = 1;
192 const char *ifs = NULL; 192 const char *ifs = NULL;
193 int ifs_split = EXP_IFS_SPLIT; 193 int ifs_split = EXP_IFS_SPLIT;
194 194
195 if (flag & EXP_IFS_SPLIT) 195 if (flag & EXP_IFS_SPLIT)
196 ifs = ifsset() ? ifsval() : " \t\n"; 196 ifs = ifsval();
197 197
198 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) 198 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
199 p = exptilde(p, flag); 199 p = exptilde(p, flag);
200 for (;;) { 200 for (;;) {
201 switch (c = *p++) { 201 switch (c = *p++) {
202 case '\0': 202 case '\0':
203 case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */ 203 case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
204 return; 204 return;
205 case CTLQUOTEMARK: 205 case CTLQUOTEMARK:
206 /* "$@" syntax adherence hack */ 206 /* "$@" syntax adherence hack */
207 if (p[0] == CTLVAR && p[1] & VSQUOTE && 207 if (p[0] == CTLVAR && p[1] & VSQUOTE &&
208 p[2] == '@' && p[3] == '=') 208 p[2] == '@' && p[3] == '=')
209 break; 209 break;
@@ -695,27 +695,26 @@ again: /* jump here after setting a vari @@ -695,27 +695,26 @@ again: /* jump here after setting a vari
695 } else { 695 } else {
696 char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX 696 char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
697 : BASESYNTAX; 697 : BASESYNTAX;
698 698
699 if (subtype == VSLENGTH) { 699 if (subtype == VSLENGTH) {
700 for (;*val; val++) 700 for (;*val; val++)
701 varlen++; 701 varlen++;
702 } else { 702 } else {
703 while (*val) { 703 while (*val) {
704 if (quotes && syntax[(int)*val] == CCTL) 704 if (quotes && syntax[(int)*val] == CCTL)
705 STPUTC(CTLESC, expdest); 705 STPUTC(CTLESC, expdest);
706 STPUTC(*val++, expdest); 706 STPUTC(*val++, expdest);
707 } 707 }
708 
709 } 708 }
710 } 709 }
711 } 710 }
712 711
713 712
714 if (flag & EXP_IN_QUOTES) 713 if (flag & EXP_IN_QUOTES)
715 apply_ifs = 0; 714 apply_ifs = 0;
716 else if (varflags & VSQUOTE) { 715 else if (varflags & VSQUOTE) {
717 if (*var == '@' && shellparam.nparam != 1) 716 if (*var == '@' && shellparam.nparam != 1)
718 apply_ifs = 1; 717 apply_ifs = 1;
719 else { 718 else {
720 /* 719 /*
721 * Mark so that we don't apply IFS if we recurse through 720 * Mark so that we don't apply IFS if we recurse through
@@ -914,30 +913,27 @@ numvar: @@ -914,30 +913,27 @@ numvar:
914 break; 913 break;
915 case '@': 914 case '@':
916 if (flag & EXP_FULL && quoted) { 915 if (flag & EXP_FULL && quoted) {
917 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 916 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
918 STRTODEST(p); 917 STRTODEST(p);
919 if (*ap) 918 if (*ap)
920 /* A NUL separates args inside "" */ 919 /* A NUL separates args inside "" */
921 STPUTC('\0', expdest); 920 STPUTC('\0', expdest);
922 } 921 }
923 break; 922 break;
924 } 923 }
925 /* fall through */ 924 /* fall through */
926 case '*': 925 case '*':
927 if (ifsset() != 0) 926 sep = ifsval()[0];
928 sep = ifsval()[0]; 
929 else 
930 sep = ' '; 
931 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 927 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
932 STRTODEST(p); 928 STRTODEST(p);
933 if (*ap && sep) 929 if (*ap && sep)
934 STPUTC(sep, expdest); 930 STPUTC(sep, expdest);
935 } 931 }
936 break; 932 break;
937 case '0': 933 case '0':
938 p = arg0; 934 p = arg0;
939 STRTODEST(p); 935 STRTODEST(p);
940 break; 936 break;
941 default: 937 default:
942 if (is_digit(*name)) { 938 if (is_digit(*name)) {
943 num = atoi(name); 939 num = atoi(name);
@@ -1001,27 +997,27 @@ ifsbreakup(char *string, struct arglist  @@ -1001,27 +997,27 @@ ifsbreakup(char *string, struct arglist
1001 int had_param_ch = 0; 997 int had_param_ch = 0;
1002 998
1003 start = string; 999 start = string;
1004 1000
1005 if (ifslastp == NULL) { 1001 if (ifslastp == NULL) {
1006 /* Return entire argument, IFS doesn't apply to any of it */ 1002 /* Return entire argument, IFS doesn't apply to any of it */
1007 sp = stalloc(sizeof(*sp)); 1003 sp = stalloc(sizeof(*sp));
1008 sp->text = start; 1004 sp->text = start;
1009 *arglist->lastp = sp; 1005 *arglist->lastp = sp;
1010 arglist->lastp = &sp->next; 1006 arglist->lastp = &sp->next;
1011 return; 1007 return;
1012 } 1008 }
1013 1009
1014 ifs = ifsset() ? ifsval() : " \t\n"; 1010 ifs = ifsval();
1015 1011
1016 for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) { 1012 for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
1017 p = string + ifsp->begoff; 1013 p = string + ifsp->begoff;
1018 while (p < string + ifsp->endoff) { 1014 while (p < string + ifsp->endoff) {
1019 had_param_ch = 1; 1015 had_param_ch = 1;
1020 q = p; 1016 q = p;
1021 if (*p == CTLESC) 1017 if (*p == CTLESC)
1022 p++; 1018 p++;
1023 if (ifsp->inquotes) { 1019 if (ifsp->inquotes) {
1024 /* Only NULs (should be from "$@") end args */ 1020 /* Only NULs (should be from "$@") end args */
1025 if (*p != 0) { 1021 if (*p != 0) {
1026 p++; 1022 p++;
1027 continue; 1023 continue;

cvs diff -r1.47 -r1.48 src/bin/sh/input.c (expand / switch to unified 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,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: input.c,v 1.47 2016/01/04 03:00:24 christos Exp $ */ 1/* $NetBSD: input.c,v 1.48 2016/03/27 14:34:46 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; 38static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
39#else 39#else
40__RCSID("$NetBSD: input.c,v 1.47 2016/01/04 03:00:24 christos Exp $"); 40__RCSID("$NetBSD: input.c,v 1.48 2016/03/27 14:34:46 christos Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <stdio.h> /* defines BUFSIZ */ 44#include <stdio.h> /* defines BUFSIZ */
45#include <fcntl.h> 45#include <fcntl.h>
46#include <errno.h> 46#include <errno.h>
47#include <unistd.h> 47#include <unistd.h>
48#include <limits.h> 48#include <limits.h>
49#include <stdlib.h> 49#include <stdlib.h>
50#include <string.h> 50#include <string.h>
51 51
52/* 52/*
53 * This file implements the input routines used by the parser. 53 * This file implements the input routines used by the parser.
@@ -443,26 +443,27 @@ setinputfd(int fd, int push) @@ -443,26 +443,27 @@ setinputfd(int fd, int push)
443 parsefile->buf = ckmalloc(BUFSIZ); 443 parsefile->buf = ckmalloc(BUFSIZ);
444 parselleft = parsenleft = 0; 444 parselleft = parsenleft = 0;
445 plinno = 1; 445 plinno = 1;
446} 446}
447 447
448 448
449/* 449/*
450 * Like setinputfile, but takes input from a string. 450 * Like setinputfile, but takes input from a string.
451 */ 451 */
452 452
453void 453void
454setinputstring(char *string, int push) 454setinputstring(char *string, int push)
455{ 455{
 456
456 INTOFF; 457 INTOFF;
457 if (push) 458 if (push)
458 pushfile(); 459 pushfile();
459 parsenextc = string; 460 parsenextc = string;
460 parselleft = parsenleft = strlen(string); 461 parselleft = parsenleft = strlen(string);
461 parsefile->buf = NULL; 462 parsefile->buf = NULL;
462 plinno = 1; 463 plinno = 1;
463 INTON; 464 INTON;
464} 465}
465 466
466 467
467 468
468/* 469/*

cvs diff -r1.47 -r1.48 src/bin/sh/var.c (expand / switch to unified 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,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.47 2016/03/08 23:24:51 christos Exp $ */ 1/* $NetBSD: var.c,v 1.48 2016/03/27 14:34:46 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; 38static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
39#else 39#else
40__RCSID("$NetBSD: var.c,v 1.47 2016/03/08 23:24:51 christos Exp $"); 40__RCSID("$NetBSD: var.c,v 1.48 2016/03/27 14:34:46 christos Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <unistd.h> 44#include <unistd.h>
45#include <stdlib.h> 45#include <stdlib.h>
46#include <string.h> 46#include <string.h>
47#include <paths.h> 47#include <paths.h>
48#include <limits.h> 48#include <limits.h>
49 49
50/* 50/*
51 * Shell variables. 51 * Shell variables.
52 */ 52 */
53 53
@@ -77,47 +77,42 @@ __RCSID("$NetBSD: var.c,v 1.47 2016/03/0 @@ -77,47 +77,42 @@ __RCSID("$NetBSD: var.c,v 1.47 2016/03/0
77#define VTABSIZE 517 77#define VTABSIZE 517
78#endif 78#endif
79 79
80 80
81struct varinit { 81struct varinit {
82 struct var *var; 82 struct var *var;
83 int flags; 83 int flags;
84 const char *text; 84 const char *text;
85 void (*func)(const char *); 85 void (*func)(const char *);
86}; 86};
87 87
88struct localvar *localvars; 88struct localvar *localvars;
89 89
90#if ATTY 
91struct var vatty; 
92#endif 
93#ifndef SMALL 90#ifndef SMALL
94struct var vhistsize; 91struct var vhistsize;
95struct var vterm; 92struct var vterm;
96#endif 93#endif
97struct var vifs; 94struct var vifs;
98struct var vmail; 95struct var vmail;
99struct var vmpath; 96struct var vmpath;
100struct var vpath; 97struct var vpath;
101struct var vps1; 98struct var vps1;
102struct var vps2; 99struct var vps2;
103struct var vps4; 100struct var vps4;
104struct var voptind; 101struct var voptind;
105 102
 103char ifs_default[] = " \t\n";
 104
106const struct varinit varinit[] = { 105const struct varinit varinit[] = {
107#if ATTY 
108 { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", 
109 NULL }, 
110#endif 
111#ifndef SMALL 106#ifndef SMALL
112 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", 107 { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
113 sethistsize }, 108 sethistsize },
114#endif 109#endif
115 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", 110 { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
116 NULL }, 111 NULL },
117 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", 112 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
118 NULL }, 113 NULL },
119 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", 114 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
120 NULL }, 115 NULL },
121 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, 116 { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
122 changepath }, 117 changepath },
123 /* 118 /*
@@ -152,33 +147,34 @@ INCLUDE  @@ -152,33 +147,34 @@ INCLUDE
152INCLUDE "var.h" 147INCLUDE "var.h"
153MKINIT char **environ; 148MKINIT char **environ;
154INIT { 149INIT {
155 char **envp; 150 char **envp;
156 char buf[64]; 151 char buf[64];
157 152
158 initvar(); 153 initvar();
159 for (envp = environ ; *envp ; envp++) { 154 for (envp = environ ; *envp ; envp++) {
160 if (strchr(*envp, '=')) { 155 if (strchr(*envp, '=')) {
161 setvareq(*envp, VEXPORT|VTEXTFIXED); 156 setvareq(*envp, VEXPORT|VTEXTFIXED);
162 } 157 }
163 } 158 }
164 159
165 
166 /* 160 /*
167 * PPID is readonly 161 * PPID is readonly
168 * set after processing environ to override anything there 162 * set after processing environ to override anything there
 163 * Always default IFS, ignore any value from environment.
169 */ 164 */
170 snprintf(buf, sizeof(buf), "%d", (int)getppid()); 165 snprintf(buf, sizeof(buf), "%d", (int)getppid());
171 setvar("PPID", buf, VREADONLY); 166 setvar("PPID", buf, VREADONLY);
 167 setvar("IFS", ifs_default, VTEXTFIXED);
172} 168}
173#endif 169#endif
174 170
175 171
176/* 172/*
177 * This routine initializes the builtin variables. It is called when the 173 * This routine initializes the builtin variables. It is called when the
178 * shell is initialized and again when a shell procedure is spawned. 174 * shell is initialized and again when a shell procedure is spawned.
179 */ 175 */
180 176
181void 177void
182initvar(void) 178initvar(void)
183{ 179{
184 const struct varinit *ip; 180 const struct varinit *ip;

cvs diff -r1.62 -r1.63 src/bin/sh/main.c (expand / switch to unified 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,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: main.c,v 1.62 2016/03/01 21:10:40 martin Exp $ */ 1/* $NetBSD: main.c,v 1.63 2016/03/27 14:34:46 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -32,27 +32,27 @@ @@ -32,27 +32,27 @@
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37__COPYRIGHT("@(#) Copyright (c) 1991, 1993\ 37__COPYRIGHT("@(#) Copyright (c) 1991, 1993\
38 The Regents of the University of California. All rights reserved."); 38 The Regents of the University of California. All rights reserved.");
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#ifndef lint 41#ifndef lint
42#if 0 42#if 0
43static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95"; 43static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
44#else 44#else
45__RCSID("$NetBSD: main.c,v 1.62 2016/03/01 21:10:40 martin Exp $"); 45__RCSID("$NetBSD: main.c,v 1.63 2016/03/27 14:34:46 christos Exp $");
46#endif 46#endif
47#endif /* not lint */ 47#endif /* not lint */
48 48
49#include <errno.h> 49#include <errno.h>
50#include <stdio.h> 50#include <stdio.h>
51#include <signal.h> 51#include <signal.h>
52#include <sys/stat.h> 52#include <sys/stat.h>
53#include <unistd.h> 53#include <unistd.h>
54#include <stdlib.h> 54#include <stdlib.h>
55#include <locale.h> 55#include <locale.h>
56#include <fcntl.h> 56#include <fcntl.h>
57 57
58 58
@@ -140,31 +140,27 @@ main(int argc, char **argv) @@ -140,31 +140,27 @@ main(int argc, char **argv)
140 case EXERROR: 140 case EXERROR:
141 exitstatus = 2; 141 exitstatus = 2;
142 break; 142 break;
143 143
144 default: 144 default:
145 break; 145 break;
146 } 146 }
147 147
148 if (exception != EXSHELLPROC) { 148 if (exception != EXSHELLPROC) {
149 if (state == 0 || iflag == 0 || ! rootshell) 149 if (state == 0 || iflag == 0 || ! rootshell)
150 exitshell(exitstatus); 150 exitshell(exitstatus);
151 } 151 }
152 reset(); 152 reset();
153 if (exception == EXINT 153 if (exception == EXINT) {
154#if ATTY 
155 && (! attyset() || equal(termval(), "emacs")) 
156#endif 
157 ) { 
158 out2c('\n'); 154 out2c('\n');
159 flushout(&errout); 155 flushout(&errout);
160 } 156 }
161 popstackmark(&smark); 157 popstackmark(&smark);
162 FORCEINTON; /* enable interrupts */ 158 FORCEINTON; /* enable interrupts */
163 if (state == 1) 159 if (state == 1)
164 goto state1; 160 goto state1;
165 else if (state == 2) 161 else if (state == 2)
166 goto state2; 162 goto state2;
167 else if (state == 3) 163 else if (state == 3)
168 goto state3; 164 goto state3;
169 else 165 else
170 goto state4; 166 goto state4;

cvs diff -r1.6 -r1.7 src/bin/sh/mkinit.sh (expand / switch to unified 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,15 +1,15 @@ @@ -1,15 +1,15 @@
1#! /bin/sh 1#! /bin/sh
2# $NetBSD: mkinit.sh,v 1.6 2016/03/08 23:23:31 christos Exp $ 2# $NetBSD: mkinit.sh,v 1.7 2016/03/27 14:34:46 christos Exp $
3 3
4# Copyright (c) 2003 The NetBSD Foundation, Inc. 4# Copyright (c) 2003 The NetBSD Foundation, Inc.
5# All rights reserved. 5# All rights reserved.
6# 6#
7# This code is derived from software contributed to The NetBSD Foundation 7# This code is derived from software contributed to The NetBSD Foundation
8# by David Laight. 8# by David Laight.
9# 9#
10# Redistribution and use in source and binary forms, with or without 10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions 11# modification, are permitted provided that the following conditions
12# are met: 12# are met:
13# 1. Redistributions of source code must retain the above copyright 13# 1. Redistributions of source code must retain the above copyright
14# notice, this list of conditions and the following disclaimer. 14# notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright 15# 2. Redistributions in binary form must reproduce the above copyright
@@ -45,27 +45,27 @@ event_shellproc= @@ -45,27 +45,27 @@ event_shellproc=
45for src in $srcs; do 45for src in $srcs; do
46 exec <$src 46 exec <$src
47 decnl="$nl" 47 decnl="$nl"
48 while IFS=; read -r line; do 48 while IFS=; read -r line; do
49 [ "$line" = x ] 49 [ "$line" = x ]
50 case "$line " in 50 case "$line " in
51 INIT["{ "]* ) event=init;; 51 INIT["{ "]* ) event=init;;
52 RESET["{ "]* ) event=reset;; 52 RESET["{ "]* ) event=reset;;
53 SHELLPROC["{ "]* ) event=shellproc;; 53 SHELLPROC["{ "]* ) event=shellproc;;
54 INCLUDE[\ \ ]* ) 54 INCLUDE[\ \ ]* )
55 IFS=' ' 55 IFS=' '
56 set -- $line 56 set -- $line
57 # ignore duplicates 57 # ignore duplicates
58 [ "${includes}" != "${includes%* $2 *}" ] && continue 58 [ "${includes}" != "${includes% $2 *}" ] && continue
59 includes="$includes$2 " 59 includes="$includes$2 "
60 continue 60 continue
61 ;; 61 ;;
62 MKINIT\ ) 62 MKINIT\ )
63 # struct declaration 63 # struct declaration
64 decles="$decles$nl" 64 decles="$decles$nl"
65 while 65 while
66 read -r line 66 read -r line
67 decles="${decles}${line}${nl}" 67 decles="${decles}${line}${nl}"
68 [ "$line" != "};" ] 68 [ "$line" != "};" ]
69 do 69 do
70 : 70 :
71 done 71 done

cvs diff -r1.2 -r1.3 src/bin/sh/mknodenames.sh (expand / switch to unified 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
@@ -1,23 +1,23 @@ @@ -1,23 +1,23 @@
1#! /bin/sh 1#! /bin/sh
2 2
3if [ -z "$1" ]; then 3if [ -z "$1" ]; then
4 echo "Usage: $0 nodes.h" 1>&2 4 echo "Usage: $0 nodes.h" 1>&2
5 exit 1 5 exit 1
6fi 6fi
7 7
8NODES=$1 8NODES=$1
9 9
10test -t 1 && exec > nodenames.h 10test -t 1 && -z "$2" && exec > nodenames.h
11 11
12echo "#ifdef DEBUG" 12echo "#ifdef DEBUG"
13echo ' 13echo '
14/* 14/*
15 * Automatically generated by '"$0"' 15 * Automatically generated by '"$0"'
16 * DO NOT EDIT. Do Not "cvs add". 16 * DO NOT EDIT. Do Not "cvs add".
17 */ 17 */
18' 18'
19 19
20MAX=$(awk < "$NODES" ' 20MAX=$(awk < "$NODES" '
21 /#define/ { 21 /#define/ {
22 if ($3 > MAX) MAX = $3 22 if ($3 > MAX) MAX = $3
23 } 23 }

cvs diff -r1.107 -r1.108 src/bin/sh/parser.c (expand / switch to unified 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,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parser.c,v 1.107 2016/03/21 02:37:26 christos Exp $ */ 1/* $NetBSD: parser.c,v 1.108 2016/03/27 14:34:46 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; 38static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
39#else 39#else
40__RCSID("$NetBSD: parser.c,v 1.107 2016/03/21 02:37:26 christos Exp $"); 40__RCSID("$NetBSD: parser.c,v 1.108 2016/03/27 14:34:46 christos Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <stdio.h> 44#include <stdio.h>
45#include <stdlib.h> 45#include <stdlib.h>
46#include <limits.h> 46#include <limits.h>
47 47
48#include "shell.h" 48#include "shell.h"
49#include "parser.h" 49#include "parser.h"
50#include "nodes.h" 50#include "nodes.h"
51#include "expand.h" /* defines rmescapes() */ 51#include "expand.h" /* defines rmescapes() */
52#include "eval.h" /* defines commandname */ 52#include "eval.h" /* defines commandname */
53#include "redir.h" /* defines copyfd() */ 53#include "redir.h" /* defines copyfd() */
@@ -107,33 +107,34 @@ int funclinno; /* line # where the cur @@ -107,33 +107,34 @@ int funclinno; /* line # where the cur
107STATIC union node *list(int, int); 107STATIC union node *list(int, int);
108STATIC union node *andor(void); 108STATIC union node *andor(void);
109STATIC union node *pipeline(void); 109STATIC union node *pipeline(void);
110STATIC union node *command(void); 110STATIC union node *command(void);
111STATIC union node *simplecmd(union node **, union node *); 111STATIC union node *simplecmd(union node **, union node *);
112STATIC union node *makename(void); 112STATIC union node *makename(void);
113STATIC void parsefname(void); 113STATIC void parsefname(void);
114STATIC void parseheredoc(void); 114STATIC void parseheredoc(void);
115STATIC int peektoken(void); 115STATIC int peektoken(void);
116STATIC int readtoken(void); 116STATIC int readtoken(void);
117STATIC int xxreadtoken(void); 117STATIC int xxreadtoken(void);
118STATIC int readtoken1(int, char const *, char *, int); 118STATIC int readtoken1(int, char const *, char *, int);
119STATIC int noexpand(char *); 119STATIC int noexpand(char *);
120STATIC void synexpect(int) __dead; 120STATIC void synexpect(int, const char *) __dead;
121STATIC void synerror(const char *) __dead; 121STATIC void synerror(const char *) __dead;
122STATIC void setprompt(int); 122STATIC void setprompt(int);
123 123
124 124
125static const char EOFhere[] = "EOF reading here (<<) document"; 125static const char EOFhere[] = "EOF reading here (<<) document";
126 126
 127
127/* 128/*
128 * Read and parse a command. Returns NEOF on end of file. (NULL is a 129 * Read and parse a command. Returns NEOF on end of file. (NULL is a
129 * valid parse tree indicating a blank line.) 130 * valid parse tree indicating a blank line.)
130 */ 131 */
131 132
132union node * 133union node *
133parsecmd(int interact) 134parsecmd(int interact)
134{ 135{
135 int t; 136 int t;
136 137
137 tokpushback = 0; 138 tokpushback = 0;
138 doprompt = interact; 139 doprompt = interact;
139 if (doprompt) 140 if (doprompt)
@@ -146,27 +147,27 @@ parsecmd(int interact) @@ -146,27 +147,27 @@ parsecmd(int interact)
146 return NEOF; 147 return NEOF;
147 if (t == TNL) 148 if (t == TNL)
148 return NULL; 149 return NULL;
149 tokpushback++; 150 tokpushback++;
150 return list(1, 0); 151 return list(1, 0);
151} 152}
152 153
153 154
154STATIC union node * 155STATIC union node *
155list(int nlflag, int erflag) 156list(int nlflag, int erflag)
156{ 157{
157 union node *n1, *n2, *n3; 158 union node *n1, *n2, *n3;
158 int tok; 159 int tok;
159 TRACE(("list: entered\n")); 160 TRACE(("list(%d,%d): entered\n", nlflag, erflag));
160 161
161 checkkwd = 2; 162 checkkwd = 2;
162 if (nlflag == 0 && tokendlist[peektoken()]) 163 if (nlflag == 0 && tokendlist[peektoken()])
163 return NULL; 164 return NULL;
164 n1 = NULL; 165 n1 = NULL;
165 for (;;) { 166 for (;;) {
166 n2 = andor(); 167 n2 = andor();
167 tok = readtoken(); 168 tok = readtoken();
168 if (tok == TBACKGND) { 169 if (tok == TBACKGND) {
169 if (n2->type == NCMD || n2->type == NPIPE) { 170 if (n2->type == NCMD || n2->type == NPIPE) {
170 n2->ncmd.backgnd = 1; 171 n2->ncmd.backgnd = 1;
171 } else if (n2->type == NREDIR) { 172 } else if (n2->type == NREDIR) {
172 n2->type = NBACKGND; 173 n2->type = NBACKGND;
@@ -182,84 +183,80 @@ list(int nlflag, int erflag) @@ -182,84 +183,80 @@ list(int nlflag, int erflag)
182 n1 = n2; 183 n1 = n2;
183 } 184 }
184 else { 185 else {
185 n3 = stalloc(sizeof(struct nbinary)); 186 n3 = stalloc(sizeof(struct nbinary));
186 n3->type = NSEMI; 187 n3->type = NSEMI;
187 n3->nbinary.ch1 = n1; 188 n3->nbinary.ch1 = n1;
188 n3->nbinary.ch2 = n2; 189 n3->nbinary.ch2 = n2;
189 n1 = n3; 190 n1 = n3;
190 } 191 }
191 switch (tok) { 192 switch (tok) {
192 case TBACKGND: 193 case TBACKGND:
193 case TSEMI: 194 case TSEMI:
194 tok = readtoken(); 195 tok = readtoken();
195 /* fall through */ 196 /* FALLTHROUGH */
196 case TNL: 197 case TNL:
197 if (tok == TNL) { 198 if (tok == TNL) {
198 parseheredoc(); 199 parseheredoc();
199 if (nlflag) 200 if (nlflag)
200 return n1; 201 return n1;
201 } else { 202 } else {
202 tokpushback++; 203 tokpushback++;
203 } 204 }
204 checkkwd = 2; 205 checkkwd = 2;
205 if (tokendlist[peektoken()]) 206 if (tokendlist[peektoken()])
206 return n1; 207 return n1;
207 break; 208 break;
208 case TEOF: 209 case TEOF:
209 if (heredoclist) 210 if (heredoclist)
210 parseheredoc(); 211 parseheredoc();
211 else 212 else
212 pungetc(); /* push back EOF on input */ 213 pungetc(); /* push back EOF on input */
213 return n1; 214 return n1;
214 default: 215 default:
215 if (nlflag || erflag) 216 if (nlflag || erflag)
216 synexpect(-1); 217 synexpect(-1, 0);
217 tokpushback++; 218 tokpushback++;
218 return n1; 219 return n1;
219 } 220 }
220 } 221 }
221} 222}
222 223
223 
224 
225STATIC union node * 224STATIC union node *
226andor(void) 225andor(void)
227{ 226{
228 union node *n1, *n2, *n3; 227 union node *n1, *n2, *n3;
229 int t; 228 int t;
230 229
231 TRACE(("andor: entered\n")); 230 TRACE(("andor: entered\n"));
232 n1 = pipeline(); 231 n1 = pipeline();
233 for (;;) { 232 for (;;) {
234 if ((t = readtoken()) == TAND) { 233 if ((t = readtoken()) == TAND) {
235 t = NAND; 234 t = NAND;
236 } else if (t == TOR) { 235 } else if (t == TOR) {
237 t = NOR; 236 t = NOR;
238 } else { 237 } else {
239 tokpushback++; 238 tokpushback++;
240 return n1; 239 return n1;
241 } 240 }
242 n2 = pipeline(); 241 n2 = pipeline();
243 n3 = stalloc(sizeof(struct nbinary)); 242 n3 = stalloc(sizeof(struct nbinary));
244 n3->type = t; 243 n3->type = t;
245 n3->nbinary.ch1 = n1; 244 n3->nbinary.ch1 = n1;
246 n3->nbinary.ch2 = n2; 245 n3->nbinary.ch2 = n2;
247 n1 = n3; 246 n1 = n3;
248 } 247 }
249} 248}
250 249
251 
252 
253STATIC union node * 250STATIC union node *
254pipeline(void) 251pipeline(void)
255{ 252{
256 union node *n1, *n2, *pipenode; 253 union node *n1, *n2, *pipenode;
257 struct nodelist *lp, *prev; 254 struct nodelist *lp, *prev;
258 int negate; 255 int negate;
259 256
260 TRACE(("pipeline: entered\n")); 257 TRACE(("pipeline: entered\n"));
261 258
262 negate = 0; 259 negate = 0;
263 checkkwd = 2; 260 checkkwd = 2;
264 while (readtoken() == TNOT) { 261 while (readtoken() == TNOT) {
265 TRACE(("pipeline: TNOT recognized\n")); 262 TRACE(("pipeline: TNOT recognized\n"));
@@ -322,126 +319,126 @@ command(void) @@ -322,126 +319,126 @@ command(void)
322 319
323 while (readtoken() == TNOT) { 320 while (readtoken() == TNOT) {
324 TRACE(("command: TNOT recognized\n")); 321 TRACE(("command: TNOT recognized\n"));
325 negate = !negate; 322 negate = !negate;
326 } 323 }
327 tokpushback++; 324 tokpushback++;
328 325
329 switch (readtoken()) { 326 switch (readtoken()) {
330 case TIF: 327 case TIF:
331 n1 = stalloc(sizeof(struct nif)); 328 n1 = stalloc(sizeof(struct nif));
332 n1->type = NIF; 329 n1->type = NIF;
333 n1->nif.test = list(0, 0); 330 n1->nif.test = list(0, 0);
334 if (readtoken() != TTHEN) 331 if (readtoken() != TTHEN)
335 synexpect(TTHEN); 332 synexpect(TTHEN, 0);
336 n1->nif.ifpart = list(0, 0); 333 n1->nif.ifpart = list(0, 0);
337 n2 = n1; 334 n2 = n1;
338 while (readtoken() == TELIF) { 335 while (readtoken() == TELIF) {
339 n2->nif.elsepart = stalloc(sizeof(struct nif)); 336 n2->nif.elsepart = stalloc(sizeof(struct nif));
340 n2 = n2->nif.elsepart; 337 n2 = n2->nif.elsepart;
341 n2->type = NIF; 338 n2->type = NIF;
342 n2->nif.test = list(0, 0); 339 n2->nif.test = list(0, 0);
343 if (readtoken() != TTHEN) 340 if (readtoken() != TTHEN)
344 synexpect(TTHEN); 341 synexpect(TTHEN, 0);
345 n2->nif.ifpart = list(0, 0); 342 n2->nif.ifpart = list(0, 0);
346 } 343 }
347 if (lasttoken == TELSE) 344 if (lasttoken == TELSE)
348 n2->nif.elsepart = list(0, 0); 345 n2->nif.elsepart = list(0, 0);
349 else { 346 else {
350 n2->nif.elsepart = NULL; 347 n2->nif.elsepart = NULL;
351 tokpushback++; 348 tokpushback++;
352 } 349 }
353 if (readtoken() != TFI) 350 if (readtoken() != TFI)
354 synexpect(TFI); 351 synexpect(TFI, 0);
355 checkkwd = 1; 352 checkkwd = 1;
356 break; 353 break;
357 case TWHILE: 354 case TWHILE:
358 case TUNTIL: { 355 case TUNTIL: {
359 int got; 356 int got;
360 n1 = stalloc(sizeof(struct nbinary)); 357 n1 = stalloc(sizeof(struct nbinary));
361 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 358 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
362 n1->nbinary.ch1 = list(0, 0); 359 n1->nbinary.ch1 = list(0, 0);
363 if ((got=readtoken()) != TDO) { 360 if ((got=readtoken()) != TDO) {
364TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); 361TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
365 synexpect(TDO); 362 synexpect(TDO, 0);
366 } 363 }
367 n1->nbinary.ch2 = list(0, 0); 364 n1->nbinary.ch2 = list(0, 0);
368 if (readtoken() != TDONE) 365 if (readtoken() != TDONE)
369 synexpect(TDONE); 366 synexpect(TDONE, 0);
370 checkkwd = 1; 367 checkkwd = 1;
371 break; 368 break;
372 } 369 }
373 case TFOR: 370 case TFOR:
374 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 371 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
375 synerror("Bad for loop variable"); 372 synerror("Bad for loop variable");
376 n1 = stalloc(sizeof(struct nfor)); 373 n1 = stalloc(sizeof(struct nfor));
377 n1->type = NFOR; 374 n1->type = NFOR;
378 n1->nfor.var = wordtext; 375 n1->nfor.var = wordtext;
379 if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) { 376 if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
380 app = &ap; 377 app = &ap;
381 while (readtoken() == TWORD) { 378 while (readtoken() == TWORD) {
382 n2 = stalloc(sizeof(struct narg)); 379 n2 = stalloc(sizeof(struct narg));
383 n2->type = NARG; 380 n2->type = NARG;
384 n2->narg.text = wordtext; 381 n2->narg.text = wordtext;
385 n2->narg.backquote = backquotelist; 382 n2->narg.backquote = backquotelist;
386 *app = n2; 383 *app = n2;
387 app = &n2->narg.next; 384 app = &n2->narg.next;
388 } 385 }
389 *app = NULL; 386 *app = NULL;
390 n1->nfor.args = ap; 387 n1->nfor.args = ap;
391 if (lasttoken != TNL && lasttoken != TSEMI) 388 if (lasttoken != TNL && lasttoken != TSEMI)
392 synexpect(-1); 389 synexpect(-1, 0);
393 } else { 390 } else {
394 static char argvars[5] = { 391 static char argvars[5] = {
395 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' 392 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
396 }; 393 };
397 n2 = stalloc(sizeof(struct narg)); 394 n2 = stalloc(sizeof(struct narg));
398 n2->type = NARG; 395 n2->type = NARG;
399 n2->narg.text = argvars; 396 n2->narg.text = argvars;
400 n2->narg.backquote = NULL; 397 n2->narg.backquote = NULL;
401 n2->narg.next = NULL; 398 n2->narg.next = NULL;
402 n1->nfor.args = n2; 399 n1->nfor.args = n2;
403 /* 400 /*
404 * Newline or semicolon here is optional (but note 401 * Newline or semicolon here is optional (but note
405 * that the original Bourne shell only allowed NL). 402 * that the original Bourne shell only allowed NL).
406 */ 403 */
407 if (lasttoken != TNL && lasttoken != TSEMI) 404 if (lasttoken != TNL && lasttoken != TSEMI)
408 tokpushback++; 405 tokpushback++;
409 } 406 }
410 checkkwd = 2; 407 checkkwd = 2;
411 if ((t = readtoken()) == TDO) 408 if ((t = readtoken()) == TDO)
412 t = TDONE; 409 t = TDONE;
413 else if (t == TBEGIN) 410 else if (t == TBEGIN)
414 t = TEND; 411 t = TEND;
415 else 412 else
416 synexpect(-1); 413 synexpect(-1, 0);
417 n1->nfor.body = list(0, 0); 414 n1->nfor.body = list(0, 0);
418 if (readtoken() != t) 415 if (readtoken() != t)
419 synexpect(t); 416 synexpect(t, 0);
420 checkkwd = 1; 417 checkkwd = 1;
421 break; 418 break;
422 case TCASE: 419 case TCASE:
423 n1 = stalloc(sizeof(struct ncase)); 420 n1 = stalloc(sizeof(struct ncase));
424 n1->type = NCASE; 421 n1->type = NCASE;
425 if (readtoken() != TWORD) 422 if (readtoken() != TWORD)
426 synexpect(TWORD); 423 synexpect(TWORD, 0);
427 n1->ncase.expr = n2 = stalloc(sizeof(struct narg)); 424 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
428 n2->type = NARG; 425 n2->type = NARG;
429 n2->narg.text = wordtext; 426 n2->narg.text = wordtext;
430 n2->narg.backquote = backquotelist; 427 n2->narg.backquote = backquotelist;
431 n2->narg.next = NULL; 428 n2->narg.next = NULL;
432 while (readtoken() == TNL); 429 while (readtoken() == TNL);
433 if (lasttoken != TWORD || ! equal(wordtext, "in")) 430 if (lasttoken != TWORD || ! equal(wordtext, "in"))
434 synerror("expecting \"in\""); 431 synexpect(-1, "in");
435 cpp = &n1->ncase.cases; 432 cpp = &n1->ncase.cases;
436 noalias = 1; 433 noalias = 1;
437 checkkwd = 2, readtoken(); 434 checkkwd = 2, readtoken();
438 /* 435 /*
439 * Both ksh and bash accept 'case x in esac' 436 * Both ksh and bash accept 'case x in esac'
440 * so configure scripts started taking advantage of this. 437 * so configure scripts started taking advantage of this.
441 * The page: http://pubs.opengroup.org/onlinepubs/\ 438 * The page: http://pubs.opengroup.org/onlinepubs/\
442 * 009695399/utilities/xcu_chap02.html contradicts itself, 439 * 009695399/utilities/xcu_chap02.html contradicts itself,
443 * as to if this is legal; the "Case Conditional Format" 440 * as to if this is legal; the "Case Conditional Format"
444 * paragraph shows one case is required, but the "Grammar" 441 * paragraph shows one case is required, but the "Grammar"
445 * section shows a grammar that explicitly allows the no 442 * section shows a grammar that explicitly allows the no
446 * case option. 443 * case option.
447 */ 444 */
@@ -454,87 +451,87 @@ TRACE(("expecting DO got %s %s\n", tokna @@ -454,87 +451,87 @@ TRACE(("expecting DO got %s %s\n", tokna
454 for (;;) { 451 for (;;) {
455 *app = ap = stalloc(sizeof(struct narg)); 452 *app = ap = stalloc(sizeof(struct narg));
456 ap->type = NARG; 453 ap->type = NARG;
457 ap->narg.text = wordtext; 454 ap->narg.text = wordtext;
458 ap->narg.backquote = backquotelist; 455 ap->narg.backquote = backquotelist;
459 if (checkkwd = 2, readtoken() != TPIPE) 456 if (checkkwd = 2, readtoken() != TPIPE)
460 break; 457 break;
461 app = &ap->narg.next; 458 app = &ap->narg.next;
462 readtoken(); 459 readtoken();
463 } 460 }
464 ap->narg.next = NULL; 461 ap->narg.next = NULL;
465 noalias = 0; 462 noalias = 0;
466 if (lasttoken != TRP) { 463 if (lasttoken != TRP) {
467 synexpect(TRP); 464 synexpect(TRP, 0);
468 } 465 }
469 cp->nclist.body = list(0, 0); 466 cp->nclist.body = list(0, 0);
470 467
471 checkkwd = 2; 468 checkkwd = 2;
472 if ((t = readtoken()) != TESAC) { 469 if ((t = readtoken()) != TESAC) {
473 if (t != TENDCASE) { 470 if (t != TENDCASE) {
474 noalias = 0; 471 noalias = 0;
475 synexpect(TENDCASE); 472 synexpect(TENDCASE, 0);
476 } else { 473 } else {
477 noalias = 1; 474 noalias = 1;
478 checkkwd = 2; 475 checkkwd = 2;
479 readtoken(); 476 readtoken();
480 } 477 }
481 } 478 }
482 cpp = &cp->nclist.next; 479 cpp = &cp->nclist.next;
483 } 480 }
484 noalias = 0; 481 noalias = 0;
485 *cpp = NULL; 482 *cpp = NULL;
486 checkkwd = 1; 483 checkkwd = 1;
487 break; 484 break;
488 case TLP: 485 case TLP:
489 n1 = stalloc(sizeof(struct nredir)); 486 n1 = stalloc(sizeof(struct nredir));
490 n1->type = NSUBSHELL; 487 n1->type = NSUBSHELL;
491 n1->nredir.n = list(0, 0); 488 n1->nredir.n = list(0, 0);
492 n1->nredir.redirect = NULL; 489 n1->nredir.redirect = NULL;
493 if (readtoken() != TRP) 490 if (readtoken() != TRP)
494 synexpect(TRP); 491 synexpect(TRP, 0);
495 checkkwd = 1; 492 checkkwd = 1;
496 break; 493 break;
497 case TBEGIN: 494 case TBEGIN:
498 n1 = list(0, 0); 495 n1 = list(0, 0);
499 if (readtoken() != TEND) 496 if (readtoken() != TEND)
500 synexpect(TEND); 497 synexpect(TEND, 0);
501 checkkwd = 1; 498 checkkwd = 1;
502 break; 499 break;
503 /* Handle an empty command like other simple commands. */ 500 /* Handle an empty command like other simple commands. */
504 case TSEMI: 501 case TSEMI:
505 /* 502 /*
506 * An empty command before a ; doesn't make much sense, and 503 * An empty command before a ; doesn't make much sense, and
507 * should certainly be disallowed in the case of `if ;'. 504 * should certainly be disallowed in the case of `if ;'.
508 */ 505 */
509 if (!redir) 506 if (!redir)
510 synexpect(-1); 507 synexpect(-1, 0);
511 case TAND: 508 case TAND:
512 case TOR: 509 case TOR:
513 case TNL: 510 case TNL:
514 case TEOF: 511 case TEOF:
515 case TWORD: 512 case TWORD:
516 case TRP: 513 case TRP:
517 tokpushback++; 514 tokpushback++;
518 n1 = simplecmd(rpp, redir); 515 n1 = simplecmd(rpp, redir);
519 goto checkneg; 516 goto checkneg;
520 case TENDCASE: 517 case TENDCASE:
521 if (redir) { 518 if (redir) {
522 tokpushback++; 519 tokpushback++;
523 goto checkneg; 520 goto checkneg;
524 } 521 }
525 /* FALLTHROUGH */ 522 /* FALLTHROUGH */
526 default: 523 default:
527 synexpect(-1); 524 synexpect(-1, 0);
528 /* NOTREACHED */ 525 /* NOTREACHED */
529 } 526 }
530 527
531 /* Now check for redirection which may follow command */ 528 /* Now check for redirection which may follow command */
532 while (readtoken() == TREDIR) { 529 while (readtoken() == TREDIR) {
533 *rpp = n2 = redirnode; 530 *rpp = n2 = redirnode;
534 rpp = &n2->nfile.next; 531 rpp = &n2->nfile.next;
535 parsefname(); 532 parsefname();
536 } 533 }
537 tokpushback++; 534 tokpushback++;
538 *rpp = NULL; 535 *rpp = NULL;
539 if (redir) { 536 if (redir) {
540 if (n1->type != NSUBSHELL) { 537 if (n1->type != NSUBSHELL) {
@@ -593,27 +590,27 @@ simplecmd(union node **rpp, union node * @@ -593,27 +590,27 @@ simplecmd(union node **rpp, union node *
593 n->type = NARG; 590 n->type = NARG;
594 n->narg.text = wordtext; 591 n->narg.text = wordtext;
595 n->narg.backquote = backquotelist; 592 n->narg.backquote = backquotelist;
596 *app = n; 593 *app = n;
597 app = &n->narg.next; 594 app = &n->narg.next;
598 } else if (lasttoken == TREDIR) { 595 } else if (lasttoken == TREDIR) {
599 *rpp = n = redirnode; 596 *rpp = n = redirnode;
600 rpp = &n->nfile.next; 597 rpp = &n->nfile.next;
601 parsefname(); /* read name of redirection file */ 598 parsefname(); /* read name of redirection file */
602 } else if (lasttoken == TLP && app == &args->narg.next 599 } else if (lasttoken == TLP && app == &args->narg.next
603 && rpp == orig_rpp) { 600 && rpp == orig_rpp) {
604 /* We have a function */ 601 /* We have a function */
605 if (readtoken() != TRP) 602 if (readtoken() != TRP)
606 synexpect(TRP); 603 synexpect(TRP, 0);
607 funclinno = plinno; 604 funclinno = plinno;
608 rmescapes(n->narg.text); 605 rmescapes(n->narg.text);
609 if (!goodname(n->narg.text)) 606 if (!goodname(n->narg.text))
610 synerror("Bad function name"); 607 synerror("Bad function name");
611 n->type = NDEFUN; 608 n->type = NDEFUN;
612 n->narg.next = command(); 609 n->narg.next = command();
613 funclinno = 0; 610 funclinno = 0;
614 goto checkneg; 611 goto checkneg;
615 } else { 612 } else {
616 tokpushback++; 613 tokpushback++;
617 break; 614 break;
618 } 615 }
619 } 616 }
@@ -667,27 +664,27 @@ fixredir(union node *n, const char *text @@ -667,27 +664,27 @@ fixredir(union node *n, const char *text
667 synerror("Bad fd number"); 664 synerror("Bad fd number");
668 else 665 else
669 n->ndup.vname = makename(); 666 n->ndup.vname = makename();
670 } 667 }
671} 668}
672 669
673 670
674STATIC void 671STATIC void
675parsefname(void) 672parsefname(void)
676{ 673{
677 union node *n = redirnode; 674 union node *n = redirnode;
678 675
679 if (readtoken() != TWORD) 676 if (readtoken() != TWORD)
680 synexpect(-1); 677 synexpect(-1, 0);
681 if (n->type == NHERE) { 678 if (n->type == NHERE) {
682 struct heredoc *here = heredoc; 679 struct heredoc *here = heredoc;
683 struct heredoc *p; 680 struct heredoc *p;
684 int i; 681 int i;
685 682
686 if (quoteflag == 0) 683 if (quoteflag == 0)
687 n->type = NXHERE; 684 n->type = NXHERE;
688 TRACE(("Here document %d\n", n->type)); 685 TRACE(("Here document %d\n", n->type));
689 if (here->striptabs) { 686 if (here->striptabs) {
690 while (*wordtext == '\t') 687 while (*wordtext == '\t')
691 wordtext++; 688 wordtext++;
692 } 689 }
693 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) 690 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
@@ -842,73 +839,74 @@ xxreadtoken(void) @@ -842,73 +839,74 @@ xxreadtoken(void)
842 needprompt = 0; 839 needprompt = 0;
843 } 840 }
844 startlinno = plinno; 841 startlinno = plinno;
845 for (;;) { /* until token or start of word found */ 842 for (;;) { /* until token or start of word found */
846 c = pgetc_macro(); 843 c = pgetc_macro();
847 switch (c) { 844 switch (c) {
848 case ' ': case '\t': 845 case ' ': case '\t':
849 continue; 846 continue;
850 case '#': 847 case '#':
851 while ((c = pgetc()) != '\n' && c != PEOF) 848 while ((c = pgetc()) != '\n' && c != PEOF)
852 continue; 849 continue;
853 pungetc(); 850 pungetc();
854 continue; 851 continue;
855 case '\\': 852
856 switch (pgetc()) { 
857 case '\n': 
858 startlinno = ++plinno; 
859 if (doprompt) 
860 setprompt(2); 
861 else 
862 setprompt(0); 
863 continue; 
864 case PEOF: 
865 RETURN(TEOF); 
866 default: 
867 pungetc(); 
868 break; 
869 } 
870 goto breakloop; 
871 case '\n': 853 case '\n':
872 plinno++; 854 plinno++;
873 needprompt = doprompt; 855 needprompt = doprompt;
874 RETURN(TNL); 856 RETURN(TNL);
875 case PEOF: 857 case PEOF:
876 RETURN(TEOF); 858 RETURN(TEOF);
 859
877 case '&': 860 case '&':
878 if (pgetc() == '&') 861 if (pgetc() == '&')
879 RETURN(TAND); 862 RETURN(TAND);
880 pungetc(); 863 pungetc();
881 RETURN(TBACKGND); 864 RETURN(TBACKGND);
882 case '|': 865 case '|':
883 if (pgetc() == '|') 866 if (pgetc() == '|')
884 RETURN(TOR); 867 RETURN(TOR);
885 pungetc(); 868 pungetc();
886 RETURN(TPIPE); 869 RETURN(TPIPE);
887 case ';': 870 case ';':
888 if (pgetc() == ';') 871 if (pgetc() == ';')
889 RETURN(TENDCASE); 872 RETURN(TENDCASE);
890 pungetc(); 873 pungetc();
891 RETURN(TSEMI); 874 RETURN(TSEMI);
892 case '(': 875 case '(':
893 RETURN(TLP); 876 RETURN(TLP);
894 case ')': 877 case ')':
895 RETURN(TRP); 878 RETURN(TRP);
 879
 880 case '\\':
 881 switch (pgetc()) {
 882 case '\n':
 883 startlinno = ++plinno;
 884 if (doprompt)
 885 setprompt(2);
 886 else
 887 setprompt(0);
 888 continue;
 889 case PEOF:
 890 RETURN(TEOF);
 891 default:
 892 pungetc();
 893 break;
 894 }
 895 /* FALLTHROUGH */
896 default: 896 default:
897 goto breakloop; 897 return readtoken1(c, BASESYNTAX, NULL, 0);
898 } 898 }
899 } 899 }
900breakloop: 
901 return readtoken1(c, BASESYNTAX, NULL, 0); 
902#undef RETURN 900#undef RETURN
903} 901}
904 902
905 903
906 904
907/* 905/*
908 * If eofmark is NULL, read a word or a redirection symbol. If eofmark 906 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
909 * is not NULL, read a here document. In the latter case, eofmark is the 907 * is not NULL, read a here document. In the latter case, eofmark is the
910 * word which marks the end of the document and striptabs is true if 908 * word which marks the end of the document and striptabs is true if
911 * leading tabs should be stripped from the document. The argument firstc 909 * leading tabs should be stripped from the document. The argument firstc
912 * is the first character of the input token or document. 910 * is the first character of the input token or document.
913 * 911 *
914 * Because C does not have internal subroutines, I have simulated them 912 * Because C does not have internal subroutines, I have simulated them
@@ -1199,27 +1197,27 @@ done: @@ -1199,27 +1197,27 @@ done:
1199 if (oldstyle) { 1197 if (oldstyle) {
1200 saveprompt = doprompt; 1198 saveprompt = doprompt;
1201 doprompt = 0; 1199 doprompt = 0;
1202 } else 1200 } else
1203 saveprompt = 0; 1201 saveprompt = 0;
1204 1202
1205 n = list(0, oldstyle); 1203 n = list(0, oldstyle);
1206 1204
1207 if (oldstyle) 1205 if (oldstyle)
1208 doprompt = saveprompt; 1206 doprompt = saveprompt;
1209 else { 1207 else {
1210 if (readtoken() != TRP) { 1208 if (readtoken() != TRP) {
1211 cleanup_state_stack(stack); 1209 cleanup_state_stack(stack);
1212 synexpect(TRP); 1210 synexpect(TRP, 0);
1213 } 1211 }
1214 } 1212 }
1215 1213
1216 (*nlpp)->n = n; 1214 (*nlpp)->n = n;
1217 if (oldstyle) { 1215 if (oldstyle) {
1218 /* 1216 /*
1219 * Start reading from old file again, ignoring any pushed back 1217 * Start reading from old file again, ignoring any pushed back
1220 * tokens left from the backquote parsing 1218 * tokens left from the backquote parsing
1221 */ 1219 */
1222 popfile(); 1220 popfile();
1223 tokpushback = 0; 1221 tokpushback = 0;
1224 } 1222 }
1225 while (stackblocksize() <= savelen) 1223 while (stackblocksize() <= savelen)
@@ -1253,46 +1251,35 @@ readtoken1(int firstc, char const *syn,  @@ -1253,46 +1251,35 @@ readtoken1(int firstc, char const *syn,
1253 struct nodelist *bqlist; 1251 struct nodelist *bqlist;
1254 int quotef; 1252 int quotef;
1255 VSS static_stack; 1253 VSS static_stack;
1256 VSS *stack = &static_stack; 1254 VSS *stack = &static_stack;
1257 1255
1258 stack->prev = NULL; 1256 stack->prev = NULL;
1259 stack->cur = 0; 1257 stack->cur = 0;
1260 1258
1261 syntax = syn; 1259 syntax = syn;
1262 1260
1263 startlinno = plinno; 1261 startlinno = plinno;
1264 varnest = 0; 1262 varnest = 0;
1265 quoted = 0; 1263 quoted = 0;
1266 if (syntax == DQSYNTAX) { 1264 if (syntax == DQSYNTAX)
1267 SETDBLQUOTE(); 1265 SETDBLQUOTE();
1268 } 
1269 quotef = 0; 1266 quotef = 0;
1270 bqlist = NULL; 1267 bqlist = NULL;
1271 arinest = 0; 1268 arinest = 0;
1272 parenlevel = 0; 1269 parenlevel = 0;
1273 1270
1274 STARTSTACKSTR(out); 1271 STARTSTACKSTR(out);
1275 loop: { /* for each line, until end of word */ 1272 loop: { /* for each line, until end of word */
1276#if ATTY 
1277 if (c == '\034' && doprompt 
1278 && attyset() && ! equal(termval(), "emacs")) { 
1279 attyline(); 
1280 if (syntax == BASESYNTAX) 
1281 return readtoken(); 
1282 c = pgetc(); 
1283 goto loop; 
1284 } 
1285#endif 
1286 CHECKEND(); /* set c to PEOF if at end of here document */ 1273 CHECKEND(); /* set c to PEOF if at end of here document */
1287 for (;;) { /* until end of line or end of word */ 1274 for (;;) { /* until end of line or end of word */
1288 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ 1275 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
1289 switch(syntax[c]) { 1276 switch(syntax[c]) {
1290 case CNL: /* '\n' */ 1277 case CNL: /* '\n' */
1291 if (syntax == BASESYNTAX) 1278 if (syntax == BASESYNTAX)
1292 goto endword; /* exit outer loop */ 1279 goto endword; /* exit outer loop */
1293 USTPUTC(c, out); 1280 USTPUTC(c, out);
1294 plinno++; 1281 plinno++;
1295 if (doprompt) 1282 if (doprompt)
1296 setprompt(2); 1283 setprompt(2);
1297 else 1284 else
1298 setprompt(0); 1285 setprompt(0);
@@ -1769,91 +1756,97 @@ noexpand(char *text) @@ -1769,91 +1756,97 @@ noexpand(char *text)
1769 return 0; 1756 return 0;
1770 } 1757 }
1771 return 1; 1758 return 1;
1772} 1759}
1773 1760
1774 1761
1775/* 1762/*
1776 * Return true if the argument is a legal variable name (a letter or 1763 * Return true if the argument is a legal variable name (a letter or
1777 * underscore followed by zero or more letters, underscores, and digits). 1764 * underscore followed by zero or more letters, underscores, and digits).
1778 */ 1765 */
1779 1766
1780int 1767int
1781goodname(char *name) 1768goodname(char *name)
1782 { 1769{
1783 char *p; 1770 char *p;
1784 1771
1785 p = name; 1772 p = name;
1786 if (! is_name(*p)) 1773 if (! is_name(*p))
1787 return 0; 1774 return 0;
1788 while (*++p) { 1775 while (*++p) {
1789 if (! is_in_name(*p)) 1776 if (! is_in_name(*p))
1790 return 0; 1777 return 0;
1791 } 1778 }
1792 return 1; 1779 return 1;
1793} 1780}
1794 1781
1795 1782
1796/* 1783/*
1797 * Called when an unexpected token is read during the parse. The argument 1784 * Called when an unexpected token is read during the parse. The argument
1798 * is the token that is expected, or -1 if more than one type of token can 1785 * is the token that is expected, or -1 if more than one type of token can
1799 * occur at this point. 1786 * occur at this point.
1800 */ 1787 */
1801 1788
1802STATIC void 1789STATIC void
1803synexpect(int token) 1790synexpect(int token, const char *text)
1804{ 1791{
1805 char msg[64]; 1792 char msg[64];
 1793 char *p;
 1794
 1795 if (lasttoken == TWORD) {
 1796 size_t len = strlen(wordtext);
 1797
 1798 if (len <= 13)
 1799 fmtstr(msg, 34, "Word \"%.13s\" unexpected", wordtext);
 1800 else
 1801 fmtstr(msg, 34,
 1802 "Word \"%.10s...\" unexpected", wordtext);
 1803 } else
 1804 fmtstr(msg, 34, "%s unexpected", tokname[lasttoken]);
 1805
 1806 p = strchr(msg, '\0');
 1807 if (text)
 1808 fmtstr(p, 30, " (expecting \"%.10s\")", text);
 1809 else if (token >= 0)
 1810 fmtstr(p, 30, " (expecting %s)", tokname[token]);
1806 1811
1807 if (token >= 0) { 
1808 fmtstr(msg, 64, "%s unexpected (expecting %s)", 
1809 tokname[lasttoken], tokname[token]); 
1810 } else { 
1811 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); 
1812 } 
1813 synerror(msg); 1812 synerror(msg);
1814 /* NOTREACHED */ 1813 /* NOTREACHED */
1815} 1814}
1816 1815
1817 1816
1818STATIC void 1817STATIC void
1819synerror(const char *msg) 1818synerror(const char *msg)
1820{ 1819{
1821 if (commandname) 1820 error("%d: Syntax error: %s\n", startlinno, msg);
1822 outfmt(&errout, "%s: %d: ", commandname, startlinno); 
1823 else 
1824 outfmt(&errout, "%s: ", getprogname()); 
1825 outfmt(&errout, "Syntax error: %s\n", msg); 
1826 error(NULL); 
1827 /* NOTREACHED */ 1821 /* NOTREACHED */
1828} 1822}
1829 1823
1830STATIC void 1824STATIC void
1831setprompt(int which) 1825setprompt(int which)
1832{ 1826{
1833 whichprompt = which; 1827 whichprompt = which;
1834 1828
1835#ifndef SMALL 1829#ifndef SMALL
1836 if (!el) 1830 if (!el)
1837#endif 1831#endif
1838 out2str(getprompt(NULL)); 1832 out2str(getprompt(NULL));
1839} 1833}
1840 1834
1841/* 1835/*
1842 * called by editline -- any expansions to the prompt 1836 * called by editline -- any expansions to the prompt
1843 * should be added here. 1837 * should be added here.
1844 */ 1838 */
1845const char * 1839const char *
1846getprompt(void *unused) 1840getprompt(void *unused)
1847 { 1841{
1848 switch (whichprompt) { 1842 switch (whichprompt) {
1849 case 0: 1843 case 0:
1850 return ""; 1844 return "";
1851 case 1: 1845 case 1:
1852 return ps1val(); 1846 return ps1val();
1853 case 2: 1847 case 2:
1854 return ps2val(); 1848 return ps2val();
1855 default: 1849 default:
1856 return "<internal prompt error>"; 1850 return "<internal prompt error>";
1857 } 1851 }
1858} 1852}
1859 

cvs diff -r1.26 -r1.27 src/bin/sh/var.h (expand / switch to unified 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,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.h,v 1.26 2015/05/26 21:35:15 christos Exp $ */ 1/* $NetBSD: var.h,v 1.27 2016/03/27 14:34:46 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -60,65 +60,60 @@ struct var { @@ -60,65 +60,60 @@ struct var {
60}; 60};
61 61
62 62
63struct localvar { 63struct localvar {
64 struct localvar *next; /* next local variable in list */ 64 struct localvar *next; /* next local variable in list */
65 struct var *vp; /* the variable that was made local */ 65 struct var *vp; /* the variable that was made local */
66 int flags; /* saved flags */ 66 int flags; /* saved flags */
67 char *text; /* saved text */ 67 char *text; /* saved text */
68}; 68};
69 69
70 70
71extern struct localvar *localvars; 71extern struct localvar *localvars;
72 72
73#if ATTY 
74extern struct var vatty; 
75#endif 
76extern struct var vifs; 73extern struct var vifs;
 74extern char ifs_default[];
77extern struct var vmail; 75extern struct var vmail;
78extern struct var vmpath; 76extern struct var vmpath;
79extern struct var vpath; 77extern struct var vpath;
80extern struct var vps1; 78extern struct var vps1;
81extern struct var vps2; 79extern struct var vps2;
82extern struct var vps4; 80extern struct var vps4;
83#ifndef SMALL 81#ifndef SMALL
84extern struct var vterm; 82extern struct var vterm;
85extern struct var vtermcap; 83extern struct var vtermcap;
86extern struct var vhistsize; 84extern struct var vhistsize;
87#endif 85#endif
88 86
89/* 87/*
90 * The following macros access the values of the above variables. 88 * The following macros access the values of the above variables.
91 * They have to skip over the name. They return the null string 89 * They have to skip over the name. They return the null string
92 * for unset variables. 90 * for unset variables.
93 */ 91 */
94 92
95#define ifsval() (vifs.text + 4) 
96#define ifsset() ((vifs.flags & VUNSET) == 0) 93#define ifsset() ((vifs.flags & VUNSET) == 0)
 94#define ifsval() (ifsset() ? (vifs.text + 4) : ifs_default)
97#define mailval() (vmail.text + 5) 95#define mailval() (vmail.text + 5)
98#define mpathval() (vmpath.text + 9) 96#define mpathval() (vmpath.text + 9)
99#define pathval() (vpath.text + 5) 97#define pathval() (vpath.text + 5)
100#define ps1val() (vps1.text + 4) 98#define ps1val() (vps1.text + 4)
101#define ps2val() (vps2.text + 4) 99#define ps2val() (vps2.text + 4)
102#define ps4val() (vps4.text + 4) 100#define ps4val() (vps4.text + 4)
103#define optindval() (voptind.text + 7) 101#define optindval() (voptind.text + 7)
104#ifndef SMALL 102#ifndef SMALL
105#define histsizeval() (vhistsize.text + 9) 103#define histsizeval() (vhistsize.text + 9)
106#define termval() (vterm.text + 5) 104#define termval() (vterm.text + 5)
107#endif 105#endif
108 106
109#if ATTY 
110#define attyset() ((vatty.flags & VUNSET) == 0) 
111#endif 
112#define mpathset() ((vmpath.flags & VUNSET) == 0) 107#define mpathset() ((vmpath.flags & VUNSET) == 0)
113 108
114void initvar(void); 109void initvar(void);
115void setvar(const char *, const char *, int); 110void setvar(const char *, const char *, int);
116void setvareq(char *, int); 111void setvareq(char *, int);
117struct strlist; 112struct strlist;
118void listsetvar(struct strlist *, int); 113void listsetvar(struct strlist *, int);
119char *lookupvar(const char *); 114char *lookupvar(const char *);
120char *bltinlookup(const char *, int); 115char *bltinlookup(const char *, int);
121char **environment(void); 116char **environment(void);
122void shprocvar(void); 117void shprocvar(void);
123int showvars(const char *, int, int); 118int showvars(const char *, int, int);
124void mklocal(const char *, int); 119void mklocal(const char *, int);