Sun Mar 27 14:39:33 2016 UTC ()
PR bin/50993 - this is a significant rewrite of the way that here
documents are processed.  Now, when first detected, they are
simply read (the only change made to the text is to join lines
ended with a \ to the subsequent line, otherwise end marker detection
does not work correctly (for here docs with an unquoted endmarker
only of course.)  This patch also moves the "internal subroutine"
for looking for the end marker out of readtoken1() (which had to
happen as readtoken1 is no longer reading the here doc when it is
needed) - that uses code mostly taken from FreeBSD's sh (thanks!)
and along the way results in some restrictions on what the end
marker can be being removed.   We still do not allow all we should.
(from kre@)


(christos)
diff -r1.98 -r1.99 src/bin/sh/expand.c
diff -r1.110 -r1.111 src/bin/sh/parser.c
diff -r1.19 -r1.20 src/bin/sh/parser.h

cvs diff -r1.98 -r1.99 src/bin/sh/expand.c (switch to unified diff)

--- src/bin/sh/expand.c 2016/03/27 14:34:46 1.98
+++ src/bin/sh/expand.c 2016/03/27 14:39:33 1.99
@@ -1,1122 +1,1128 @@ @@ -1,1122 +1,1128 @@
1/* $NetBSD: expand.c,v 1.98 2016/03/27 14:34:46 christos Exp $ */ 1/* $NetBSD: expand.c,v 1.99 2016/03/27 14:39:33 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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.98 2016/03/27 14:34:46 christos Exp $"); 40__RCSID("$NetBSD: expand.c,v 1.99 2016/03/27 14:39:33 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>
54#include <wctype.h> 54#include <wctype.h>
55 55
56/* 56/*
57 * Routines to expand arguments to commands. We have to deal with 57 * Routines to expand arguments to commands. We have to deal with
58 * backquotes, shell variables, and file metacharacters. 58 * backquotes, shell variables, and file metacharacters.
59 */ 59 */
60 60
61#include "shell.h" 61#include "shell.h"
62#include "main.h" 62#include "main.h"
63#include "nodes.h" 63#include "nodes.h"
64#include "eval.h" 64#include "eval.h"
65#include "expand.h" 65#include "expand.h"
66#include "syntax.h" 66#include "syntax.h"
67#include "parser.h" 67#include "parser.h"
68#include "jobs.h" 68#include "jobs.h"
69#include "options.h" 69#include "options.h"
70#include "builtins.h" 70#include "builtins.h"
71#include "var.h" 71#include "var.h"
72#include "input.h" 72#include "input.h"
73#include "output.h" 73#include "output.h"
74#include "memalloc.h" 74#include "memalloc.h"
75#include "error.h" 75#include "error.h"
76#include "mystring.h" 76#include "mystring.h"
77#include "show.h" 77#include "show.h"
78 78
79/* 79/*
80 * Structure specifying which parts of the string should be searched 80 * Structure specifying which parts of the string should be searched
81 * for IFS characters. 81 * for IFS characters.
82 */ 82 */
83 83
84struct ifsregion { 84struct ifsregion {
85 struct ifsregion *next; /* next region in list */ 85 struct ifsregion *next; /* next region in list */
86 int begoff; /* offset of start of region */ 86 int begoff; /* offset of start of region */
87 int endoff; /* offset of end of region */ 87 int endoff; /* offset of end of region */
88 int inquotes; /* search for nul bytes only */ 88 int inquotes; /* search for nul bytes only */
89}; 89};
90 90
91 91
92char *expdest; /* output of current string */ 92char *expdest; /* output of current string */
93struct nodelist *argbackq; /* list of back quote expressions */ 93struct nodelist *argbackq; /* list of back quote expressions */
94struct ifsregion ifsfirst; /* first struct in list of ifs regions */ 94struct ifsregion ifsfirst; /* first struct in list of ifs regions */
95struct ifsregion *ifslastp; /* last struct in list */ 95struct ifsregion *ifslastp; /* last struct in list */
96struct arglist exparg; /* holds expanded arg list */ 96struct arglist exparg; /* holds expanded arg list */
97 97
98STATIC void argstr(char *, int); 98STATIC void argstr(char *, int);
99STATIC char *exptilde(char *, int); 99STATIC char *exptilde(char *, int);
100STATIC void expbackq(union node *, int, int); 100STATIC void expbackq(union node *, int, int);
101STATIC int subevalvar(char *, char *, int, int, int, int, int); 101STATIC int subevalvar(char *, char *, int, int, int, int, int);
102STATIC char *evalvar(char *, int); 102STATIC char *evalvar(char *, int);
103STATIC int varisset(char *, int); 103STATIC int varisset(char *, int);
104STATIC void varvalue(char *, int, int, int); 104STATIC void varvalue(char *, int, int, int);
105STATIC void recordregion(int, int, int); 105STATIC void recordregion(int, int, int);
106STATIC void removerecordregions(int);  106STATIC void removerecordregions(int);
107STATIC void ifsbreakup(char *, struct arglist *); 107STATIC void ifsbreakup(char *, struct arglist *);
108STATIC void ifsfree(void); 108STATIC void ifsfree(void);
109STATIC void expandmeta(struct strlist *, int); 109STATIC void expandmeta(struct strlist *, int);
110STATIC void expmeta(char *, char *); 110STATIC void expmeta(char *, char *);
111STATIC void addfname(char *); 111STATIC void addfname(char *);
112STATIC struct strlist *expsort(struct strlist *); 112STATIC struct strlist *expsort(struct strlist *);
113STATIC struct strlist *msort(struct strlist *, int); 113STATIC struct strlist *msort(struct strlist *, int);
114STATIC int pmatch(char *, char *, int); 114STATIC int pmatch(char *, char *, int);
115STATIC char *cvtnum(int, char *); 115STATIC char *cvtnum(int, char *);
116 116
117/* 117/*
118 * Expand shell variables and backquotes inside a here document. 118 * Expand shell variables and backquotes inside a here document.
119 */ 119 */
120 120
121void 121void
122expandhere(union node *arg, int fd) 122expandhere(union node *arg, int fd)
123{ 123{
 124 /*
 125 * First, parse the content of the here doc (to internal form)
 126 * It was initially saved as (almost) unmodified text.
 127 */
 128 parse_heredoc(arg);
 129
124 herefd = fd; 130 herefd = fd;
125 expandarg(arg, NULL, 0); 131 expandarg(arg, NULL, 0);
126 xwrite(fd, stackblock(), expdest - stackblock()); 132 xwrite(fd, stackblock(), expdest - stackblock());
127} 133}
128 134
129 135
130/* 136/*
131 * Perform variable substitution and command substitution on an argument, 137 * Perform variable substitution and command substitution on an argument,
132 * placing the resulting list of arguments in arglist. If EXP_FULL is true, 138 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
133 * perform splitting and file name expansion. When arglist is NULL, perform 139 * perform splitting and file name expansion. When arglist is NULL, perform
134 * here document expansion. 140 * here document expansion.
135 */ 141 */
136 142
137void 143void
138expandarg(union node *arg, struct arglist *arglist, int flag) 144expandarg(union node *arg, struct arglist *arglist, int flag)
139{ 145{
140 struct strlist *sp; 146 struct strlist *sp;
141 char *p; 147 char *p;
142 148
143 argbackq = arg->narg.backquote; 149 argbackq = arg->narg.backquote;
144 STARTSTACKSTR(expdest); 150 STARTSTACKSTR(expdest);
145 ifsfirst.next = NULL; 151 ifsfirst.next = NULL;
146 ifslastp = NULL; 152 ifslastp = NULL;
147 argstr(arg->narg.text, flag); 153 argstr(arg->narg.text, flag);
148 if (arglist == NULL) { 154 if (arglist == NULL) {
149 return; /* here document expanded */ 155 return; /* here document expanded */
150 } 156 }
151 STPUTC('\0', expdest); 157 STPUTC('\0', expdest);
152 p = grabstackstr(expdest); 158 p = grabstackstr(expdest);
153 exparg.lastp = &exparg.list; 159 exparg.lastp = &exparg.list;
154 /* 160 /*
155 * TODO - EXP_REDIR 161 * TODO - EXP_REDIR
156 */ 162 */
157 if (flag & EXP_FULL) { 163 if (flag & EXP_FULL) {
158 ifsbreakup(p, &exparg); 164 ifsbreakup(p, &exparg);
159 *exparg.lastp = NULL; 165 *exparg.lastp = NULL;
160 exparg.lastp = &exparg.list; 166 exparg.lastp = &exparg.list;
161 expandmeta(exparg.list, flag); 167 expandmeta(exparg.list, flag);
162 } else { 168 } else {
163 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ 169 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
164 rmescapes(p); 170 rmescapes(p);
165 sp = stalloc(sizeof(*sp)); 171 sp = stalloc(sizeof(*sp));
166 sp->text = p; 172 sp->text = p;
167 *exparg.lastp = sp; 173 *exparg.lastp = sp;
168 exparg.lastp = &sp->next; 174 exparg.lastp = &sp->next;
169 } 175 }
170 ifsfree(); 176 ifsfree();
171 *exparg.lastp = NULL; 177 *exparg.lastp = NULL;
172 if (exparg.list) { 178 if (exparg.list) {
173 *arglist->lastp = exparg.list; 179 *arglist->lastp = exparg.list;
174 arglist->lastp = exparg.lastp; 180 arglist->lastp = exparg.lastp;
175 } 181 }
176} 182}
177 183
178 184
179 185
180/* 186/*
181 * Perform variable and command substitution. 187 * Perform variable and command substitution.
182 * If EXP_FULL is set, output CTLESC characters to allow for further processing. 188 * If EXP_FULL is set, output CTLESC characters to allow for further processing.
183 * Otherwise treat $@ like $* since no splitting will be performed. 189 * Otherwise treat $@ like $* since no splitting will be performed.
184 */ 190 */
185 191
186STATIC void 192STATIC void
187argstr(char *p, int flag) 193argstr(char *p, int flag)
188{ 194{
189 char c; 195 char c;
190 int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */ 196 int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
191 int firsteq = 1; 197 int firsteq = 1;
192 const char *ifs = NULL; 198 const char *ifs = NULL;
193 int ifs_split = EXP_IFS_SPLIT; 199 int ifs_split = EXP_IFS_SPLIT;
194 200
195 if (flag & EXP_IFS_SPLIT) 201 if (flag & EXP_IFS_SPLIT)
196 ifs = ifsval(); 202 ifs = ifsval();
197 203
198 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) 204 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
199 p = exptilde(p, flag); 205 p = exptilde(p, flag);
200 for (;;) { 206 for (;;) {
201 switch (c = *p++) { 207 switch (c = *p++) {
202 case '\0': 208 case '\0':
203 case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */ 209 case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
204 return; 210 return;
205 case CTLQUOTEMARK: 211 case CTLQUOTEMARK:
206 /* "$@" syntax adherence hack */ 212 /* "$@" syntax adherence hack */
207 if (p[0] == CTLVAR && p[1] & VSQUOTE && 213 if (p[0] == CTLVAR && p[1] & VSQUOTE &&
208 p[2] == '@' && p[3] == '=') 214 p[2] == '@' && p[3] == '=')
209 break; 215 break;
210 if ((flag & EXP_FULL) != 0) 216 if ((flag & EXP_FULL) != 0)
211 STPUTC(c, expdest); 217 STPUTC(c, expdest);
212 ifs_split = 0; 218 ifs_split = 0;
213 break; 219 break;
214 case CTLQUOTEEND: 220 case CTLQUOTEEND:
215 ifs_split = EXP_IFS_SPLIT; 221 ifs_split = EXP_IFS_SPLIT;
216 break; 222 break;
217 case CTLESC: 223 case CTLESC:
218 if (quotes) 224 if (quotes)
219 STPUTC(c, expdest); 225 STPUTC(c, expdest);
220 c = *p++; 226 c = *p++;
221 STPUTC(c, expdest); 227 STPUTC(c, expdest);
222 break; 228 break;
223 case CTLVAR: 229 case CTLVAR:
224 p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split)); 230 p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
225 break; 231 break;
226 case CTLBACKQ: 232 case CTLBACKQ:
227 case CTLBACKQ|CTLQUOTE: 233 case CTLBACKQ|CTLQUOTE:
228 expbackq(argbackq->n, c & CTLQUOTE, flag); 234 expbackq(argbackq->n, c & CTLQUOTE, flag);
229 argbackq = argbackq->next; 235 argbackq = argbackq->next;
230 break; 236 break;
231 case CTLENDARI: 237 case CTLENDARI:
232 expari(flag); 238 expari(flag);
233 break; 239 break;
234 case ':': 240 case ':':
235 case '=': 241 case '=':
236 /* 242 /*
237 * sort of a hack - expand tildes in variable 243 * sort of a hack - expand tildes in variable
238 * assignments (after the first '=' and after ':'s). 244 * assignments (after the first '=' and after ':'s).
239 */ 245 */
240 STPUTC(c, expdest); 246 STPUTC(c, expdest);
241 if (flag & EXP_VARTILDE && *p == '~') { 247 if (flag & EXP_VARTILDE && *p == '~') {
242 if (c == '=') { 248 if (c == '=') {
243 if (firsteq) 249 if (firsteq)
244 firsteq = 0; 250 firsteq = 0;
245 else 251 else
246 break; 252 break;
247 } 253 }
248 p = exptilde(p, flag); 254 p = exptilde(p, flag);
249 } 255 }
250 break; 256 break;
251 default: 257 default:
252 STPUTC(c, expdest); 258 STPUTC(c, expdest);
253 if (flag & ifs_split && strchr(ifs, c) != NULL) { 259 if (flag & ifs_split && strchr(ifs, c) != NULL) {
254 /* We need to get the output split here... */ 260 /* We need to get the output split here... */
255 recordregion(expdest - stackblock() - 1, 261 recordregion(expdest - stackblock() - 1,
256 expdest - stackblock(), 0); 262 expdest - stackblock(), 0);
257 } 263 }
258 break; 264 break;
259 } 265 }
260 } 266 }
261} 267}
262 268
263STATIC char * 269STATIC char *
264exptilde(char *p, int flag) 270exptilde(char *p, int flag)
265{ 271{
266 char c, *startp = p; 272 char c, *startp = p;
267 struct passwd *pw; 273 struct passwd *pw;
268 const char *home; 274 const char *home;
269 int quotes = flag & (EXP_FULL | EXP_CASE); 275 int quotes = flag & (EXP_FULL | EXP_CASE);
270 276
271 while ((c = *p) != '\0') { 277 while ((c = *p) != '\0') {
272 switch(c) { 278 switch(c) {
273 case CTLESC: 279 case CTLESC:
274 return (startp); 280 return (startp);
275 case CTLQUOTEMARK: 281 case CTLQUOTEMARK:
276 return (startp); 282 return (startp);
277 case ':': 283 case ':':
278 if (flag & EXP_VARTILDE) 284 if (flag & EXP_VARTILDE)
279 goto done; 285 goto done;
280 break; 286 break;
281 case '/': 287 case '/':
282 goto done; 288 goto done;
283 } 289 }
284 p++; 290 p++;
285 } 291 }
286done: 292done:
287 *p = '\0'; 293 *p = '\0';
288 if (*(startp+1) == '\0') { 294 if (*(startp+1) == '\0') {
289 if ((home = lookupvar("HOME")) == NULL) 295 if ((home = lookupvar("HOME")) == NULL)
290 goto lose; 296 goto lose;
291 } else { 297 } else {
292 if ((pw = getpwnam(startp+1)) == NULL) 298 if ((pw = getpwnam(startp+1)) == NULL)
293 goto lose; 299 goto lose;
294 home = pw->pw_dir; 300 home = pw->pw_dir;
295 } 301 }
296 if (*home == '\0') 302 if (*home == '\0')
297 goto lose; 303 goto lose;
298 *p = c; 304 *p = c;
299 while ((c = *home++) != '\0') { 305 while ((c = *home++) != '\0') {
300 if (quotes && SQSYNTAX[(int)c] == CCTL) 306 if (quotes && SQSYNTAX[(int)c] == CCTL)
301 STPUTC(CTLESC, expdest); 307 STPUTC(CTLESC, expdest);
302 STPUTC(c, expdest); 308 STPUTC(c, expdest);
303 } 309 }
304 return (p); 310 return (p);
305lose: 311lose:
306 *p = c; 312 *p = c;
307 return (startp); 313 return (startp);
308} 314}
309 315
310 316
311STATIC void  317STATIC void
312removerecordregions(int endoff) 318removerecordregions(int endoff)
313{ 319{
314 if (ifslastp == NULL) 320 if (ifslastp == NULL)
315 return; 321 return;
316 322
317 if (ifsfirst.endoff > endoff) { 323 if (ifsfirst.endoff > endoff) {
318 while (ifsfirst.next != NULL) { 324 while (ifsfirst.next != NULL) {
319 struct ifsregion *ifsp; 325 struct ifsregion *ifsp;
320 INTOFF; 326 INTOFF;
321 ifsp = ifsfirst.next->next; 327 ifsp = ifsfirst.next->next;
322 ckfree(ifsfirst.next); 328 ckfree(ifsfirst.next);
323 ifsfirst.next = ifsp; 329 ifsfirst.next = ifsp;
324 INTON; 330 INTON;
325 } 331 }
326 if (ifsfirst.begoff > endoff) 332 if (ifsfirst.begoff > endoff)
327 ifslastp = NULL; 333 ifslastp = NULL;
328 else { 334 else {
329 ifslastp = &ifsfirst; 335 ifslastp = &ifsfirst;
330 ifsfirst.endoff = endoff; 336 ifsfirst.endoff = endoff;
331 } 337 }
332 return; 338 return;
333 } 339 }
334 340
335 ifslastp = &ifsfirst; 341 ifslastp = &ifsfirst;
336 while (ifslastp->next && ifslastp->next->begoff < endoff) 342 while (ifslastp->next && ifslastp->next->begoff < endoff)
337 ifslastp=ifslastp->next; 343 ifslastp=ifslastp->next;
338 while (ifslastp->next != NULL) { 344 while (ifslastp->next != NULL) {
339 struct ifsregion *ifsp; 345 struct ifsregion *ifsp;
340 INTOFF; 346 INTOFF;
341 ifsp = ifslastp->next->next; 347 ifsp = ifslastp->next->next;
342 ckfree(ifslastp->next); 348 ckfree(ifslastp->next);
343 ifslastp->next = ifsp; 349 ifslastp->next = ifsp;
344 INTON; 350 INTON;
345 } 351 }
346 if (ifslastp->endoff > endoff) 352 if (ifslastp->endoff > endoff)
347 ifslastp->endoff = endoff; 353 ifslastp->endoff = endoff;
348} 354}
349 355
350 356
351/* 357/*
352 * Expand arithmetic expression. Backup to start of expression, 358 * Expand arithmetic expression. Backup to start of expression,
353 * evaluate, place result in (backed up) result, adjust string position. 359 * evaluate, place result in (backed up) result, adjust string position.
354 */ 360 */
355void 361void
356expari(int flag) 362expari(int flag)
357{ 363{
358 char *p, *start; 364 char *p, *start;
359 intmax_t result; 365 intmax_t result;
360 int adjustment; 366 int adjustment;
361 int begoff; 367 int begoff;
362 int quotes = flag & (EXP_FULL | EXP_CASE); 368 int quotes = flag & (EXP_FULL | EXP_CASE);
363 int quoted; 369 int quoted;
364 370
365 /* ifsfree(); */ 371 /* ifsfree(); */
366 372
367 /* 373 /*
368 * This routine is slightly over-complicated for 374 * This routine is slightly over-complicated for
369 * efficiency. First we make sure there is 375 * efficiency. First we make sure there is
370 * enough space for the result, which may be bigger 376 * enough space for the result, which may be bigger
371 * than the expression if we add exponentation. Next we 377 * than the expression if we add exponentation. Next we
372 * scan backwards looking for the start of arithmetic. If the 378 * scan backwards looking for the start of arithmetic. If the
373 * next previous character is a CTLESC character, then we 379 * next previous character is a CTLESC character, then we
374 * have to rescan starting from the beginning since CTLESC 380 * have to rescan starting from the beginning since CTLESC
375 * characters have to be processed left to right. 381 * characters have to be processed left to right.
376 */ 382 */
377/* SPACE_NEEDED is enough for all digits, plus possible "-", plus 2 (why?) */ 383/* SPACE_NEEDED is enough for all digits, plus possible "-", plus 2 (why?) */
378#define SPACE_NEEDED ((sizeof(intmax_t) * CHAR_BIT + 2) / 3 + 1 + 2) 384#define SPACE_NEEDED ((sizeof(intmax_t) * CHAR_BIT + 2) / 3 + 1 + 2)
379 CHECKSTRSPACE((int)(SPACE_NEEDED - 2), expdest); 385 CHECKSTRSPACE((int)(SPACE_NEEDED - 2), expdest);
380 USTPUTC('\0', expdest); 386 USTPUTC('\0', expdest);
381 start = stackblock(); 387 start = stackblock();
382 p = expdest - 1; 388 p = expdest - 1;
383 while (*p != CTLARI && p >= start) 389 while (*p != CTLARI && p >= start)
384 --p; 390 --p;
385 if (*p != CTLARI) 391 if (*p != CTLARI)
386 error("missing CTLARI (shouldn't happen)"); 392 error("missing CTLARI (shouldn't happen)");
387 if (p > start && *(p-1) == CTLESC) 393 if (p > start && *(p-1) == CTLESC)
388 for (p = start; *p != CTLARI; p++) 394 for (p = start; *p != CTLARI; p++)
389 if (*p == CTLESC) 395 if (*p == CTLESC)
390 p++; 396 p++;
391 397
392 if (p[1] == '"') 398 if (p[1] == '"')
393 quoted=1; 399 quoted=1;
394 else 400 else
395 quoted=0; 401 quoted=0;
396 begoff = p - start; 402 begoff = p - start;
397 removerecordregions(begoff); 403 removerecordregions(begoff);
398 if (quotes) 404 if (quotes)
399 rmescapes(p+2); 405 rmescapes(p+2);
400 result = arith(p+2); 406 result = arith(p+2);
401 fmtstr(p, SPACE_NEEDED, "%"PRIdMAX, result); 407 fmtstr(p, SPACE_NEEDED, "%"PRIdMAX, result);
402 408
403 while (*p++) 409 while (*p++)
404 ; 410 ;
405 411
406 if (quoted == 0) 412 if (quoted == 0)
407 recordregion(begoff, p - 1 - start, 0); 413 recordregion(begoff, p - 1 - start, 0);
408 adjustment = expdest - p + 1; 414 adjustment = expdest - p + 1;
409 STADJUST(-adjustment, expdest); 415 STADJUST(-adjustment, expdest);
410} 416}
411 417
412 418
413/* 419/*
414 * Expand stuff in backwards quotes. 420 * Expand stuff in backwards quotes.
415 */ 421 */
416 422
417STATIC void 423STATIC void
418expbackq(union node *cmd, int quoted, int flag) 424expbackq(union node *cmd, int quoted, int flag)
419{ 425{
420 struct backcmd in; 426 struct backcmd in;
421 int i; 427 int i;
422 char buf[128]; 428 char buf[128];
423 char *p; 429 char *p;
424 char *dest = expdest; 430 char *dest = expdest;
425 struct ifsregion saveifs, *savelastp; 431 struct ifsregion saveifs, *savelastp;
426 struct nodelist *saveargbackq; 432 struct nodelist *saveargbackq;
427 char lastc; 433 char lastc;
428 int startloc = dest - stackblock(); 434 int startloc = dest - stackblock();
429 char const *syntax = quoted? DQSYNTAX : BASESYNTAX; 435 char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
430 int saveherefd; 436 int saveherefd;
431 int quotes = flag & (EXP_FULL | EXP_CASE); 437 int quotes = flag & (EXP_FULL | EXP_CASE);
432 int nnl; 438 int nnl;
433 439
434 INTOFF; 440 INTOFF;
435 saveifs = ifsfirst; 441 saveifs = ifsfirst;
436 savelastp = ifslastp; 442 savelastp = ifslastp;
437 saveargbackq = argbackq; 443 saveargbackq = argbackq;
438 saveherefd = herefd; 444 saveherefd = herefd;
439 herefd = -1; 445 herefd = -1;
440 p = grabstackstr(dest); 446 p = grabstackstr(dest);
441 evalbackcmd(cmd, &in); 447 evalbackcmd(cmd, &in);
442 ungrabstackstr(p, dest); 448 ungrabstackstr(p, dest);
443 ifsfirst = saveifs; 449 ifsfirst = saveifs;
444 ifslastp = savelastp; 450 ifslastp = savelastp;
445 argbackq = saveargbackq; 451 argbackq = saveargbackq;
446 herefd = saveherefd; 452 herefd = saveherefd;
447 453
448 p = in.buf; 454 p = in.buf;
449 lastc = '\0'; 455 lastc = '\0';
450 nnl = 0; 456 nnl = 0;
451 for (;;) { 457 for (;;) {
452 if (--in.nleft < 0) { 458 if (--in.nleft < 0) {
453 if (in.fd < 0) 459 if (in.fd < 0)
454 break; 460 break;
455 while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR) 461 while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR)
456 continue; 462 continue;
457 TRACE(("expbackq: read returns %d\n", i)); 463 TRACE(("expbackq: read returns %d\n", i));
458 if (i <= 0) 464 if (i <= 0)
459 break; 465 break;
460 p = buf; 466 p = buf;
461 in.nleft = i - 1; 467 in.nleft = i - 1;
462 } 468 }
463 lastc = *p++; 469 lastc = *p++;
464 if (lastc != '\0') { 470 if (lastc != '\0') {
465 if (lastc == '\n') 471 if (lastc == '\n')
466 nnl++; 472 nnl++;
467 else { 473 else {
468 CHECKSTRSPACE(nnl + 2, dest); 474 CHECKSTRSPACE(nnl + 2, dest);
469 while (nnl > 0) { 475 while (nnl > 0) {
470 nnl--; 476 nnl--;
471 USTPUTC('\n', dest); 477 USTPUTC('\n', dest);
472 } 478 }
473 if (quotes && syntax[(int)lastc] == CCTL) 479 if (quotes && syntax[(int)lastc] == CCTL)
474 USTPUTC(CTLESC, dest); 480 USTPUTC(CTLESC, dest);
475 USTPUTC(lastc, dest); 481 USTPUTC(lastc, dest);
476 } 482 }
477 } 483 }
478 } 484 }
479 485
480 if (in.fd >= 0) 486 if (in.fd >= 0)
481 close(in.fd); 487 close(in.fd);
482 if (in.buf) 488 if (in.buf)
483 ckfree(in.buf); 489 ckfree(in.buf);
484 if (in.jp) 490 if (in.jp)
485 back_exitstatus = waitforjob(in.jp); 491 back_exitstatus = waitforjob(in.jp);
486 if (quoted == 0) 492 if (quoted == 0)
487 recordregion(startloc, dest - stackblock(), 0); 493 recordregion(startloc, dest - stackblock(), 0);
488 TRACE(("evalbackq: size=%d: \"%.*s\"\n", 494 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
489 (int)((dest - stackblock()) - startloc), 495 (int)((dest - stackblock()) - startloc),
490 (int)((dest - stackblock()) - startloc), 496 (int)((dest - stackblock()) - startloc),
491 stackblock() + startloc)); 497 stackblock() + startloc));
492 expdest = dest; 498 expdest = dest;
493 INTON; 499 INTON;
494} 500}
495 501
496 502
497 503
498STATIC int 504STATIC int
499subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes) 505subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
500{ 506{
501 char *startp; 507 char *startp;
502 char *loc = NULL; 508 char *loc = NULL;
503 char *q; 509 char *q;
504 int c = 0; 510 int c = 0;
505 int saveherefd = herefd; 511 int saveherefd = herefd;
506 struct nodelist *saveargbackq = argbackq; 512 struct nodelist *saveargbackq = argbackq;
507 int amount, how; 513 int amount, how;
508 514
509 herefd = -1; 515 herefd = -1;
510 switch (subtype) { 516 switch (subtype) {
511 case VSTRIMLEFT: 517 case VSTRIMLEFT:
512 case VSTRIMLEFTMAX: 518 case VSTRIMLEFTMAX:
513 case VSTRIMRIGHT: 519 case VSTRIMRIGHT:
514 case VSTRIMRIGHTMAX: 520 case VSTRIMRIGHTMAX:
515 how = (varflags & (VSQUOTE|VSPATQ)) == VSQUOTE ? 0 : EXP_CASE; 521 how = (varflags & (VSQUOTE|VSPATQ)) == VSQUOTE ? 0 : EXP_CASE;
516 break; 522 break;
517 default: 523 default:
518 how = 0; 524 how = 0;
519 break; 525 break;
520 } 526 }
521 argstr(p, how); 527 argstr(p, how);
522 STACKSTRNUL(expdest); 528 STACKSTRNUL(expdest);
523 herefd = saveherefd; 529 herefd = saveherefd;
524 argbackq = saveargbackq; 530 argbackq = saveargbackq;
525 startp = stackblock() + startloc; 531 startp = stackblock() + startloc;
526 if (str == NULL) 532 if (str == NULL)
527 str = stackblock() + strloc; 533 str = stackblock() + strloc;
528 534
529 switch (subtype) { 535 switch (subtype) {
530 case VSASSIGN: 536 case VSASSIGN:
531 setvar(str, startp, 0); 537 setvar(str, startp, 0);
532 amount = startp - expdest; 538 amount = startp - expdest;
533 STADJUST(amount, expdest); 539 STADJUST(amount, expdest);
534 varflags &= ~VSNUL; 540 varflags &= ~VSNUL;
535 return 1; 541 return 1;
536 542
537 case VSQUESTION: 543 case VSQUESTION:
538 if (*p != CTLENDVAR) { 544 if (*p != CTLENDVAR) {
539 outfmt(&errout, "%s\n", startp); 545 outfmt(&errout, "%s\n", startp);
540 error(NULL); 546 error(NULL);
541 } 547 }
542 error("%.*s: parameter %snot set", 548 error("%.*s: parameter %snot set",
543 (int)(p - str - 1), 549 (int)(p - str - 1),
544 str, (varflags & VSNUL) ? "null or " 550 str, (varflags & VSNUL) ? "null or "
545 : nullstr); 551 : nullstr);
546 /* NOTREACHED */ 552 /* NOTREACHED */
547 553
548 case VSTRIMLEFT: 554 case VSTRIMLEFT:
549 for (loc = startp; loc < str; loc++) { 555 for (loc = startp; loc < str; loc++) {
550 c = *loc; 556 c = *loc;
551 *loc = '\0'; 557 *loc = '\0';
552 if (patmatch(str, startp, quotes)) 558 if (patmatch(str, startp, quotes))
553 goto recordleft; 559 goto recordleft;
554 *loc = c; 560 *loc = c;
555 if (quotes && *loc == CTLESC) 561 if (quotes && *loc == CTLESC)
556 loc++; 562 loc++;
557 } 563 }
558 return 0; 564 return 0;
559 565
560 case VSTRIMLEFTMAX: 566 case VSTRIMLEFTMAX:
561 for (loc = str - 1; loc >= startp;) { 567 for (loc = str - 1; loc >= startp;) {
562 c = *loc; 568 c = *loc;
563 *loc = '\0'; 569 *loc = '\0';
564 if (patmatch(str, startp, quotes)) 570 if (patmatch(str, startp, quotes))
565 goto recordleft; 571 goto recordleft;
566 *loc = c; 572 *loc = c;
567 loc--; 573 loc--;
568 if (quotes && loc > startp && 574 if (quotes && loc > startp &&
569 *(loc - 1) == CTLESC) { 575 *(loc - 1) == CTLESC) {
570 for (q = startp; q < loc; q++) 576 for (q = startp; q < loc; q++)
571 if (*q == CTLESC) 577 if (*q == CTLESC)
572 q++; 578 q++;
573 if (q > loc) 579 if (q > loc)
574 loc--; 580 loc--;
575 } 581 }
576 } 582 }
577 return 0; 583 return 0;
578 584
579 case VSTRIMRIGHT: 585 case VSTRIMRIGHT:
580 for (loc = str - 1; loc >= startp;) { 586 for (loc = str - 1; loc >= startp;) {
581 if (patmatch(str, loc, quotes)) 587 if (patmatch(str, loc, quotes))
582 goto recordright; 588 goto recordright;
583 loc--; 589 loc--;
584 if (quotes && loc > startp && 590 if (quotes && loc > startp &&
585 *(loc - 1) == CTLESC) {  591 *(loc - 1) == CTLESC) {
586 for (q = startp; q < loc; q++) 592 for (q = startp; q < loc; q++)
587 if (*q == CTLESC) 593 if (*q == CTLESC)
588 q++; 594 q++;
589 if (q > loc) 595 if (q > loc)
590 loc--; 596 loc--;
591 } 597 }
592 } 598 }
593 return 0; 599 return 0;
594 600
595 case VSTRIMRIGHTMAX: 601 case VSTRIMRIGHTMAX:
596 for (loc = startp; loc < str - 1; loc++) { 602 for (loc = startp; loc < str - 1; loc++) {
597 if (patmatch(str, loc, quotes)) 603 if (patmatch(str, loc, quotes))
598 goto recordright; 604 goto recordright;
599 if (quotes && *loc == CTLESC) 605 if (quotes && *loc == CTLESC)
600 loc++; 606 loc++;
601 } 607 }
602 return 0; 608 return 0;
603 609
604 default: 610 default:
605 abort(); 611 abort();
606 } 612 }
607 613
608recordleft: 614recordleft:
609 *loc = c; 615 *loc = c;
610 amount = ((str - 1) - (loc - startp)) - expdest; 616 amount = ((str - 1) - (loc - startp)) - expdest;
611 STADJUST(amount, expdest); 617 STADJUST(amount, expdest);
612 while (loc != str - 1) 618 while (loc != str - 1)
613 *startp++ = *loc++; 619 *startp++ = *loc++;
614 return 1; 620 return 1;
615 621
616recordright: 622recordright:
617 amount = loc - expdest; 623 amount = loc - expdest;
618 STADJUST(amount, expdest); 624 STADJUST(amount, expdest);
619 STPUTC('\0', expdest); 625 STPUTC('\0', expdest);
620 STADJUST(-1, expdest); 626 STADJUST(-1, expdest);
621 return 1; 627 return 1;
622} 628}
623 629
624 630
625/* 631/*
626 * Expand a variable, and return a pointer to the next character in the 632 * Expand a variable, and return a pointer to the next character in the
627 * input string. 633 * input string.
628 */ 634 */
629 635
630STATIC char * 636STATIC char *
631evalvar(char *p, int flag) 637evalvar(char *p, int flag)
632{ 638{
633 int subtype; 639 int subtype;
634 int varflags; 640 int varflags;
635 char *var; 641 char *var;
636 char *val; 642 char *val;
637 int patloc; 643 int patloc;
638 int c; 644 int c;
639 int set; 645 int set;
640 int special; 646 int special;
641 int startloc; 647 int startloc;
642 int varlen; 648 int varlen;
643 int apply_ifs; 649 int apply_ifs;
644 int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); 650 int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
645 651
646 varflags = (unsigned char)*p++; 652 varflags = (unsigned char)*p++;
647 subtype = varflags & VSTYPE; 653 subtype = varflags & VSTYPE;
648 var = p; 654 var = p;
649 special = !is_name(*p); 655 special = !is_name(*p);
650 p = strchr(p, '=') + 1; 656 p = strchr(p, '=') + 1;
651 657
652again: /* jump here after setting a variable with ${var=text} */ 658again: /* jump here after setting a variable with ${var=text} */
653 if (varflags & VSLINENO) { 659 if (varflags & VSLINENO) {
654 set = 1; 660 set = 1;
655 special = 0; 661 special = 0;
656 val = var; 662 val = var;
657 p[-1] = '\0'; 663 p[-1] = '\0';
658 } else if (special) { 664 } else if (special) {
659 set = varisset(var, varflags & VSNUL); 665 set = varisset(var, varflags & VSNUL);
660 val = NULL; 666 val = NULL;
661 } else { 667 } else {
662 val = lookupvar(var); 668 val = lookupvar(var);
663 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { 669 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
664 val = NULL; 670 val = NULL;
665 set = 0; 671 set = 0;
666 } else 672 } else
667 set = 1; 673 set = 1;
668 } 674 }
669 675
670 varlen = 0; 676 varlen = 0;
671 startloc = expdest - stackblock(); 677 startloc = expdest - stackblock();
672 678
673 if (!set && uflag && *var != '@' && *var != '*') { 679 if (!set && uflag && *var != '@' && *var != '*') {
674 switch (subtype) { 680 switch (subtype) {
675 case VSNORMAL: 681 case VSNORMAL:
676 case VSTRIMLEFT: 682 case VSTRIMLEFT:
677 case VSTRIMLEFTMAX: 683 case VSTRIMLEFTMAX:
678 case VSTRIMRIGHT: 684 case VSTRIMRIGHT:
679 case VSTRIMRIGHTMAX: 685 case VSTRIMRIGHTMAX:
680 case VSLENGTH: 686 case VSLENGTH:
681 error("%.*s: parameter not set", 687 error("%.*s: parameter not set",
682 (int)(p - var - 1), var); 688 (int)(p - var - 1), var);
683 /* NOTREACHED */ 689 /* NOTREACHED */
684 } 690 }
685 } 691 }
686 692
687 if (set && subtype != VSPLUS) { 693 if (set && subtype != VSPLUS) {
688 /* insert the value of the variable */ 694 /* insert the value of the variable */
689 if (special) { 695 if (special) {
690 varvalue(var, varflags & VSQUOTE, subtype, flag); 696 varvalue(var, varflags & VSQUOTE, subtype, flag);
691 if (subtype == VSLENGTH) { 697 if (subtype == VSLENGTH) {
692 varlen = expdest - stackblock() - startloc; 698 varlen = expdest - stackblock() - startloc;
693 STADJUST(-varlen, expdest); 699 STADJUST(-varlen, expdest);
694 } 700 }
695 } else { 701 } else {
696 char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX 702 char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
697 : BASESYNTAX; 703 : BASESYNTAX;
698 704
699 if (subtype == VSLENGTH) { 705 if (subtype == VSLENGTH) {
700 for (;*val; val++) 706 for (;*val; val++)
701 varlen++; 707 varlen++;
702 } else { 708 } else {
703 while (*val) { 709 while (*val) {
704 if (quotes && syntax[(int)*val] == CCTL) 710 if (quotes && syntax[(int)*val] == CCTL)
705 STPUTC(CTLESC, expdest); 711 STPUTC(CTLESC, expdest);
706 STPUTC(*val++, expdest); 712 STPUTC(*val++, expdest);
707 } 713 }
708 } 714 }
709 } 715 }
710 } 716 }
711 717
712 718
713 if (flag & EXP_IN_QUOTES) 719 if (flag & EXP_IN_QUOTES)
714 apply_ifs = 0; 720 apply_ifs = 0;
715 else if (varflags & VSQUOTE) { 721 else if (varflags & VSQUOTE) {
716 if (*var == '@' && shellparam.nparam != 1) 722 if (*var == '@' && shellparam.nparam != 1)
717 apply_ifs = 1; 723 apply_ifs = 1;
718 else { 724 else {
719 /* 725 /*
720 * Mark so that we don't apply IFS if we recurse through 726 * Mark so that we don't apply IFS if we recurse through
721 * here expanding $bar from "${foo-$bar}". 727 * here expanding $bar from "${foo-$bar}".
722 */ 728 */
723 flag |= EXP_IN_QUOTES; 729 flag |= EXP_IN_QUOTES;
724 apply_ifs = 0; 730 apply_ifs = 0;
725 } 731 }
726 } else 732 } else
727 apply_ifs = 1; 733 apply_ifs = 1;
728 734
729 switch (subtype) { 735 switch (subtype) {
730 case VSLENGTH: 736 case VSLENGTH:
731 expdest = cvtnum(varlen, expdest); 737 expdest = cvtnum(varlen, expdest);
732 break; 738 break;
733 739
734 case VSNORMAL: 740 case VSNORMAL:
735 break; 741 break;
736 742
737 case VSPLUS: 743 case VSPLUS:
738 set = !set; 744 set = !set;
739 /* FALLTHROUGH */ 745 /* FALLTHROUGH */
740 case VSMINUS: 746 case VSMINUS:
741 if (!set) { 747 if (!set) {
742 argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0)); 748 argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));
743 /* 749 /*
744 * ${x-a b c} doesn't get split, but removing the 750 * ${x-a b c} doesn't get split, but removing the
745 * 'apply_ifs = 0' apparently breaks ${1+"$@"}.. 751 * 'apply_ifs = 0' apparently breaks ${1+"$@"}..
746 * ${x-'a b' c} should generate 2 args. 752 * ${x-'a b' c} should generate 2 args.
747 */ 753 */
748 if (*p != CTLENDVAR) 754 if (*p != CTLENDVAR)
749 /* We should have marked stuff already */ 755 /* We should have marked stuff already */
750 apply_ifs = 0; 756 apply_ifs = 0;
751 } 757 }
752 break; 758 break;
753 759
754 case VSTRIMLEFT: 760 case VSTRIMLEFT:
755 case VSTRIMLEFTMAX: 761 case VSTRIMLEFTMAX:
756 case VSTRIMRIGHT: 762 case VSTRIMRIGHT:
757 case VSTRIMRIGHTMAX: 763 case VSTRIMRIGHTMAX:
758 if (!set) 764 if (!set)
759 break; 765 break;
760 /* 766 /*
761 * Terminate the string and start recording the pattern 767 * Terminate the string and start recording the pattern
762 * right after it 768 * right after it
763 */ 769 */
764 STPUTC('\0', expdest); 770 STPUTC('\0', expdest);
765 patloc = expdest - stackblock(); 771 patloc = expdest - stackblock();
766 if (subevalvar(p, NULL, patloc, subtype, 772 if (subevalvar(p, NULL, patloc, subtype,
767 startloc, varflags, quotes) == 0) { 773 startloc, varflags, quotes) == 0) {
768 int amount = (expdest - stackblock() - patloc) + 1; 774 int amount = (expdest - stackblock() - patloc) + 1;
769 STADJUST(-amount, expdest); 775 STADJUST(-amount, expdest);
770 } 776 }
771 /* Remove any recorded regions beyond start of variable */ 777 /* Remove any recorded regions beyond start of variable */
772 removerecordregions(startloc); 778 removerecordregions(startloc);
773 apply_ifs = 1; 779 apply_ifs = 1;
774 break; 780 break;
775 781
776 case VSASSIGN: 782 case VSASSIGN:
777 case VSQUESTION: 783 case VSQUESTION:
778 if (set) 784 if (set)
779 break; 785 break;
780 if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) { 786 if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) {
781 varflags &= ~VSNUL; 787 varflags &= ~VSNUL;
782 /*  788 /*
783 * Remove any recorded regions beyond  789 * Remove any recorded regions beyond
784 * start of variable  790 * start of variable
785 */ 791 */
786 removerecordregions(startloc); 792 removerecordregions(startloc);
787 goto again; 793 goto again;
788 } 794 }
789 apply_ifs = 0; 795 apply_ifs = 0;
790 break; 796 break;
791 797
792 default: 798 default:
793 abort(); 799 abort();
794 } 800 }
795 p[-1] = '='; /* recover overwritten '=' */ 801 p[-1] = '='; /* recover overwritten '=' */
796 802
797 if (apply_ifs) 803 if (apply_ifs)
798 recordregion(startloc, expdest - stackblock(), 804 recordregion(startloc, expdest - stackblock(),
799 varflags & VSQUOTE); 805 varflags & VSQUOTE);
800 806
801 if (subtype != VSNORMAL) { /* skip to end of alternative */ 807 if (subtype != VSNORMAL) { /* skip to end of alternative */
802 int nesting = 1; 808 int nesting = 1;
803 for (;;) { 809 for (;;) {
804 if ((c = *p++) == CTLESC) 810 if ((c = *p++) == CTLESC)
805 p++; 811 p++;
806 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { 812 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
807 if (set) 813 if (set)
808 argbackq = argbackq->next; 814 argbackq = argbackq->next;
809 } else if (c == CTLVAR) { 815 } else if (c == CTLVAR) {
810 if ((*p++ & VSTYPE) != VSNORMAL) 816 if ((*p++ & VSTYPE) != VSNORMAL)
811 nesting++; 817 nesting++;
812 } else if (c == CTLENDVAR) { 818 } else if (c == CTLENDVAR) {
813 if (--nesting == 0) 819 if (--nesting == 0)
814 break; 820 break;
815 } 821 }
816 } 822 }
817 } 823 }
818 return p; 824 return p;
819} 825}
820 826
821 827
822 828
823/* 829/*
824 * Test whether a specialized variable is set. 830 * Test whether a specialized variable is set.
825 */ 831 */
826 832
827STATIC int 833STATIC int
828varisset(char *name, int nulok) 834varisset(char *name, int nulok)
829{ 835{
830 if (*name == '!') 836 if (*name == '!')
831 return backgndpid != -1; 837 return backgndpid != -1;
832 else if (*name == '@' || *name == '*') { 838 else if (*name == '@' || *name == '*') {
833 if (*shellparam.p == NULL) 839 if (*shellparam.p == NULL)
834 return 0; 840 return 0;
835 841
836 if (nulok) { 842 if (nulok) {
837 char **av; 843 char **av;
838 844
839 for (av = shellparam.p; *av; av++) 845 for (av = shellparam.p; *av; av++)
840 if (**av != '\0') 846 if (**av != '\0')
841 return 1; 847 return 1;
842 return 0; 848 return 0;
843 } 849 }
844 } else if (is_digit(*name)) { 850 } else if (is_digit(*name)) {
845 char *ap; 851 char *ap;
846 int num = atoi(name); 852 int num = atoi(name);
847 853
848 if (num > shellparam.nparam) 854 if (num > shellparam.nparam)
849 return 0; 855 return 0;
850 856
851 if (num == 0) 857 if (num == 0)
852 ap = arg0; 858 ap = arg0;
853 else 859 else
854 ap = shellparam.p[num - 1]; 860 ap = shellparam.p[num - 1];
855 861
856 if (nulok && (ap == NULL || *ap == '\0')) 862 if (nulok && (ap == NULL || *ap == '\0'))
857 return 0; 863 return 0;
858 } 864 }
859 return 1; 865 return 1;
860} 866}
861 867
862 868
863 869
864/* 870/*
865 * Add the value of a specialized variable to the stack string. 871 * Add the value of a specialized variable to the stack string.
866 */ 872 */
867 873
868STATIC void 874STATIC void
869varvalue(char *name, int quoted, int subtype, int flag) 875varvalue(char *name, int quoted, int subtype, int flag)
870{ 876{
871 int num; 877 int num;
872 char *p; 878 char *p;
873 int i; 879 int i;
874 char sep; 880 char sep;
875 char **ap; 881 char **ap;
876 char const *syntax; 882 char const *syntax;
877 883
878#define STRTODEST(p) \ 884#define STRTODEST(p) \
879 do {\ 885 do {\
880 if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \ 886 if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \
881 syntax = quoted? DQSYNTAX : BASESYNTAX; \ 887 syntax = quoted? DQSYNTAX : BASESYNTAX; \
882 while (*p) { \ 888 while (*p) { \
883 if (syntax[(int)*p] == CCTL) \ 889 if (syntax[(int)*p] == CCTL) \
884 STPUTC(CTLESC, expdest); \ 890 STPUTC(CTLESC, expdest); \
885 STPUTC(*p++, expdest); \ 891 STPUTC(*p++, expdest); \
886 } \ 892 } \
887 } else \ 893 } else \
888 while (*p) \ 894 while (*p) \
889 STPUTC(*p++, expdest); \ 895 STPUTC(*p++, expdest); \
890 } while (0) 896 } while (0)
891 897
892 898
893 switch (*name) { 899 switch (*name) {
894 case '$': 900 case '$':
895 num = rootpid; 901 num = rootpid;
896 goto numvar; 902 goto numvar;
897 case '?': 903 case '?':
898 num = exitstatus; 904 num = exitstatus;
899 goto numvar; 905 goto numvar;
900 case '#': 906 case '#':
901 num = shellparam.nparam; 907 num = shellparam.nparam;
902 goto numvar; 908 goto numvar;
903 case '!': 909 case '!':
904 num = backgndpid; 910 num = backgndpid;
905numvar: 911numvar:
906 expdest = cvtnum(num, expdest); 912 expdest = cvtnum(num, expdest);
907 break; 913 break;
908 case '-': 914 case '-':
909 for (i = 0; optlist[i].name; i++) { 915 for (i = 0; optlist[i].name; i++) {
910 if (optlist[i].val && optlist[i].letter) 916 if (optlist[i].val && optlist[i].letter)
911 STPUTC(optlist[i].letter, expdest); 917 STPUTC(optlist[i].letter, expdest);
912 } 918 }
913 break; 919 break;
914 case '@': 920 case '@':
915 if (flag & EXP_FULL && quoted) { 921 if (flag & EXP_FULL && quoted) {
916 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 922 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
917 STRTODEST(p); 923 STRTODEST(p);
918 if (*ap) 924 if (*ap)
919 /* A NUL separates args inside "" */ 925 /* A NUL separates args inside "" */
920 STPUTC('\0', expdest); 926 STPUTC('\0', expdest);
921 } 927 }
922 break; 928 break;
923 } 929 }
924 /* fall through */ 930 /* fall through */
925 case '*': 931 case '*':
926 sep = ifsval()[0]; 932 sep = ifsval()[0];
927 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 933 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
928 STRTODEST(p); 934 STRTODEST(p);
929 if (*ap && sep) 935 if (*ap && sep)
930 STPUTC(sep, expdest); 936 STPUTC(sep, expdest);
931 } 937 }
932 break; 938 break;
933 case '0': 939 case '0':
934 p = arg0; 940 p = arg0;
935 STRTODEST(p); 941 STRTODEST(p);
936 break; 942 break;
937 default: 943 default:
938 if (is_digit(*name)) { 944 if (is_digit(*name)) {
939 num = atoi(name); 945 num = atoi(name);
940 if (num > 0 && num <= shellparam.nparam) { 946 if (num > 0 && num <= shellparam.nparam) {
941 p = shellparam.p[num - 1]; 947 p = shellparam.p[num - 1];
942 STRTODEST(p); 948 STRTODEST(p);
943 } 949 }
944 } 950 }
945 break; 951 break;
946 } 952 }
947} 953}
948 954
949 955
950 956
951/* 957/*
952 * Record the fact that we have to scan this region of the 958 * Record the fact that we have to scan this region of the
953 * string for IFS characters. 959 * string for IFS characters.
954 */ 960 */
955 961
956STATIC void 962STATIC void
957recordregion(int start, int end, int inquotes) 963recordregion(int start, int end, int inquotes)
958{ 964{
959 struct ifsregion *ifsp; 965 struct ifsregion *ifsp;
960 966
961 if (ifslastp == NULL) { 967 if (ifslastp == NULL) {
962 ifsp = &ifsfirst; 968 ifsp = &ifsfirst;
963 } else { 969 } else {
964 if (ifslastp->endoff == start 970 if (ifslastp->endoff == start
965 && ifslastp->inquotes == inquotes) { 971 && ifslastp->inquotes == inquotes) {
966 /* extend previous area */ 972 /* extend previous area */
967 ifslastp->endoff = end; 973 ifslastp->endoff = end;
968 return; 974 return;
969 } 975 }
970 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); 976 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
971 ifslastp->next = ifsp; 977 ifslastp->next = ifsp;
972 } 978 }
973 ifslastp = ifsp; 979 ifslastp = ifsp;
974 ifslastp->next = NULL; 980 ifslastp->next = NULL;
975 ifslastp->begoff = start; 981 ifslastp->begoff = start;
976 ifslastp->endoff = end; 982 ifslastp->endoff = end;
977 ifslastp->inquotes = inquotes; 983 ifslastp->inquotes = inquotes;
978} 984}
979 985
980 986
981 987
982/* 988/*
983 * Break the argument string into pieces based upon IFS and add the 989 * Break the argument string into pieces based upon IFS and add the
984 * strings to the argument list. The regions of the string to be 990 * strings to the argument list. The regions of the string to be
985 * searched for IFS characters have been stored by recordregion. 991 * searched for IFS characters have been stored by recordregion.
986 */ 992 */
987STATIC void 993STATIC void
988ifsbreakup(char *string, struct arglist *arglist) 994ifsbreakup(char *string, struct arglist *arglist)
989{ 995{
990 struct ifsregion *ifsp; 996 struct ifsregion *ifsp;
991 struct strlist *sp; 997 struct strlist *sp;
992 char *start; 998 char *start;
993 char *p; 999 char *p;
994 char *q; 1000 char *q;
995 const char *ifs; 1001 const char *ifs;
996 const char *ifsspc; 1002 const char *ifsspc;
997 int had_param_ch = 0; 1003 int had_param_ch = 0;
998 1004
999 start = string; 1005 start = string;
1000 1006
1001 if (ifslastp == NULL) { 1007 if (ifslastp == NULL) {
1002 /* Return entire argument, IFS doesn't apply to any of it */ 1008 /* Return entire argument, IFS doesn't apply to any of it */
1003 sp = stalloc(sizeof(*sp)); 1009 sp = stalloc(sizeof(*sp));
1004 sp->text = start; 1010 sp->text = start;
1005 *arglist->lastp = sp; 1011 *arglist->lastp = sp;
1006 arglist->lastp = &sp->next; 1012 arglist->lastp = &sp->next;
1007 return; 1013 return;
1008 } 1014 }
1009 1015
1010 ifs = ifsval(); 1016 ifs = ifsval();
1011 1017
1012 for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) { 1018 for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
1013 p = string + ifsp->begoff; 1019 p = string + ifsp->begoff;
1014 while (p < string + ifsp->endoff) { 1020 while (p < string + ifsp->endoff) {
1015 had_param_ch = 1; 1021 had_param_ch = 1;
1016 q = p; 1022 q = p;
1017 if (*p == CTLESC) 1023 if (*p == CTLESC)
1018 p++; 1024 p++;
1019 if (ifsp->inquotes) { 1025 if (ifsp->inquotes) {
1020 /* Only NULs (should be from "$@") end args */ 1026 /* Only NULs (should be from "$@") end args */
1021 if (*p != 0) { 1027 if (*p != 0) {
1022 p++; 1028 p++;
1023 continue; 1029 continue;
1024 } 1030 }
1025 ifsspc = NULL; 1031 ifsspc = NULL;
1026 } else { 1032 } else {
1027 if (!strchr(ifs, *p)) { 1033 if (!strchr(ifs, *p)) {
1028 p++; 1034 p++;
1029 continue; 1035 continue;
1030 } 1036 }
1031 had_param_ch = 0; 1037 had_param_ch = 0;
1032 ifsspc = strchr(" \t\n", *p); 1038 ifsspc = strchr(" \t\n", *p);
1033 1039
1034 /* Ignore IFS whitespace at start */ 1040 /* Ignore IFS whitespace at start */
1035 if (q == start && ifsspc != NULL) { 1041 if (q == start && ifsspc != NULL) {
1036 p++; 1042 p++;
1037 start = p; 1043 start = p;
1038 continue; 1044 continue;
1039 } 1045 }
1040 } 1046 }
1041 1047
1042 /* Save this argument... */ 1048 /* Save this argument... */
1043 *q = '\0'; 1049 *q = '\0';
1044 sp = stalloc(sizeof(*sp)); 1050 sp = stalloc(sizeof(*sp));
1045 sp->text = start; 1051 sp->text = start;
1046 *arglist->lastp = sp; 1052 *arglist->lastp = sp;
1047 arglist->lastp = &sp->next; 1053 arglist->lastp = &sp->next;
1048 p++; 1054 p++;
1049 1055
1050 if (ifsspc != NULL) { 1056 if (ifsspc != NULL) {
1051 /* Ignore further trailing IFS whitespace */ 1057 /* Ignore further trailing IFS whitespace */
1052 for (; p < string + ifsp->endoff; p++) { 1058 for (; p < string + ifsp->endoff; p++) {
1053 q = p; 1059 q = p;
1054 if (*p == CTLESC) 1060 if (*p == CTLESC)
1055 p++; 1061 p++;
1056 if (strchr(ifs, *p) == NULL) { 1062 if (strchr(ifs, *p) == NULL) {
1057 p = q; 1063 p = q;
1058 break; 1064 break;
1059 } 1065 }
1060 if (strchr(" \t\n", *p) == NULL) { 1066 if (strchr(" \t\n", *p) == NULL) {
1061 p++; 1067 p++;
1062 break; 1068 break;
1063 } 1069 }
1064 } 1070 }
1065 } 1071 }
1066 start = p; 1072 start = p;
1067 } 1073 }
1068 } 1074 }
1069 1075
1070 /* 1076 /*
1071 * Save anything left as an argument. 1077 * Save anything left as an argument.
1072 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as 1078 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
1073 * generating 2 arguments, the second of which is empty. 1079 * generating 2 arguments, the second of which is empty.
1074 * Some recent clarification of the Posix spec say that it 1080 * Some recent clarification of the Posix spec say that it
1075 * should only generate one.... 1081 * should only generate one....
1076 */ 1082 */
1077 if (had_param_ch || *start != 0) { 1083 if (had_param_ch || *start != 0) {
1078 sp = stalloc(sizeof(*sp)); 1084 sp = stalloc(sizeof(*sp));
1079 sp->text = start; 1085 sp->text = start;
1080 *arglist->lastp = sp; 1086 *arglist->lastp = sp;
1081 arglist->lastp = &sp->next; 1087 arglist->lastp = &sp->next;
1082 } 1088 }
1083} 1089}
1084 1090
1085STATIC void 1091STATIC void
1086ifsfree(void) 1092ifsfree(void)
1087{ 1093{
1088 while (ifsfirst.next != NULL) { 1094 while (ifsfirst.next != NULL) {
1089 struct ifsregion *ifsp; 1095 struct ifsregion *ifsp;
1090 INTOFF; 1096 INTOFF;
1091 ifsp = ifsfirst.next->next; 1097 ifsp = ifsfirst.next->next;
1092 ckfree(ifsfirst.next); 1098 ckfree(ifsfirst.next);
1093 ifsfirst.next = ifsp; 1099 ifsfirst.next = ifsp;
1094 INTON; 1100 INTON;
1095 } 1101 }
1096 ifslastp = NULL; 1102 ifslastp = NULL;
1097 ifsfirst.next = NULL; 1103 ifsfirst.next = NULL;
1098} 1104}
1099 1105
1100 1106
1101 1107
1102/* 1108/*
1103 * Expand shell metacharacters. At this point, the only control characters 1109 * Expand shell metacharacters. At this point, the only control characters
1104 * should be escapes. The results are stored in the list exparg. 1110 * should be escapes. The results are stored in the list exparg.
1105 */ 1111 */
1106 1112
1107char *expdir; 1113char *expdir;
1108 1114
1109 1115
1110STATIC void 1116STATIC void
1111expandmeta(struct strlist *str, int flag) 1117expandmeta(struct strlist *str, int flag)
1112{ 1118{
1113 char *p; 1119 char *p;
1114 struct strlist **savelastp; 1120 struct strlist **savelastp;
1115 struct strlist *sp; 1121 struct strlist *sp;
1116 char c; 1122 char c;
1117 /* TODO - EXP_REDIR */ 1123 /* TODO - EXP_REDIR */
1118 1124
1119 while (str) { 1125 while (str) {
1120 if (fflag) 1126 if (fflag)
1121 goto nometa; 1127 goto nometa;
1122 p = str->text; 1128 p = str->text;

cvs diff -r1.110 -r1.111 src/bin/sh/parser.c (switch to unified diff)

--- src/bin/sh/parser.c 2016/03/27 14:36:29 1.110
+++ src/bin/sh/parser.c 2016/03/27 14:39:33 1.111
@@ -1,1842 +1,1940 @@ @@ -1,1842 +1,1940 @@
1/* $NetBSD: parser.c,v 1.110 2016/03/27 14:36:29 christos Exp $ */ 1/* $NetBSD: parser.c,v 1.111 2016/03/27 14:39:33 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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.110 2016/03/27 14:36:29 christos Exp $"); 40__RCSID("$NetBSD: parser.c,v 1.111 2016/03/27 14:39:33 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() */
54#include "syntax.h" 54#include "syntax.h"
55#include "options.h" 55#include "options.h"
56#include "input.h" 56#include "input.h"
57#include "output.h" 57#include "output.h"
58#include "var.h" 58#include "var.h"
59#include "error.h" 59#include "error.h"
60#include "memalloc.h" 60#include "memalloc.h"
61#include "mystring.h" 61#include "mystring.h"
62#include "alias.h" 62#include "alias.h"
63#include "show.h" 63#include "show.h"
64#ifndef SMALL 64#ifndef SMALL
65#include "myhistedit.h" 65#include "myhistedit.h"
66#endif 66#endif
67 67
68/* 68/*
69 * Shell command parser. 69 * Shell command parser.
70 */ 70 */
71 71
72#define EOFMARKLEN 79 
73 
74/* values returned by readtoken */ 72/* values returned by readtoken */
75#include "token.h" 73#include "token.h"
76 74
77#define OPENBRACE '{' 75#define OPENBRACE '{'
78#define CLOSEBRACE '}' 76#define CLOSEBRACE '}'
79 77
80 78
81struct heredoc { 79struct heredoc {
82 struct heredoc *next; /* next here document in list */ 80 struct heredoc *next; /* next here document in list */
83 union node *here; /* redirection node */ 81 union node *here; /* redirection node */
84 char *eofmark; /* string indicating end of input */ 82 char *eofmark; /* string indicating end of input */
85 int striptabs; /* if set, strip leading tabs */ 83 int striptabs; /* if set, strip leading tabs */
86}; 84};
87 85
88 86
89 87
90static int noalias = 0; /* when set, don't handle aliases */ 88static int noalias = 0; /* when set, don't handle aliases */
91struct heredoc *heredoclist; /* list of here documents to read */ 89struct heredoc *heredoclist; /* list of here documents to read */
92int parsebackquote; /* nonzero if we are inside backquotes */ 90int parsebackquote; /* nonzero if we are inside backquotes */
93int doprompt; /* if set, prompt the user */ 91int doprompt; /* if set, prompt the user */
94int needprompt; /* true if interactive and at start of line */ 92int needprompt; /* true if interactive and at start of line */
95int lasttoken; /* last token read */ 93int lasttoken; /* last token read */
96MKINIT int tokpushback; /* last token pushed back */ 94MKINIT int tokpushback; /* last token pushed back */
97char *wordtext; /* text of last word returned by readtoken */ 95char *wordtext; /* text of last word returned by readtoken */
98MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */ 96MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
99struct nodelist *backquotelist; 97struct nodelist *backquotelist;
100union node *redirnode; 98union node *redirnode;
101struct heredoc *heredoc; 99struct heredoc *heredoc;
102int quoteflag; /* set if (part of) last token was quoted */ 100int quoteflag; /* set if (part of) last token was quoted */
103int startlinno; /* line # where last token started */ 101int startlinno; /* line # where last token started */
104int funclinno; /* line # where the current function started */ 102int funclinno; /* line # where the current function started */
105 103
106 104
107STATIC union node *list(int, int); 105STATIC union node *list(int, int);
108STATIC union node *andor(void); 106STATIC union node *andor(void);
109STATIC union node *pipeline(void); 107STATIC union node *pipeline(void);
110STATIC union node *command(void); 108STATIC union node *command(void);
111STATIC union node *simplecmd(union node **, union node *); 109STATIC union node *simplecmd(union node **, union node *);
112STATIC union node *makename(void); 110STATIC union node *makename(void);
113STATIC void parsefname(void); 111STATIC void parsefname(void);
114STATIC void parseheredoc(void); 112STATIC void slurp_heredoc(char *const, int, int);
 113STATIC void readheredocs(void);
115STATIC int peektoken(void); 114STATIC int peektoken(void);
116STATIC int readtoken(void); 115STATIC int readtoken(void);
117STATIC int xxreadtoken(void); 116STATIC int xxreadtoken(void);
118STATIC int readtoken1(int, char const *, char *, int); 117STATIC int readtoken1(int, char const *, int);
119STATIC int noexpand(char *); 118STATIC int noexpand(char *);
120STATIC void synexpect(int, const char *) __dead; 119STATIC void synexpect(int, const char *) __dead;
121STATIC void synerror(const char *) __dead; 120STATIC void synerror(const char *) __dead;
122STATIC void setprompt(int); 121STATIC void setprompt(int);
123 122
124 123
125static const char EOFhere[] = "EOF reading here (<<) document"; 124static const char EOFhere[] = "EOF reading here (<<) document";
126 125
127 126
128/* 127/*
129 * Read and parse a command. Returns NEOF on end of file. (NULL is a 128 * Read and parse a command. Returns NEOF on end of file. (NULL is a
130 * valid parse tree indicating a blank line.) 129 * valid parse tree indicating a blank line.)
131 */ 130 */
132 131
133union node * 132union node *
134parsecmd(int interact) 133parsecmd(int interact)
135{ 134{
136 int t; 135 int t;
137 136
138 tokpushback = 0; 137 tokpushback = 0;
139 doprompt = interact; 138 doprompt = interact;
140 if (doprompt) 139 if (doprompt)
141 setprompt(1); 140 setprompt(1);
142 else 141 else
143 setprompt(0); 142 setprompt(0);
144 needprompt = 0; 143 needprompt = 0;
145 t = readtoken(); 144 t = readtoken();
146 if (t == TEOF) 145 if (t == TEOF)
147 return NEOF; 146 return NEOF;
148 if (t == TNL) 147 if (t == TNL)
149 return NULL; 148 return NULL;
150 tokpushback++; 149 tokpushback++;
151 return list(1, 0); 150 return list(1, 0);
152} 151}
153 152
154 153
155STATIC union node * 154STATIC union node *
156list(int nlflag, int erflag) 155list(int nlflag, int erflag)
157{ 156{
158 union node *n1, *n2, *n3; 157 union node *n1, *n2, *n3;
159 int tok; 158 int tok;
160 TRACE(("list(%d,%d): entered\n", nlflag, erflag)); 159 TRACE(("list(%d,%d): entered\n", nlflag, erflag));
161 160
162 checkkwd = 2; 161 checkkwd = 2;
163 if (nlflag == 0 && tokendlist[peektoken()]) 162 if (nlflag == 0 && tokendlist[peektoken()])
164 return NULL; 163 return NULL;
165 n1 = NULL; 164 n1 = NULL;
166 for (;;) { 165 for (;;) {
167 n2 = andor(); 166 n2 = andor();
168 tok = readtoken(); 167 tok = readtoken();
169 if (tok == TBACKGND) { 168 if (tok == TBACKGND) {
170 if (n2->type == NCMD || n2->type == NPIPE) { 169 if (n2->type == NCMD || n2->type == NPIPE) {
171 n2->ncmd.backgnd = 1; 170 n2->ncmd.backgnd = 1;
172 } else if (n2->type == NREDIR) { 171 } else if (n2->type == NREDIR) {
173 n2->type = NBACKGND; 172 n2->type = NBACKGND;
174 } else { 173 } else {
175 n3 = stalloc(sizeof(struct nredir)); 174 n3 = stalloc(sizeof(struct nredir));
176 n3->type = NBACKGND; 175 n3->type = NBACKGND;
177 n3->nredir.n = n2; 176 n3->nredir.n = n2;
178 n3->nredir.redirect = NULL; 177 n3->nredir.redirect = NULL;
179 n2 = n3; 178 n2 = n3;
180 } 179 }
181 } 180 }
182 if (n1 == NULL) { 181 if (n1 == NULL) {
183 n1 = n2; 182 n1 = n2;
184 } 183 }
185 else { 184 else {
186 n3 = stalloc(sizeof(struct nbinary)); 185 n3 = stalloc(sizeof(struct nbinary));
187 n3->type = NSEMI; 186 n3->type = NSEMI;
188 n3->nbinary.ch1 = n1; 187 n3->nbinary.ch1 = n1;
189 n3->nbinary.ch2 = n2; 188 n3->nbinary.ch2 = n2;
190 n1 = n3; 189 n1 = n3;
191 } 190 }
192 switch (tok) { 191 switch (tok) {
193 case TBACKGND: 192 case TBACKGND:
194 case TSEMI: 193 case TSEMI:
195 tok = readtoken(); 194 tok = readtoken();
196 /* FALLTHROUGH */ 195 /* FALLTHROUGH */
197 case TNL: 196 case TNL:
198 if (tok == TNL) { 197 if (tok == TNL) {
199 parseheredoc(); 198 readheredocs();
200 if (nlflag) 199 if (nlflag)
201 return n1; 200 return n1;
202 } else { 201 } else {
203 tokpushback++; 202 tokpushback++;
204 } 203 }
205 checkkwd = 2; 204 checkkwd = 2;
206 if (tokendlist[peektoken()]) 205 if (tokendlist[peektoken()])
207 return n1; 206 return n1;
208 break; 207 break;
209 case TEOF: 208 case TEOF:
210 if (heredoclist) 209 if (heredoclist)
211 parseheredoc(); 210 readheredocs();
212 else 211 else
213 pungetc(); /* push back EOF on input */ 212 pungetc(); /* push back EOF on input */
214 return n1; 213 return n1;
215 default: 214 default:
216 if (nlflag || erflag) 215 if (nlflag || erflag)
217 synexpect(-1, 0); 216 synexpect(-1, 0);
218 tokpushback++; 217 tokpushback++;
219 return n1; 218 return n1;
220 } 219 }
221 } 220 }
222} 221}
223 222
224STATIC union node * 223STATIC union node *
225andor(void) 224andor(void)
226{ 225{
227 union node *n1, *n2, *n3; 226 union node *n1, *n2, *n3;
228 int t; 227 int t;
229 228
230 TRACE(("andor: entered\n")); 229 TRACE(("andor: entered\n"));
231 n1 = pipeline(); 230 n1 = pipeline();
232 for (;;) { 231 for (;;) {
233 if ((t = readtoken()) == TAND) { 232 if ((t = readtoken()) == TAND) {
234 t = NAND; 233 t = NAND;
235 } else if (t == TOR) { 234 } else if (t == TOR) {
236 t = NOR; 235 t = NOR;
237 } else { 236 } else {
238 tokpushback++; 237 tokpushback++;
239 return n1; 238 return n1;
240 } 239 }
241 n2 = pipeline(); 240 n2 = pipeline();
242 n3 = stalloc(sizeof(struct nbinary)); 241 n3 = stalloc(sizeof(struct nbinary));
243 n3->type = t; 242 n3->type = t;
244 n3->nbinary.ch1 = n1; 243 n3->nbinary.ch1 = n1;
245 n3->nbinary.ch2 = n2; 244 n3->nbinary.ch2 = n2;
246 n1 = n3; 245 n1 = n3;
247 } 246 }
248} 247}
249 248
250STATIC union node * 249STATIC union node *
251pipeline(void) 250pipeline(void)
252{ 251{
253 union node *n1, *n2, *pipenode; 252 union node *n1, *n2, *pipenode;
254 struct nodelist *lp, *prev; 253 struct nodelist *lp, *prev;
255 int negate; 254 int negate;
256 255
257 TRACE(("pipeline: entered\n")); 256 TRACE(("pipeline: entered\n"));
258 257
259 negate = 0; 258 negate = 0;
260 checkkwd = 2; 259 checkkwd = 2;
261 while (readtoken() == TNOT) { 260 while (readtoken() == TNOT) {
262 TRACE(("pipeline: TNOT recognized\n")); 261 TRACE(("pipeline: TNOT recognized\n"));
263 negate = !negate; 262 negate = !negate;
264 } 263 }
265 tokpushback++; 264 tokpushback++;
266 n1 = command(); 265 n1 = command();
267 if (readtoken() == TPIPE) { 266 if (readtoken() == TPIPE) {
268 pipenode = stalloc(sizeof(struct npipe)); 267 pipenode = stalloc(sizeof(struct npipe));
269 pipenode->type = NPIPE; 268 pipenode->type = NPIPE;
270 pipenode->npipe.backgnd = 0; 269 pipenode->npipe.backgnd = 0;
271 lp = stalloc(sizeof(struct nodelist)); 270 lp = stalloc(sizeof(struct nodelist));
272 pipenode->npipe.cmdlist = lp; 271 pipenode->npipe.cmdlist = lp;
273 lp->n = n1; 272 lp->n = n1;
274 do { 273 do {
275 prev = lp; 274 prev = lp;
276 lp = stalloc(sizeof(struct nodelist)); 275 lp = stalloc(sizeof(struct nodelist));
277 lp->n = command(); 276 lp->n = command();
278 prev->next = lp; 277 prev->next = lp;
279 } while (readtoken() == TPIPE); 278 } while (readtoken() == TPIPE);
280 lp->next = NULL; 279 lp->next = NULL;
281 n1 = pipenode; 280 n1 = pipenode;
282 } 281 }
283 tokpushback++; 282 tokpushback++;
284 if (negate) { 283 if (negate) {
285 TRACE(("negate pipeline\n")); 284 TRACE(("negate pipeline\n"));
286 n2 = stalloc(sizeof(struct nnot)); 285 n2 = stalloc(sizeof(struct nnot));
287 n2->type = NNOT; 286 n2->type = NNOT;
288 n2->nnot.com = n1; 287 n2->nnot.com = n1;
289 return n2; 288 return n2;
290 } else 289 } else
291 return n1; 290 return n1;
292} 291}
293 292
294 293
295 294
296STATIC union node * 295STATIC union node *
297command(void) 296command(void)
298{ 297{
299 union node *n1, *n2; 298 union node *n1, *n2;
300 union node *ap, **app; 299 union node *ap, **app;
301 union node *cp, **cpp; 300 union node *cp, **cpp;
302 union node *redir, **rpp; 301 union node *redir, **rpp;
303 int t, negate = 0; 302 int t, negate = 0;
304 303
305 TRACE(("command: entered\n")); 304 TRACE(("command: entered\n"));
306 305
307 checkkwd = 2; 306 checkkwd = 2;
308 redir = NULL; 307 redir = NULL;
309 n1 = NULL; 308 n1 = NULL;
310 rpp = &redir; 309 rpp = &redir;
311 310
312 /* Check for redirection which may precede command */ 311 /* Check for redirection which may precede command */
313 while (readtoken() == TREDIR) { 312 while (readtoken() == TREDIR) {
314 *rpp = n2 = redirnode; 313 *rpp = n2 = redirnode;
315 rpp = &n2->nfile.next; 314 rpp = &n2->nfile.next;
316 parsefname(); 315 parsefname();
317 } 316 }
318 tokpushback++; 317 tokpushback++;
319 318
320 while (readtoken() == TNOT) { 319 while (readtoken() == TNOT) {
321 TRACE(("command: TNOT recognized\n")); 320 TRACE(("command: TNOT recognized\n"));
322 negate = !negate; 321 negate = !negate;
323 } 322 }
324 tokpushback++; 323 tokpushback++;
325 324
326 switch (readtoken()) { 325 switch (readtoken()) {
327 case TIF: 326 case TIF:
328 n1 = stalloc(sizeof(struct nif)); 327 n1 = stalloc(sizeof(struct nif));
329 n1->type = NIF; 328 n1->type = NIF;
330 n1->nif.test = list(0, 0); 329 n1->nif.test = list(0, 0);
331 if (readtoken() != TTHEN) 330 if (readtoken() != TTHEN)
332 synexpect(TTHEN, 0); 331 synexpect(TTHEN, 0);
333 n1->nif.ifpart = list(0, 0); 332 n1->nif.ifpart = list(0, 0);
334 n2 = n1; 333 n2 = n1;
335 while (readtoken() == TELIF) { 334 while (readtoken() == TELIF) {
336 n2->nif.elsepart = stalloc(sizeof(struct nif)); 335 n2->nif.elsepart = stalloc(sizeof(struct nif));
337 n2 = n2->nif.elsepart; 336 n2 = n2->nif.elsepart;
338 n2->type = NIF; 337 n2->type = NIF;
339 n2->nif.test = list(0, 0); 338 n2->nif.test = list(0, 0);
340 if (readtoken() != TTHEN) 339 if (readtoken() != TTHEN)
341 synexpect(TTHEN, 0); 340 synexpect(TTHEN, 0);
342 n2->nif.ifpart = list(0, 0); 341 n2->nif.ifpart = list(0, 0);
343 } 342 }
344 if (lasttoken == TELSE) 343 if (lasttoken == TELSE)
345 n2->nif.elsepart = list(0, 0); 344 n2->nif.elsepart = list(0, 0);
346 else { 345 else {
347 n2->nif.elsepart = NULL; 346 n2->nif.elsepart = NULL;
348 tokpushback++; 347 tokpushback++;
349 } 348 }
350 if (readtoken() != TFI) 349 if (readtoken() != TFI)
351 synexpect(TFI, 0); 350 synexpect(TFI, 0);
352 checkkwd = 1; 351 checkkwd = 1;
353 break; 352 break;
354 case TWHILE: 353 case TWHILE:
355 case TUNTIL: { 354 case TUNTIL: {
356 int got; 355 int got;
357 n1 = stalloc(sizeof(struct nbinary)); 356 n1 = stalloc(sizeof(struct nbinary));
358 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 357 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
359 n1->nbinary.ch1 = list(0, 0); 358 n1->nbinary.ch1 = list(0, 0);
360 if ((got=readtoken()) != TDO) { 359 if ((got=readtoken()) != TDO) {
361TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); 360TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
362 synexpect(TDO, 0); 361 synexpect(TDO, 0);
363 } 362 }
364 n1->nbinary.ch2 = list(0, 0); 363 n1->nbinary.ch2 = list(0, 0);
365 if (readtoken() != TDONE) 364 if (readtoken() != TDONE)
366 synexpect(TDONE, 0); 365 synexpect(TDONE, 0);
367 checkkwd = 1; 366 checkkwd = 1;
368 break; 367 break;
369 } 368 }
370 case TFOR: 369 case TFOR:
371 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 370 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
372 synerror("Bad for loop variable"); 371 synerror("Bad for loop variable");
373 n1 = stalloc(sizeof(struct nfor)); 372 n1 = stalloc(sizeof(struct nfor));
374 n1->type = NFOR; 373 n1->type = NFOR;
375 n1->nfor.var = wordtext; 374 n1->nfor.var = wordtext;
376 if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) { 375 if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
377 app = &ap; 376 app = &ap;
378 while (readtoken() == TWORD) { 377 while (readtoken() == TWORD) {
379 n2 = stalloc(sizeof(struct narg)); 378 n2 = stalloc(sizeof(struct narg));
380 n2->type = NARG; 379 n2->type = NARG;
381 n2->narg.text = wordtext; 380 n2->narg.text = wordtext;
382 n2->narg.backquote = backquotelist; 381 n2->narg.backquote = backquotelist;
383 *app = n2; 382 *app = n2;
384 app = &n2->narg.next; 383 app = &n2->narg.next;
385 } 384 }
386 *app = NULL; 385 *app = NULL;
387 n1->nfor.args = ap; 386 n1->nfor.args = ap;
388 if (lasttoken != TNL && lasttoken != TSEMI) 387 if (lasttoken != TNL && lasttoken != TSEMI)
389 synexpect(-1, 0); 388 synexpect(-1, 0);
390 } else { 389 } else {
391 static char argvars[5] = { 390 static char argvars[5] = {
392 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' 391 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
393 }; 392 };
394 n2 = stalloc(sizeof(struct narg)); 393 n2 = stalloc(sizeof(struct narg));
395 n2->type = NARG; 394 n2->type = NARG;
396 n2->narg.text = argvars; 395 n2->narg.text = argvars;
397 n2->narg.backquote = NULL; 396 n2->narg.backquote = NULL;
398 n2->narg.next = NULL; 397 n2->narg.next = NULL;
399 n1->nfor.args = n2; 398 n1->nfor.args = n2;
400 /* 399 /*
401 * Newline or semicolon here is optional (but note 400 * Newline or semicolon here is optional (but note
402 * that the original Bourne shell only allowed NL). 401 * that the original Bourne shell only allowed NL).
403 */ 402 */
404 if (lasttoken != TNL && lasttoken != TSEMI) 403 if (lasttoken != TNL && lasttoken != TSEMI)
405 tokpushback++; 404 tokpushback++;
406 } 405 }
407 checkkwd = 2; 406 checkkwd = 2;
408 if ((t = readtoken()) == TDO) 407 if ((t = readtoken()) == TDO)
409 t = TDONE; 408 t = TDONE;
410 else if (t == TBEGIN) 409 else if (t == TBEGIN)
411 t = TEND; 410 t = TEND;
412 else 411 else
413 synexpect(-1, 0); 412 synexpect(-1, 0);
414 n1->nfor.body = list(0, 0); 413 n1->nfor.body = list(0, 0);
415 if (readtoken() != t) 414 if (readtoken() != t)
416 synexpect(t, 0); 415 synexpect(t, 0);
417 checkkwd = 1; 416 checkkwd = 1;
418 break; 417 break;
419 case TCASE: 418 case TCASE:
420 n1 = stalloc(sizeof(struct ncase)); 419 n1 = stalloc(sizeof(struct ncase));
421 n1->type = NCASE; 420 n1->type = NCASE;
422 if (readtoken() != TWORD) 421 if (readtoken() != TWORD)
423 synexpect(TWORD, 0); 422 synexpect(TWORD, 0);
424 n1->ncase.expr = n2 = stalloc(sizeof(struct narg)); 423 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
425 n2->type = NARG; 424 n2->type = NARG;
426 n2->narg.text = wordtext; 425 n2->narg.text = wordtext;
427 n2->narg.backquote = backquotelist; 426 n2->narg.backquote = backquotelist;
428 n2->narg.next = NULL; 427 n2->narg.next = NULL;
429 while (readtoken() == TNL); 428 while (readtoken() == TNL);
430 if (lasttoken != TWORD || ! equal(wordtext, "in")) 429 if (lasttoken != TWORD || ! equal(wordtext, "in"))
431 synexpect(-1, "in"); 430 synexpect(-1, "in");
432 cpp = &n1->ncase.cases; 431 cpp = &n1->ncase.cases;
433 noalias = 1; 432 noalias = 1;
434 checkkwd = 2, readtoken(); 433 checkkwd = 2, readtoken();
435 /* 434 /*
436 * Both ksh and bash accept 'case x in esac' 435 * Both ksh and bash accept 'case x in esac'
437 * so configure scripts started taking advantage of this. 436 * so configure scripts started taking advantage of this.
438 * The page: http://pubs.opengroup.org/onlinepubs/\ 437 * The page: http://pubs.opengroup.org/onlinepubs/\
439 * 009695399/utilities/xcu_chap02.html contradicts itself, 438 * 009695399/utilities/xcu_chap02.html contradicts itself,
440 * as to if this is legal; the "Case Conditional Format" 439 * as to if this is legal; the "Case Conditional Format"
441 * paragraph shows one case is required, but the "Grammar" 440 * paragraph shows one case is required, but the "Grammar"
442 * section shows a grammar that explicitly allows the no 441 * section shows a grammar that explicitly allows the no
443 * case option. 442 * case option.
444 */ 443 */
445 while (lasttoken != TESAC) { 444 while (lasttoken != TESAC) {
446 *cpp = cp = stalloc(sizeof(struct nclist)); 445 *cpp = cp = stalloc(sizeof(struct nclist));
447 if (lasttoken == TLP) 446 if (lasttoken == TLP)
448 readtoken(); 447 readtoken();
449 cp->type = NCLIST; 448 cp->type = NCLIST;
450 app = &cp->nclist.pattern; 449 app = &cp->nclist.pattern;
451 for (;;) { 450 for (;;) {
452 *app = ap = stalloc(sizeof(struct narg)); 451 *app = ap = stalloc(sizeof(struct narg));
453 ap->type = NARG; 452 ap->type = NARG;
454 ap->narg.text = wordtext; 453 ap->narg.text = wordtext;
455 ap->narg.backquote = backquotelist; 454 ap->narg.backquote = backquotelist;
456 if (checkkwd = 2, readtoken() != TPIPE) 455 if (checkkwd = 2, readtoken() != TPIPE)
457 break; 456 break;
458 app = &ap->narg.next; 457 app = &ap->narg.next;
459 readtoken(); 458 readtoken();
460 } 459 }
461 ap->narg.next = NULL; 460 ap->narg.next = NULL;
462 noalias = 0; 461 noalias = 0;
463 if (lasttoken != TRP) { 462 if (lasttoken != TRP) {
464 synexpect(TRP, 0); 463 synexpect(TRP, 0);
465 } 464 }
466 cp->nclist.body = list(0, 0); 465 cp->nclist.body = list(0, 0);
467 466
468 checkkwd = 2; 467 checkkwd = 2;
469 if ((t = readtoken()) != TESAC) { 468 if ((t = readtoken()) != TESAC) {
470 if (t != TENDCASE) { 469 if (t != TENDCASE) {
471 noalias = 0; 470 noalias = 0;
472 synexpect(TENDCASE, 0); 471 synexpect(TENDCASE, 0);
473 } else { 472 } else {
474 noalias = 1; 473 noalias = 1;
475 checkkwd = 2; 474 checkkwd = 2;
476 readtoken(); 475 readtoken();
477 } 476 }
478 } 477 }
479 cpp = &cp->nclist.next; 478 cpp = &cp->nclist.next;
480 } 479 }
481 noalias = 0; 480 noalias = 0;
482 *cpp = NULL; 481 *cpp = NULL;
483 checkkwd = 1; 482 checkkwd = 1;
484 break; 483 break;
485 case TLP: 484 case TLP:
486 n1 = stalloc(sizeof(struct nredir)); 485 n1 = stalloc(sizeof(struct nredir));
487 n1->type = NSUBSHELL; 486 n1->type = NSUBSHELL;
488 n1->nredir.n = list(0, 0); 487 n1->nredir.n = list(0, 0);
489 n1->nredir.redirect = NULL; 488 n1->nredir.redirect = NULL;
490 if (readtoken() != TRP) 489 if (readtoken() != TRP)
491 synexpect(TRP, 0); 490 synexpect(TRP, 0);
492 checkkwd = 1; 491 checkkwd = 1;
493 break; 492 break;
494 case TBEGIN: 493 case TBEGIN:
495 n1 = list(0, 0); 494 n1 = list(0, 0);
496 if (readtoken() != TEND) 495 if (readtoken() != TEND)
497 synexpect(TEND, 0); 496 synexpect(TEND, 0);
498 checkkwd = 1; 497 checkkwd = 1;
499 break; 498 break;
500 /* Handle an empty command like other simple commands. */ 499 /* Handle an empty command like other simple commands. */
501 case TSEMI: 500 case TSEMI:
502 /* 501 /*
503 * An empty command before a ; doesn't make much sense, and 502 * An empty command before a ; doesn't make much sense, and
504 * should certainly be disallowed in the case of `if ;'. 503 * should certainly be disallowed in the case of `if ;'.
505 */ 504 */
506 if (!redir) 505 if (!redir)
507 synexpect(-1, 0); 506 synexpect(-1, 0);
508 case TAND: 507 case TAND:
509 case TOR: 508 case TOR:
510 case TNL: 509 case TNL:
511 case TEOF: 510 case TEOF:
512 case TWORD: 511 case TWORD:
513 case TRP: 512 case TRP:
514 tokpushback++; 513 tokpushback++;
515 n1 = simplecmd(rpp, redir); 514 n1 = simplecmd(rpp, redir);
516 goto checkneg; 515 goto checkneg;
517 case TENDCASE: 516 case TENDCASE:
518 if (redir) { 517 if (redir) {
519 tokpushback++; 518 tokpushback++;
520 goto checkneg; 519 goto checkneg;
521 } 520 }
522 /* FALLTHROUGH */ 521 /* FALLTHROUGH */
523 default: 522 default:
524 synexpect(-1, 0); 523 synexpect(-1, 0);
525 /* NOTREACHED */ 524 /* NOTREACHED */
526 } 525 }
527 526
528 /* Now check for redirection which may follow command */ 527 /* Now check for redirection which may follow command */
529 while (readtoken() == TREDIR) { 528 while (readtoken() == TREDIR) {
530 *rpp = n2 = redirnode; 529 *rpp = n2 = redirnode;
531 rpp = &n2->nfile.next; 530 rpp = &n2->nfile.next;
532 parsefname(); 531 parsefname();
533 } 532 }
534 tokpushback++; 533 tokpushback++;
535 *rpp = NULL; 534 *rpp = NULL;
536 if (redir) { 535 if (redir) {
537 if (n1->type != NSUBSHELL) { 536 if (n1->type != NSUBSHELL) {
538 n2 = stalloc(sizeof(struct nredir)); 537 n2 = stalloc(sizeof(struct nredir));
539 n2->type = NREDIR; 538 n2->type = NREDIR;
540 n2->nredir.n = n1; 539 n2->nredir.n = n1;
541 n1 = n2; 540 n1 = n2;
542 } 541 }
543 n1->nredir.redirect = redir; 542 n1->nredir.redirect = redir;
544 } 543 }
545 544
546checkneg: 545checkneg:
547 if (negate) { 546 if (negate) {
548 TRACE(("negate command\n")); 547 TRACE(("negate command\n"));
549 n2 = stalloc(sizeof(struct nnot)); 548 n2 = stalloc(sizeof(struct nnot));
550 n2->type = NNOT; 549 n2->type = NNOT;
551 n2->nnot.com = n1; 550 n2->nnot.com = n1;
552 return n2; 551 return n2;
553 } 552 }
554 else 553 else
555 return n1; 554 return n1;
556} 555}
557 556
558 557
559STATIC union node * 558STATIC union node *
560simplecmd(union node **rpp, union node *redir) 559simplecmd(union node **rpp, union node *redir)
561{ 560{
562 union node *args, **app; 561 union node *args, **app;
563 union node *n = NULL, *n2; 562 union node *n = NULL, *n2;
564 int negate = 0; 563 int negate = 0;
565 564
566 /* If we don't have any redirections already, then we must reset */ 565 /* If we don't have any redirections already, then we must reset */
567 /* rpp to be the address of the local redir variable. */ 566 /* rpp to be the address of the local redir variable. */
568 if (redir == 0) 567 if (redir == 0)
569 rpp = &redir; 568 rpp = &redir;
570 569
571 args = NULL; 570 args = NULL;
572 app = &args; 571 app = &args;
573 572
574 while (readtoken() == TNOT) { 573 while (readtoken() == TNOT) {
575 TRACE(("simplcmd: TNOT recognized\n")); 574 TRACE(("simplcmd: TNOT recognized\n"));
576 negate = !negate; 575 negate = !negate;
577 } 576 }
578 tokpushback++; 577 tokpushback++;
579 578
580 for (;;) { 579 for (;;) {
581 if (readtoken() == TWORD) { 580 if (readtoken() == TWORD) {
582 n = stalloc(sizeof(struct narg)); 581 n = stalloc(sizeof(struct narg));
583 n->type = NARG; 582 n->type = NARG;
584 n->narg.text = wordtext; 583 n->narg.text = wordtext;
585 n->narg.backquote = backquotelist; 584 n->narg.backquote = backquotelist;
586 *app = n; 585 *app = n;
587 app = &n->narg.next; 586 app = &n->narg.next;
588 } else if (lasttoken == TREDIR) { 587 } else if (lasttoken == TREDIR) {
589 *rpp = n = redirnode; 588 *rpp = n = redirnode;
590 rpp = &n->nfile.next; 589 rpp = &n->nfile.next;
591 parsefname(); /* read name of redirection file */ 590 parsefname(); /* read name of redirection file */
592 } else if (lasttoken == TLP && app == &args->narg.next 591 } else if (lasttoken == TLP && app == &args->narg.next
593 && redir == 0) { 592 && redir == 0) {
594 /* We have a function */ 593 /* We have a function */
595 if (readtoken() != TRP) 594 if (readtoken() != TRP)
596 synexpect(TRP, 0); 595 synexpect(TRP, 0);
597 funclinno = plinno; 596 funclinno = plinno;
598 rmescapes(n->narg.text); 597 rmescapes(n->narg.text);
599 if (!goodname(n->narg.text)) 598 if (!goodname(n->narg.text))
600 synerror("Bad function name"); 599 synerror("Bad function name");
601 n->type = NDEFUN; 600 n->type = NDEFUN;
602 n->narg.next = command(); 601 n->narg.next = command();
603 funclinno = 0; 602 funclinno = 0;
604 goto checkneg; 603 goto checkneg;
605 } else { 604 } else {
606 tokpushback++; 605 tokpushback++;
607 break; 606 break;
608 } 607 }
609 } 608 }
610 *app = NULL; 609 *app = NULL;
611 *rpp = NULL; 610 *rpp = NULL;
612 n = stalloc(sizeof(struct ncmd)); 611 n = stalloc(sizeof(struct ncmd));
613 n->type = NCMD; 612 n->type = NCMD;
614 n->ncmd.backgnd = 0; 613 n->ncmd.backgnd = 0;
615 n->ncmd.args = args; 614 n->ncmd.args = args;
616 n->ncmd.redirect = redir; 615 n->ncmd.redirect = redir;
617 616
618checkneg: 617checkneg:
619 if (negate) { 618 if (negate) {
620 TRACE(("negate simplecmd\n")); 619 TRACE(("negate simplecmd\n"));
621 n2 = stalloc(sizeof(struct nnot)); 620 n2 = stalloc(sizeof(struct nnot));
622 n2->type = NNOT; 621 n2->type = NNOT;
623 n2->nnot.com = n; 622 n2->nnot.com = n;
624 return n2; 623 return n2;
625 } 624 }
626 else 625 else
627 return n; 626 return n;
628} 627}
629 628
630STATIC union node * 629STATIC union node *
631makename(void) 630makename(void)
632{ 631{
633 union node *n; 632 union node *n;
634 633
635 n = stalloc(sizeof(struct narg)); 634 n = stalloc(sizeof(struct narg));
636 n->type = NARG; 635 n->type = NARG;
637 n->narg.next = NULL; 636 n->narg.next = NULL;
638 n->narg.text = wordtext; 637 n->narg.text = wordtext;
639 n->narg.backquote = backquotelist; 638 n->narg.backquote = backquotelist;
640 return n; 639 return n;
641} 640}
642 641
643void 642void
644fixredir(union node *n, const char *text, int err) 643fixredir(union node *n, const char *text, int err)
645{ 644{
646 TRACE(("Fix redir %s %d\n", text, err)); 645 TRACE(("Fix redir %s %d\n", text, err));
647 if (!err) 646 if (!err)
648 n->ndup.vname = NULL; 647 n->ndup.vname = NULL;
649 648
650 if (is_number(text)) 649 if (is_number(text))
651 n->ndup.dupfd = number(text); 650 n->ndup.dupfd = number(text);
652 else if (text[0] == '-' && text[1] == '\0') 651 else if (text[0] == '-' && text[1] == '\0')
653 n->ndup.dupfd = -1; 652 n->ndup.dupfd = -1;
654 else { 653 else {
655 654
656 if (err) 655 if (err)
657 synerror("Bad fd number"); 656 synerror("Bad fd number");
658 else 657 else
659 n->ndup.vname = makename(); 658 n->ndup.vname = makename();
660 } 659 }
661} 660}
662 661
663 662
664STATIC void 663STATIC void
665parsefname(void) 664parsefname(void)
666{ 665{
667 union node *n = redirnode; 666 union node *n = redirnode;
668 667
669 if (readtoken() != TWORD) 668 if (readtoken() != TWORD)
670 synexpect(-1, 0); 669 synexpect(-1, 0);
671 if (n->type == NHERE) { 670 if (n->type == NHERE) {
672 struct heredoc *here = heredoc; 671 struct heredoc *here = heredoc;
673 struct heredoc *p; 672 struct heredoc *p;
674 int i; 
675 673
676 if (quoteflag == 0) 674 if (quoteflag == 0)
677 n->type = NXHERE; 675 n->type = NXHERE;
678 TRACE(("Here document %d\n", n->type)); 676 TRACE(("Here document %d\n", n->type));
679 if (here->striptabs) { 677 if (here->striptabs) {
680 while (*wordtext == '\t') 678 while (*wordtext == '\t')
681 wordtext++; 679 wordtext++;
682 } 680 }
683 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) 681
 682 /*
 683 * this test is not really necessary, we are not
 684 * required to expand wordtext, but there's no reason
 685 * it cannot be $$ or something like that - that would
 686 * not mean the pid, but literally two '$' characters.
 687 * There is no need for limits on what the word can be.
 688 * However, it needs to stay literal as entered, not
 689 * have $ converted to CTLVAR or something, which as
 690 * the parser is, at the minute, is impossible to prevent.
 691 * So, leave it like this until the rest of the parser is fixed.
 692 */
 693 if (! noexpand(wordtext))
684 synerror("Illegal eof marker for << redirection"); 694 synerror("Illegal eof marker for << redirection");
 695
685 rmescapes(wordtext); 696 rmescapes(wordtext);
686 here->eofmark = wordtext; 697 here->eofmark = wordtext;
687 here->next = NULL; 698 here->next = NULL;
688 if (heredoclist == NULL) 699 if (heredoclist == NULL)
689 heredoclist = here; 700 heredoclist = here;
690 else { 701 else {
691 for (p = heredoclist ; p->next ; p = p->next) 702 for (p = heredoclist ; p->next ; p = p->next)
692 continue; 703 continue;
693 p->next = here; 704 p->next = here;
694 } 705 }
695 } else if (n->type == NTOFD || n->type == NFROMFD) { 706 } else if (n->type == NTOFD || n->type == NFROMFD) {
696 fixredir(n, wordtext, 0); 707 fixredir(n, wordtext, 0);
697 } else { 708 } else {
698 n->nfile.fname = makename(); 709 n->nfile.fname = makename();
699 } 710 }
700} 711}
701 712
 713/*
 714 * Check to see whether we are at the end of the here document. When this
 715 * is called, c is set to the first character of the next input line. If
 716 * we are at the end of the here document, this routine sets the c to PEOF.
 717 * The new value of c is returned.
 718 */
 719
 720static int
 721checkend(int c, char * const eofmark, const int striptabs)
 722{
 723 if (striptabs) {
 724 while (c == '\t')
 725 c = pgetc();
 726 }
 727 if (c == PEOF) {
 728 if (*eofmark == '\0')
 729 return (c);
 730 synerror(EOFhere);
 731 }
 732 if (c == *eofmark) {
 733 int c2;
 734 char *q;
 735
 736 for (q = eofmark + 1; c2 = pgetc(), *q != '\0' && c2 == *q; q++)
 737 ;
 738 if ((c2 == PEOF || c2 == '\n') && *q == '\0') {
 739 c = PEOF;
 740 if (c2 == '\n') {
 741 plinno++;
 742 needprompt = doprompt;
 743 }
 744 } else {
 745 pungetc();
 746 pushstring(eofmark + 1, q - (eofmark + 1), NULL);
 747 }
 748 } else if (c == '\n' && *eofmark == '\0') {
 749 c = PEOF;
 750 plinno++;
 751 needprompt = doprompt;
 752 }
 753 return (c);
 754}
 755
702 756
703/* 757/*
704 * Input any here documents. 758 * Input any here documents.
705 */ 759 */
706 760
707STATIC void 761STATIC void
708parseheredoc(void) 762slurp_heredoc(char *const eofmark, int striptabs, int sq)
 763{
 764 int c;
 765 char *out;
 766
 767 c = pgetc();
 768
 769 /*
 770 * If we hit EOF on the input, and the eofmark is a null string ('')
 771 * we consider this empty line to be the eofmark, and exit without err.
 772 */
 773 if (c == PEOF && *eofmark != '\0')
 774 synerror(EOFhere);
 775
 776 STARTSTACKSTR(out);
 777
 778 while ((c = checkend(c, eofmark, striptabs)) != PEOF) {
 779 do {
 780 if (sq) {
 781 /*
 782 * in single quoted mode (eofmark quoted)
 783 * all we look for is \n so we can check
 784 * for the epfmark - everything saved literally.
 785 */
 786 STPUTC(c, out);
 787 if (c == '\n')
 788 break;
 789 continue;
 790 }
 791 /*
 792 * In double quoted (non-quoted eofmark)
 793 * we must handle \ followed by \n here
 794 * otherwise we can mismatch the end mark.
 795 * All other uses of \ will be handled later
 796 * when the here doc is expanded.
 797 *
 798 * This also makes sure \\ followed by \n does
 799 * not suppress the newline (the \ quotes itself)
 800 */
 801 if (c == '\\') { /* A backslash */
 802 c = pgetc(); /* followed by */
 803 if (c == '\n') /* a newline? */
 804 continue; /* y:drop both */
 805 STPUTC('\\', out); /* else keep \ */
 806 }
 807 STPUTC(c, out); /* keep the char */
 808 if (c == '\n') /* at end of line */
 809 break; /* look for eofmark */
 810
 811 } while ((c = pgetc()) != PEOF);
 812
 813 /*
 814 * If we have read a line, and reached EOF, without
 815 * finding the eofmark, whether the EOF comes before
 816 * or immediately after the \n, that is an error.
 817 */
 818 if (c == PEOF || (c = pgetc()) == PEOF)
 819 synerror(EOFhere);
 820 }
 821 STPUTC('\0', out);
 822
 823 c = out - stackblock();
 824 out = stackblock();
 825 grabstackblock(c);
 826 wordtext = out;
 827
 828 TRACE(("Slurped a heredoc (to '%s')%s: len %d, \"%.16s\"...\n",
 829 eofmark, striptabs ? " tab stripped" : "", c, wordtext));
 830}
 831
 832STATIC void
 833readheredocs(void)
709{ 834{
710 struct heredoc *here; 835 struct heredoc *here;
711 union node *n; 836 union node *n;
712 837
713 while (heredoclist) { 838 while (heredoclist) {
714 int c; 
715 
716 here = heredoclist; 839 here = heredoclist;
717 heredoclist = here->next; 840 heredoclist = here->next;
718 if (needprompt) { 841 if (needprompt) {
719 setprompt(2); 842 setprompt(2);
720 needprompt = 0; 843 needprompt = 0;
721 } 844 }
722 if ((c = pgetc()) == PEOF) { 845
723 synerror(EOFhere); 846 slurp_heredoc(here->eofmark, here->striptabs,
724 /* NOTREACHED */ 847 here->here->nhere.type == NHERE);
725 } 848
726 readtoken1(c, here->here->type == NHERE? SQSYNTAX : DQSYNTAX, 
727 here->eofmark, here->striptabs); 
728 n = stalloc(sizeof(struct narg)); 849 n = stalloc(sizeof(struct narg));
729 n->narg.type = NARG; 850 n->narg.type = NARG;
730 n->narg.next = NULL; 851 n->narg.next = NULL;
731 n->narg.text = wordtext; 852 n->narg.text = wordtext;
732 n->narg.backquote = backquotelist; 853 n->narg.backquote = backquotelist;
733 here->here->nhere.doc = n; 854 here->here->nhere.doc = n;
734 } 855 }
735} 856}
736 857
 858void
 859parse_heredoc(union node *n)
 860{
 861 if (n->narg.type != NARG)
 862 abort();
 863
 864 if (n->narg.text[0] == '\0') /* nothing to do */
 865 return;
 866
 867 setinputstring(n->narg.text, 1);
 868
 869 readtoken1(pgetc(), DQSYNTAX, 1);
 870
 871 n->narg.text = wordtext;
 872 n->narg.backquote = backquotelist;
 873
 874 popfile();
 875}
 876
737STATIC int 877STATIC int
738peektoken(void) 878peektoken(void)
739{ 879{
740 int t; 880 int t;
741 881
742 t = readtoken(); 882 t = readtoken();
743 tokpushback++; 883 tokpushback++;
744 return (t); 884 return (t);
745} 885}
746 886
747STATIC int 887STATIC int
748readtoken(void) 888readtoken(void)
749{ 889{
750 int t; 890 int t;
751 int savecheckkwd = checkkwd; 891 int savecheckkwd = checkkwd;
752#ifdef DEBUG 892#ifdef DEBUG
753 int alreadyseen = tokpushback; 893 int alreadyseen = tokpushback;
754#endif 894#endif
755 struct alias *ap; 895 struct alias *ap;
756 896
757 top: 897 top:
758 t = xxreadtoken(); 898 t = xxreadtoken();
759 899
760 if (checkkwd) { 900 if (checkkwd) {
761 /* 901 /*
762 * eat newlines 902 * eat newlines
763 */ 903 */
764 if (checkkwd == 2) { 904 if (checkkwd == 2) {
765 checkkwd = 0; 905 checkkwd = 0;
766 while (t == TNL) { 906 while (t == TNL) {
767 parseheredoc(); 907 readheredocs();
768 t = xxreadtoken(); 908 t = xxreadtoken();
769 } 909 }
770 } else 910 } else
771 checkkwd = 0; 911 checkkwd = 0;
772 /* 912 /*
773 * check for keywords and aliases 913 * check for keywords and aliases
774 */ 914 */
775 if (t == TWORD && !quoteflag) { 915 if (t == TWORD && !quoteflag) {
776 const char *const *pp; 916 const char *const *pp;
777 917
778 for (pp = parsekwd; *pp; pp++) { 918 for (pp = parsekwd; *pp; pp++) {
779 if (**pp == *wordtext && equal(*pp, wordtext)) { 919 if (**pp == *wordtext && equal(*pp, wordtext)) {
780 lasttoken = t = pp - 920 lasttoken = t = pp -
781 parsekwd + KWDOFFSET; 921 parsekwd + KWDOFFSET;
782 TRACE(("keyword %s recognized\n", tokname[t])); 922 TRACE(("keyword %s recognized\n", tokname[t]));
783 goto out; 923 goto out;
784 } 924 }
785 } 925 }
786 if (!noalias && 926 if (!noalias &&
787 (ap = lookupalias(wordtext, 1)) != NULL) { 927 (ap = lookupalias(wordtext, 1)) != NULL) {
788 pushstring(ap->val, strlen(ap->val), ap); 928 pushstring(ap->val, strlen(ap->val), ap);
789 checkkwd = savecheckkwd; 929 checkkwd = savecheckkwd;
790 goto top; 930 goto top;
791 } 931 }
792 } 932 }
793out: 933out:
794 checkkwd = (t == TNOT) ? savecheckkwd : 0; 934 checkkwd = (t == TNOT) ? savecheckkwd : 0;
795 } 935 }
796 TRACE(("%stoken %s %s\n", alreadyseen ? "reread " : "", tokname[t], t == TWORD ? wordtext : "")); 936 TRACE(("%stoken %s %s\n", alreadyseen ? "reread " : "", tokname[t], t == TWORD ? wordtext : ""));
797 return (t); 937 return (t);
798} 938}
799 939
800 940
801/* 941/*
802 * Read the next input token. 942 * Read the next input token.
803 * If the token is a word, we set backquotelist to the list of cmds in 943 * If the token is a word, we set backquotelist to the list of cmds in
804 * backquotes. We set quoteflag to true if any part of the word was 944 * backquotes. We set quoteflag to true if any part of the word was
805 * quoted. 945 * quoted.
806 * If the token is TREDIR, then we set redirnode to a structure containing 946 * If the token is TREDIR, then we set redirnode to a structure containing
807 * the redirection. 947 * the redirection.
808 * In all cases, the variable startlinno is set to the number of the line 948 * In all cases, the variable startlinno is set to the number of the line
809 * on which the token starts. 949 * on which the token starts.
810 * 950 *
811 * [Change comment: here documents and internal procedures] 951 * [Change comment: here documents and internal procedures]
812 * [Readtoken shouldn't have any arguments. Perhaps we should make the 952 * [Readtoken shouldn't have any arguments. Perhaps we should make the
813 * word parsing code into a separate routine. In this case, readtoken 953 * word parsing code into a separate routine. In this case, readtoken
814 * doesn't need to have any internal procedures, but parseword does. 954 * doesn't need to have any internal procedures, but parseword does.
815 * We could also make parseoperator in essence the main routine, and 955 * We could also make parseoperator in essence the main routine, and
816 * have parseword (readtoken1?) handle both words and redirection.] 956 * have parseword (readtoken1?) handle both words and redirection.]
817 */ 957 */
818 958
819#define RETURN(token) return lasttoken = token 959#define RETURN(token) return lasttoken = token
820 960
821STATIC int 961STATIC int
822xxreadtoken(void) 962xxreadtoken(void)
823{ 963{
824 int c; 964 int c;
825 965
826 if (tokpushback) { 966 if (tokpushback) {
827 tokpushback = 0; 967 tokpushback = 0;
828 return lasttoken; 968 return lasttoken;
829 } 969 }
830 if (needprompt) { 970 if (needprompt) {
831 setprompt(2); 971 setprompt(2);
832 needprompt = 0; 972 needprompt = 0;
833 } 973 }
834 startlinno = plinno; 974 startlinno = plinno;
835 for (;;) { /* until token or start of word found */ 975 for (;;) { /* until token or start of word found */
836 c = pgetc_macro(); 976 c = pgetc_macro();
837 switch (c) { 977 switch (c) {
838 case ' ': case '\t': 978 case ' ': case '\t':
839 continue; 979 continue;
840 case '#': 980 case '#':
841 while ((c = pgetc()) != '\n' && c != PEOF) 981 while ((c = pgetc()) != '\n' && c != PEOF)
842 continue; 982 continue;
843 pungetc(); 983 pungetc();
844 continue; 984 continue;
845 985
846 case '\n': 986 case '\n':
847 plinno++; 987 plinno++;
848 needprompt = doprompt; 988 needprompt = doprompt;
849 RETURN(TNL); 989 RETURN(TNL);
850 case PEOF: 990 case PEOF:
851 RETURN(TEOF); 991 RETURN(TEOF);
852 992
853 case '&': 993 case '&':
854 if (pgetc() == '&') 994 if (pgetc() == '&')
855 RETURN(TAND); 995 RETURN(TAND);
856 pungetc(); 996 pungetc();
857 RETURN(TBACKGND); 997 RETURN(TBACKGND);
858 case '|': 998 case '|':
859 if (pgetc() == '|') 999 if (pgetc() == '|')
860 RETURN(TOR); 1000 RETURN(TOR);
861 pungetc(); 1001 pungetc();
862 RETURN(TPIPE); 1002 RETURN(TPIPE);
863 case ';': 1003 case ';':
864 if (pgetc() == ';') 1004 if (pgetc() == ';')
865 RETURN(TENDCASE); 1005 RETURN(TENDCASE);
866 pungetc(); 1006 pungetc();
867 RETURN(TSEMI); 1007 RETURN(TSEMI);
868 case '(': 1008 case '(':
869 RETURN(TLP); 1009 RETURN(TLP);
870 case ')': 1010 case ')':
871 RETURN(TRP); 1011 RETURN(TRP);
872 1012
873 case '\\': 1013 case '\\':
874 switch (pgetc()) { 1014 switch (pgetc()) {
875 case '\n': 1015 case '\n':
876 startlinno = ++plinno; 1016 startlinno = ++plinno;
877 if (doprompt) 1017 if (doprompt)
878 setprompt(2); 1018 setprompt(2);
879 else 1019 else
880 setprompt(0); 1020 setprompt(0);
881 continue; 1021 continue;
882 case PEOF: 1022 case PEOF:
883 RETURN(TEOF); 1023 RETURN(TEOF);
884 default: 1024 default:
885 pungetc(); 1025 pungetc();
886 break; 1026 break;
887 } 1027 }
888 /* FALLTHROUGH */ 1028 /* FALLTHROUGH */
889 default: 1029 default:
890 return readtoken1(c, BASESYNTAX, NULL, 0); 1030 return readtoken1(c, BASESYNTAX, 0);
891 } 1031 }
892 } 1032 }
893#undef RETURN 1033#undef RETURN
894} 1034}
895 1035
896 1036
897 1037
898/* 1038/*
899 * If eofmark is NULL, read a word or a redirection symbol. If eofmark 1039 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
900 * is not NULL, read a here document. In the latter case, eofmark is the 1040 * is not NULL, read a here document. In the latter case, eofmark is the
901 * word which marks the end of the document and striptabs is true if 1041 * word which marks the end of the document and striptabs is true if
902 * leading tabs should be stripped from the document. The argument firstc 1042 * leading tabs should be stripped from the document. The argument firstc
903 * is the first character of the input token or document. 1043 * is the first character of the input token or document.
904 * 1044 *
905 * Because C does not have internal subroutines, I have simulated them 1045 * Because C does not have internal subroutines, I have simulated them
906 * using goto's to implement the subroutine linkage. The following macros 1046 * using goto's to implement the subroutine linkage. The following macros
907 * will run code that appears at the end of readtoken1. 1047 * will run code that appears at the end of readtoken1.
908 */ 1048 */
909 1049
910/* 1050/*
911 * We used to remember only the current syntax, variable nesting level, 1051 * We used to remember only the current syntax, variable nesting level,
912 * double quote state for each var nesting level, and arith nesting 1052 * double quote state for each var nesting level, and arith nesting
913 * level (unrelated to var nesting) and one prev syntax when in arith 1053 * level (unrelated to var nesting) and one prev syntax when in arith
914 * syntax. This worked for simple cases, but can't handle arith inside 1054 * syntax. This worked for simple cases, but can't handle arith inside
915 * var expansion inside arith inside var with some quoted and some not. 1055 * var expansion inside arith inside var with some quoted and some not.
916 * 1056 *
917 * Inspired by FreeBSD's implementation (though it was the obvious way) 1057 * Inspired by FreeBSD's implementation (though it was the obvious way)
918 * though implemented differently, we now have a stack that keeps track 1058 * though implemented differently, we now have a stack that keeps track
919 * of what we are doing now, and what we were doing previously. 1059 * of what we are doing now, and what we were doing previously.
920 * Every time something changes, which will eventually end and should 1060 * Every time something changes, which will eventually end and should
921 * revert to the previous state, we push this stack, and then pop it 1061 * revert to the previous state, we push this stack, and then pop it
922 * again later (that is every ${} with an operator (to parse the word 1062 * again later (that is every ${} with an operator (to parse the word
923 * or pattern that follows) ${x} and $x are too simple to need it) 1063 * or pattern that follows) ${x} and $x are too simple to need it)
924 * $(( )) $( ) and "...". Always. Really, always! 1064 * $(( )) $( ) and "...". Always. Really, always!
925 * 1065 *
926 * The stack is implemented as one static (on the C stack) base block 1066 * The stack is implemented as one static (on the C stack) base block
927 * containing LEVELS_PER_BLOCK (8) stack entries, which should be 1067 * containing LEVELS_PER_BLOCK (8) stack entries, which should be
928 * enough for the vast majority of cases. For torture tests, we 1068 * enough for the vast majority of cases. For torture tests, we
929 * malloc more blocks as needed. All accesses through the inline 1069 * malloc more blocks as needed. All accesses through the inline
930 * functions below. 1070 * functions below.
931 */ 1071 */
932 1072
933/* 1073/*
934 * varnest & arinest will typically be 0 or 1 1074 * varnest & arinest will typically be 0 or 1
935 * (varnest can increment in usages like ${x=${y}} but probably 1075 * (varnest can increment in usages like ${x=${y}} but probably
936 * does not really need to) 1076 * does not really need to)
937 * parenlevel allows balancing parens inside a $(( )), it is reset 1077 * parenlevel allows balancing parens inside a $(( )), it is reset
938 * at each new nesting level ( $(( ( x + 3 ${unset-)} )) does not work. 1078 * at each new nesting level ( $(( ( x + 3 ${unset-)} )) does not work.
939 * quoted is special - we need to know 2 things ... are we inside "..." 1079 * quoted is special - we need to know 2 things ... are we inside "..."
940 * (even if inherited from some previous nesting level) and was there 1080 * (even if inherited from some previous nesting level) and was there
941 * an opening '"' at this level (so the next will be closing). 1081 * an opening '"' at this level (so the next will be closing).
942 * "..." can span nesting levels, but cannot be opened in one and 1082 * "..." can span nesting levels, but cannot be opened in one and
943 * closed in a different one. 1083 * closed in a different one.
944 * To handle this, "quoted" has two fields, the bottom 4 (really 2) 1084 * To handle this, "quoted" has two fields, the bottom 4 (really 2)
945 * bits are 0, 1, or 2, for un, single, and double quoted (single quoted 1085 * bits are 0, 1, or 2, for un, single, and double quoted (single quoted
946 * is really so special that this setting is not very important) 1086 * is really so special that this setting is not very important)
947 * and 0x10 that indicates that an opening quote has been seen. 1087 * and 0x10 that indicates that an opening quote has been seen.
948 * The bottom 4 bits are inherited, the 0x10 bit is not. 1088 * The bottom 4 bits are inherited, the 0x10 bit is not.
949 */ 1089 */
950struct tokenstate { 1090struct tokenstate {
951 const char *ts_syntax; 1091 const char *ts_syntax;
952 unsigned short ts_parenlevel; /* counters */ 1092 unsigned short ts_parenlevel; /* counters */
953 unsigned short ts_varnest; /* 64000 levels should be enough! */ 1093 unsigned short ts_varnest; /* 64000 levels should be enough! */
954 unsigned short ts_arinest; 1094 unsigned short ts_arinest;
955 unsigned short ts_quoted; /* 1 -> single, 2 -> double */ 1095 unsigned short ts_quoted; /* 1 -> single, 2 -> double */
956}; 1096};
957 1097
958#define NQ 0x00 /* Unquoted */ 1098#define NQ 0x00 /* Unquoted */
959#define SQ 0x01 /* Single Quotes */ 1099#define SQ 0x01 /* Single Quotes */
960#define DQ 0x02 /* Double Quotes (or equivalent) */ 1100#define DQ 0x02 /* Double Quotes (or equivalent) */
961#define QF 0x0F /* Mask to extract previous values */ 1101#define QF 0x0F /* Mask to extract previous values */
962#define QS 0x10 /* Quoting started at this level in stack */ 1102#define QS 0x10 /* Quoting started at this level in stack */
963 1103
964#define LEVELS_PER_BLOCK 8 1104#define LEVELS_PER_BLOCK 8
965#define VSS struct statestack 1105#define VSS struct statestack
966 1106
967struct statestack { 1107struct statestack {
968 VSS *prev; /* previous block in list */ 1108 VSS *prev; /* previous block in list */
969 int cur; /* which of our tokenstates is current */ 1109 int cur; /* which of our tokenstates is current */
970 struct tokenstate tokenstate[LEVELS_PER_BLOCK]; 1110 struct tokenstate tokenstate[LEVELS_PER_BLOCK];
971}; 1111};
972 1112
973static inline struct tokenstate * 1113static inline struct tokenstate *
974currentstate(VSS *stack) 1114currentstate(VSS *stack)
975{ 1115{
976 return &stack->tokenstate[stack->cur]; 1116 return &stack->tokenstate[stack->cur];
977} 1117}
978 1118
979static inline struct tokenstate * 1119static inline struct tokenstate *
980prevstate(VSS *stack) 1120prevstate(VSS *stack)
981{ 1121{
982 if (stack->cur != 0) 1122 if (stack->cur != 0)
983 return &stack->tokenstate[stack->cur - 1]; 1123 return &stack->tokenstate[stack->cur - 1];
984 if (stack->prev == NULL) /* cannot drop below base */ 1124 if (stack->prev == NULL) /* cannot drop below base */
985 return &stack->tokenstate[0]; 1125 return &stack->tokenstate[0];
986 return &stack->prev->tokenstate[LEVELS_PER_BLOCK - 1]; 1126 return &stack->prev->tokenstate[LEVELS_PER_BLOCK - 1];
987} 1127}
988 1128
989static inline VSS * 1129static inline VSS *
990bump_state_level(VSS *stack) 1130bump_state_level(VSS *stack)
991{ 1131{
992 struct tokenstate *os, *ts; 1132 struct tokenstate *os, *ts;
993 1133
994 os = currentstate(stack); 1134 os = currentstate(stack);
995 1135
996 if (++stack->cur >= LEVELS_PER_BLOCK) { 1136 if (++stack->cur >= LEVELS_PER_BLOCK) {
997 VSS *ss; 1137 VSS *ss;
998 1138
999 ss = (VSS *)ckmalloc(sizeof (struct statestack)); 1139 ss = (VSS *)ckmalloc(sizeof (struct statestack));
1000 ss->cur = 0; 1140 ss->cur = 0;
1001 ss->prev = stack; 1141 ss->prev = stack;
1002 stack = ss; 1142 stack = ss;
1003 } 1143 }
1004 1144
1005 ts = currentstate(stack); 1145 ts = currentstate(stack);
1006 1146
1007 ts->ts_parenlevel = 0; /* parens inside never match outside */ 1147 ts->ts_parenlevel = 0; /* parens inside never match outside */
1008 1148
1009 ts->ts_quoted = os->ts_quoted & QF; /* these are default settings */ 1149 ts->ts_quoted = os->ts_quoted & QF; /* these are default settings */
1010 ts->ts_varnest = os->ts_varnest; 1150 ts->ts_varnest = os->ts_varnest;
1011 ts->ts_arinest = os->ts_arinest; /* when appropriate */ 1151 ts->ts_arinest = os->ts_arinest; /* when appropriate */
1012 ts->ts_syntax = os->ts_syntax; /* they will be altered */ 1152 ts->ts_syntax = os->ts_syntax; /* they will be altered */
1013 1153
1014 return stack; 1154 return stack;
1015} 1155}
1016 1156
1017static inline VSS * 1157static inline VSS *
1018drop_state_level(VSS *stack) 1158drop_state_level(VSS *stack)
1019{ 1159{
1020 if (stack->cur == 0) { 1160 if (stack->cur == 0) {
1021 VSS *ss; 1161 VSS *ss;
1022 1162
1023 ss = stack; 1163 ss = stack;
1024 stack = ss->prev; 1164 stack = ss->prev;
1025 if (stack == NULL) 1165 if (stack == NULL)
1026 return ss; 1166 return ss;
1027 ckfree(ss); 1167 ckfree(ss);
1028 } 1168 }
1029 --stack->cur; 1169 --stack->cur;
1030 return stack; 1170 return stack;
1031} 1171}
1032 1172
1033static inline void 1173static inline void
1034cleanup_state_stack(VSS *stack) 1174cleanup_state_stack(VSS *stack)
1035{ 1175{
1036 while (stack->prev != NULL) { 1176 while (stack->prev != NULL) {
1037 stack->cur = 0; 1177 stack->cur = 0;
1038 stack = drop_state_level(stack); 1178 stack = drop_state_level(stack);
1039 } 1179 }
1040} 1180}
1041 1181
1042#define CHECKEND() {goto checkend; checkend_return:;} 
1043#define PARSEREDIR() {goto parseredir; parseredir_return:;} 1182#define PARSEREDIR() {goto parseredir; parseredir_return:;}
1044#define PARSESUB() {goto parsesub; parsesub_return:;} 1183#define PARSESUB() {goto parsesub; parsesub_return:;}
1045#define PARSEARITH() {goto parsearith; parsearith_return:;} 1184#define PARSEARITH() {goto parsearith; parsearith_return:;}
1046 1185
1047/* 1186/*
1048 * The following macros all assume the existance of a local var "stack" 1187 * The following macros all assume the existance of a local var "stack"
1049 * which contains a pointer to the current struct stackstate 1188 * which contains a pointer to the current struct stackstate
1050 */ 1189 */
1051 1190
1052/* 1191/*
1053 * These are macros rather than inline funcs to avoid code churn as much 1192 * These are macros rather than inline funcs to avoid code churn as much
1054 * as possible - they replace macros of the same name used previously. 1193 * as possible - they replace macros of the same name used previously.
1055 */ 1194 */
1056#define ISDBLQUOTE() (currentstate(stack)->ts_quoted & QS) 1195#define ISDBLQUOTE() (currentstate(stack)->ts_quoted & QS)
1057#define SETDBLQUOTE() (currentstate(stack)->ts_quoted = QS | DQ) 1196#define SETDBLQUOTE() (currentstate(stack)->ts_quoted = QS | DQ)
1058#define CLRDBLQUOTE() (currentstate(stack)->ts_quoted = \ 1197#define CLRDBLQUOTE() (currentstate(stack)->ts_quoted = \
1059 stack->cur != 0 || stack->prev ? \ 1198 stack->cur != 0 || stack->prev ? \
1060 prevstate(stack)->ts_quoted & QF : 0) 1199 prevstate(stack)->ts_quoted & QF : 0)
1061 1200
1062/* 1201/*
1063 * This set are just to avoid excess typing and line lengths... 1202 * This set are just to avoid excess typing and line lengths...
1064 * The ones that "look like" var names must be implemented to be lvalues 1203 * The ones that "look like" var names must be implemented to be lvalues
1065 */ 1204 */
1066#define syntax (currentstate(stack)->ts_syntax) 1205#define syntax (currentstate(stack)->ts_syntax)
1067#define parenlevel (currentstate(stack)->ts_parenlevel) 1206#define parenlevel (currentstate(stack)->ts_parenlevel)
1068#define varnest (currentstate(stack)->ts_varnest) 1207#define varnest (currentstate(stack)->ts_varnest)
1069#define arinest (currentstate(stack)->ts_arinest) 1208#define arinest (currentstate(stack)->ts_arinest)
1070#define quoted (currentstate(stack)->ts_quoted) 1209#define quoted (currentstate(stack)->ts_quoted)
1071#define TS_PUSH() (stack = bump_state_level(stack)) 1210#define TS_PUSH() (stack = bump_state_level(stack))
1072#define TS_POP() (stack = drop_state_level(stack)) 1211#define TS_POP() (stack = drop_state_level(stack))
1073 1212
1074/* 1213/*
1075 * Called to parse command substitutions. oldstyle is true if the command 1214 * Called to parse command substitutions. oldstyle is true if the command
1076 * is enclosed inside `` (otherwise it was enclosed in "$( )") 1215 * is enclosed inside `` (otherwise it was enclosed in "$( )")
1077 * 1216 *
1078 * Internally nlpp is a pointer to the head of the linked 1217 * Internally nlpp is a pointer to the head of the linked
1079 * list of commands (passed by reference), and savelen is the number of 1218 * list of commands (passed by reference), and savelen is the number of
1080 * characters on the top of the stack which must be preserved. 1219 * characters on the top of the stack which must be preserved.
1081 */ 1220 */
1082static char * 1221static char *
1083parsebackq(VSS *const stack, char * const in, 1222parsebackq(VSS *const stack, char * const in,
1084 struct nodelist **const pbqlist, const int oldstyle) 1223 struct nodelist **const pbqlist, const int oldstyle)
1085{ 1224{
1086 struct nodelist **nlpp; 1225 struct nodelist **nlpp;
1087 const int savepbq = parsebackquote; 1226 const int savepbq = parsebackquote;
1088 union node *n; 1227 union node *n;
1089 char *out; 1228 char *out;
1090 char *str = NULL; 1229 char *str = NULL;
1091 char *volatile sstr = str; 1230 char *volatile sstr = str;
1092 struct jmploc jmploc; 1231 struct jmploc jmploc;
1093 struct jmploc *const savehandler = handler; 1232 struct jmploc *const savehandler = handler;
1094 const int savelen = in - stackblock(); 1233 const int savelen = in - stackblock();
1095 int saveprompt; 1234 int saveprompt;
1096 1235
1097 if (setjmp(jmploc.loc)) { 1236 if (setjmp(jmploc.loc)) {
1098 if (sstr) 1237 if (sstr)
1099 ckfree(__UNVOLATILE(sstr)); 1238 ckfree(__UNVOLATILE(sstr));
1100 cleanup_state_stack(stack); 1239 cleanup_state_stack(stack);
1101 parsebackquote = 0; 1240 parsebackquote = 0;
1102 handler = savehandler; 1241 handler = savehandler;
1103 longjmp(handler->loc, 1); 1242 longjmp(handler->loc, 1);
1104 } 1243 }
1105 INTOFF; 1244 INTOFF;
1106 sstr = str = NULL; 1245 sstr = str = NULL;
1107 if (savelen > 0) { 1246 if (savelen > 0) {
1108 sstr = str = ckmalloc(savelen); 1247 sstr = str = ckmalloc(savelen);
1109 memcpy(str, stackblock(), savelen); 1248 memcpy(str, stackblock(), savelen);
1110 } 1249 }
1111 handler = &jmploc; 1250 handler = &jmploc;
1112 INTON; 1251 INTON;
1113 if (oldstyle) { 1252 if (oldstyle) {
1114 /* We must read until the closing backquote, giving special 1253 /* We must read until the closing backquote, giving special
1115 treatment to some slashes, and then push the string and 1254 treatment to some slashes, and then push the string and
1116 reread it as input, interpreting it normally. */ 1255 reread it as input, interpreting it normally. */
1117 int pc; 1256 int pc;
1118 int psavelen; 1257 int psavelen;
1119 char *pstr; 1258 char *pstr;
1120 1259
1121 /* 1260 /*
1122 * Because the entire `...` is read here, we don't 1261 * Because the entire `...` is read here, we don't
1123 * need to bother the state stack. That will be used 1262 * need to bother the state stack. That will be used
1124 * (as appropriate) when the processed string is re-read. 1263 * (as appropriate) when the processed string is re-read.
1125 */ 1264 */
1126 STARTSTACKSTR(out); 1265 STARTSTACKSTR(out);
1127 for (;;) { 1266 for (;;) {
1128 if (needprompt) { 1267 if (needprompt) {
1129 setprompt(2); 1268 setprompt(2);
1130 needprompt = 0; 1269 needprompt = 0;
1131 } 1270 }
1132 switch (pc = pgetc()) { 1271 switch (pc = pgetc()) {
1133 case '`': 1272 case '`':
1134 goto done; 1273 goto done;
1135 1274
1136 case '\\': 1275 case '\\':
1137 if ((pc = pgetc()) == '\n') { 1276 if ((pc = pgetc()) == '\n') {
1138 plinno++; 1277 plinno++;
1139 if (doprompt) 1278 if (doprompt)
1140 setprompt(2); 1279 setprompt(2);
1141 else 1280 else
1142 setprompt(0); 1281 setprompt(0);
1143 /* 1282 /*
1144 * If eating a newline, avoid putting 1283 * If eating a newline, avoid putting
1145 * the newline into the new character 1284 * the newline into the new character
1146 * stream (via the STPUTC after the 1285 * stream (via the STPUTC after the
1147 * switch). 1286 * switch).
1148 */ 1287 */
1149 continue; 1288 continue;
1150 } 1289 }
1151 if (pc != '\\' && pc != '`' && pc != '$' 1290 if (pc != '\\' && pc != '`' && pc != '$'
1152 && (!ISDBLQUOTE() || pc != '"')) 1291 && (!ISDBLQUOTE() || pc != '"'))
1153 STPUTC('\\', out); 1292 STPUTC('\\', out);
1154 break; 1293 break;
1155 1294
1156 case '\n': 1295 case '\n':
1157 plinno++; 1296 plinno++;
1158 needprompt = doprompt; 1297 needprompt = doprompt;
1159 break; 1298 break;
1160 1299
1161 case PEOF: 1300 case PEOF:
1162 startlinno = plinno; 1301 startlinno = plinno;
1163 synerror("EOF in backquote substitution"); 1302 synerror("EOF in backquote substitution");
1164 break; 1303 break;
1165 1304
1166 default: 1305 default:
1167 break; 1306 break;
1168 } 1307 }
1169 STPUTC(pc, out); 1308 STPUTC(pc, out);
1170 } 1309 }
1171done: 1310done:
1172 STPUTC('\0', out); 1311 STPUTC('\0', out);
1173 psavelen = out - stackblock(); 1312 psavelen = out - stackblock();
1174 if (psavelen > 0) { 1313 if (psavelen > 0) {
1175 pstr = grabstackstr(out); 1314 pstr = grabstackstr(out);
1176 setinputstring(pstr, 1); 1315 setinputstring(pstr, 1);
1177 } 1316 }
1178 } 1317 }
1179 nlpp = pbqlist; 1318 nlpp = pbqlist;
1180 while (*nlpp) 1319 while (*nlpp)
1181 nlpp = &(*nlpp)->next; 1320 nlpp = &(*nlpp)->next;
1182 *nlpp = stalloc(sizeof(struct nodelist)); 1321 *nlpp = stalloc(sizeof(struct nodelist));
1183 (*nlpp)->next = NULL; 1322 (*nlpp)->next = NULL;
1184 parsebackquote = oldstyle; 1323 parsebackquote = oldstyle;
1185 1324
1186 if (oldstyle) { 1325 if (oldstyle) {
1187 saveprompt = doprompt; 1326 saveprompt = doprompt;
1188 doprompt = 0; 1327 doprompt = 0;
1189 } else 1328 } else
1190 saveprompt = 0; 1329 saveprompt = 0;
1191 1330
1192 n = list(0, oldstyle); 1331 n = list(0, oldstyle);
1193 1332
1194 if (oldstyle) 1333 if (oldstyle)
1195 doprompt = saveprompt; 1334 doprompt = saveprompt;
1196 else { 1335 else {
1197 if (readtoken() != TRP) { 1336 if (readtoken() != TRP) {
1198 cleanup_state_stack(stack); 1337 cleanup_state_stack(stack);
1199 synexpect(TRP, 0); 1338 synexpect(TRP, 0);
1200 } 1339 }
1201 } 1340 }
1202 1341
1203 (*nlpp)->n = n; 1342 (*nlpp)->n = n;
1204 if (oldstyle) { 1343 if (oldstyle) {
1205 /* 1344 /*
1206 * Start reading from old file again, ignoring any pushed back 1345 * Start reading from old file again, ignoring any pushed back
1207 * tokens left from the backquote parsing 1346 * tokens left from the backquote parsing
1208 */ 1347 */
1209 popfile(); 1348 popfile();
1210 tokpushback = 0; 1349 tokpushback = 0;
1211 } 1350 }
1212 1351
1213 while (stackblocksize() <= savelen) 1352 while (stackblocksize() <= savelen)
1214 growstackblock(); 1353 growstackblock();
1215 STARTSTACKSTR(out); 1354 STARTSTACKSTR(out);
1216 if (str) { 1355 if (str) {
1217 memcpy(out, str, savelen); 1356 memcpy(out, str, savelen);
1218 STADJUST(savelen, out); 1357 STADJUST(savelen, out);
1219 INTOFF; 1358 INTOFF;
1220 ckfree(str); 1359 ckfree(str);
1221 sstr = str = NULL; 1360 sstr = str = NULL;
1222 INTON; 1361 INTON;
1223 } 1362 }
1224 parsebackquote = savepbq; 1363 parsebackquote = savepbq;
1225 handler = savehandler; 1364 handler = savehandler;
1226 if (arinest || ISDBLQUOTE()) 1365 if (arinest || ISDBLQUOTE())
1227 USTPUTC(CTLBACKQ | CTLQUOTE, out); 1366 USTPUTC(CTLBACKQ | CTLQUOTE, out);
1228 else 1367 else
1229 USTPUTC(CTLBACKQ, out); 1368 USTPUTC(CTLBACKQ, out);
1230 1369
1231 return out; 1370 return out;
1232} 1371}
1233 1372
1234STATIC int 1373STATIC int
1235readtoken1(int firstc, char const *syn, char *eofmark, int striptabs) 1374readtoken1(int firstc, char const *syn, int magicq)
1236{ 1375{
1237 int c = firstc; 1376 int c = firstc;
1238 char * out; 1377 char * out;
1239 int len; 1378 int len;
1240 char line[EOFMARKLEN + 1]; 
1241 struct nodelist *bqlist; 1379 struct nodelist *bqlist;
1242 int quotef; 1380 int quotef;
1243 VSS static_stack; 1381 VSS static_stack;
1244 VSS *stack = &static_stack; 1382 VSS *stack = &static_stack;
1245 1383
1246 stack->prev = NULL; 1384 stack->prev = NULL;
1247 stack->cur = 0; 1385 stack->cur = 0;
1248 1386
1249 syntax = syn; 1387 syntax = syn;
1250 1388
1251 startlinno = plinno; 1389 startlinno = plinno;
1252 varnest = 0; 1390 varnest = 0;
1253 quoted = 0; 1391 quoted = 0;
1254 if (syntax == DQSYNTAX) 1392 if (syntax == DQSYNTAX)
1255 SETDBLQUOTE(); 1393 SETDBLQUOTE();
1256 quotef = 0; 1394 quotef = 0;
1257 bqlist = NULL; 1395 bqlist = NULL;
1258 arinest = 0; 1396 arinest = 0;
1259 parenlevel = 0; 1397 parenlevel = 0;
1260 1398
1261 STARTSTACKSTR(out); 1399 STARTSTACKSTR(out);
1262 loop: { /* for each line, until end of word */ 1400 loop: { /* for each line, until end of word */
1263 CHECKEND(); /* set c to PEOF if at end of here document */ 
1264 for (;;) { /* until end of line or end of word */ 1401 for (;;) { /* until end of line or end of word */
1265 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ 1402 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
1266 switch(syntax[c]) { 1403 switch(syntax[c]) {
1267 case CNL: /* '\n' */ 1404 case CNL: /* '\n' */
1268 if (syntax == BASESYNTAX) 1405 if (syntax == BASESYNTAX)
1269 goto endword; /* exit outer loop */ 1406 goto endword; /* exit outer loop */
1270 USTPUTC(c, out); 1407 USTPUTC(c, out);
1271 plinno++; 1408 plinno++;
1272 if (doprompt) 1409 if (doprompt)
1273 setprompt(2); 1410 setprompt(2);
1274 else 1411 else
1275 setprompt(0); 1412 setprompt(0);
1276 c = pgetc(); 1413 c = pgetc();
1277 goto loop; /* continue outer loop */ 1414 goto loop; /* continue outer loop */
1278 case CWORD: 1415 case CWORD:
1279 USTPUTC(c, out); 1416 USTPUTC(c, out);
1280 break; 1417 break;
1281 case CCTL: 1418 case CCTL:
1282 if (eofmark == NULL || ISDBLQUOTE()) 1419 if (!magicq || ISDBLQUOTE())
1283 USTPUTC(CTLESC, out); 1420 USTPUTC(CTLESC, out);
1284 USTPUTC(c, out); 1421 USTPUTC(c, out);
1285 break; 1422 break;
1286 case CBACK: /* backslash */ 1423 case CBACK: /* backslash */
1287 c = pgetc(); 1424 c = pgetc();
1288 if (c == PEOF) { 1425 if (c == PEOF) {
1289 USTPUTC('\\', out); 1426 USTPUTC('\\', out);
1290 pungetc(); 1427 pungetc();
1291 break; 1428 break;
1292 } 1429 }
1293 if (c == '\n') { 1430 if (c == '\n') {
1294 plinno++; 1431 plinno++;
1295 if (doprompt) 1432 if (doprompt)
1296 setprompt(2); 1433 setprompt(2);
1297 else 1434 else
1298 setprompt(0); 1435 setprompt(0);
1299 break; 1436 break;
1300 } 1437 }
1301 quotef = 1; 1438 quotef = 1;
1302 if (ISDBLQUOTE() && c != '\\' && 1439 if (ISDBLQUOTE() && c != '\\' &&
1303 c != '`' && c != '$' && 1440 c != '`' && c != '$' &&
1304 (c != '"' || eofmark != NULL)) 1441 (c != '"' || magicq))
1305 USTPUTC('\\', out); 1442 USTPUTC('\\', out);
1306 if (SQSYNTAX[c] == CCTL) 1443 if (SQSYNTAX[c] == CCTL)
1307 USTPUTC(CTLESC, out); 1444 USTPUTC(CTLESC, out);
1308 else if (eofmark == NULL) { 1445 else if (!magicq) {
1309 USTPUTC(CTLQUOTEMARK, out); 1446 USTPUTC(CTLQUOTEMARK, out);
1310 USTPUTC(c, out); 1447 USTPUTC(c, out);
1311 if (varnest != 0) 1448 if (varnest != 0)
1312 USTPUTC(CTLQUOTEEND, out); 1449 USTPUTC(CTLQUOTEEND, out);
1313 break; 1450 break;
1314 } 1451 }
1315 USTPUTC(c, out); 1452 USTPUTC(c, out);
1316 break; 1453 break;
1317 case CSQUOTE: 1454 case CSQUOTE:
1318 if (syntax != SQSYNTAX) { 1455 if (syntax != SQSYNTAX) {
1319 if (eofmark == NULL) 1456 if (!magicq)
1320 USTPUTC(CTLQUOTEMARK, out); 1457 USTPUTC(CTLQUOTEMARK, out);
1321 quotef = 1; 1458 quotef = 1;
1322 TS_PUSH(); 1459 TS_PUSH();
1323 syntax = SQSYNTAX; 1460 syntax = SQSYNTAX;
1324 quoted = SQ; 1461 quoted = SQ;
1325 break; 1462 break;
1326 } 1463 }
1327 if (eofmark != NULL && arinest == 0 && 1464 if (magicq && arinest == 0 && varnest == 0) {
1328 varnest == 0) { 
1329 /* Ignore inside quoted here document */ 1465 /* Ignore inside quoted here document */
1330 USTPUTC(c, out); 1466 USTPUTC(c, out);
1331 break; 1467 break;
1332 } 1468 }
1333 /* End of single quotes... */ 1469 /* End of single quotes... */
1334 TS_POP(); 1470 TS_POP();
1335 if (syntax == BASESYNTAX && varnest != 0) 1471 if (syntax == BASESYNTAX && varnest != 0)
1336 USTPUTC(CTLQUOTEEND, out); 1472 USTPUTC(CTLQUOTEEND, out);
1337 break; 1473 break;
1338 case CDQUOTE: 1474 case CDQUOTE:
1339 if (eofmark != NULL && arinest == 0 && 1475 if (magicq && arinest == 0 && varnest == 0) {
1340 varnest == 0) { 
1341 /* Ignore inside here document */ 1476 /* Ignore inside here document */
1342 USTPUTC(c, out); 1477 USTPUTC(c, out);
1343 break; 1478 break;
1344 } 1479 }
1345 quotef = 1; 1480 quotef = 1;
1346 if (arinest) { 1481 if (arinest) {
1347 if (ISDBLQUOTE()) { 1482 if (ISDBLQUOTE()) {
1348 TS_POP(); 1483 TS_POP();
1349 } else { 1484 } else {
1350 TS_PUSH(); 1485 TS_PUSH();
1351 syntax = DQSYNTAX; 1486 syntax = DQSYNTAX;
1352 SETDBLQUOTE(); 1487 SETDBLQUOTE();
1353 USTPUTC(CTLQUOTEMARK, out); 1488 USTPUTC(CTLQUOTEMARK, out);
1354 } 1489 }
1355 break; 1490 break;
1356 } 1491 }
1357 if (eofmark != NULL) 1492 if (magicq)
1358 break; 1493 break;
1359 if (ISDBLQUOTE()) { 1494 if (ISDBLQUOTE()) {
1360 TS_POP(); 1495 TS_POP();
1361 if (varnest != 0) 1496 if (varnest != 0)
1362 USTPUTC(CTLQUOTEEND, out); 1497 USTPUTC(CTLQUOTEEND, out);
1363 } else { 1498 } else {
1364 TS_PUSH(); 1499 TS_PUSH();
1365 syntax = DQSYNTAX; 1500 syntax = DQSYNTAX;
1366 SETDBLQUOTE(); 1501 SETDBLQUOTE();
1367 USTPUTC(CTLQUOTEMARK, out); 1502 USTPUTC(CTLQUOTEMARK, out);
1368 } 1503 }
1369 break; 1504 break;
1370 case CVAR: /* '$' */ 1505 case CVAR: /* '$' */
1371 PARSESUB(); /* parse substitution */ 1506 PARSESUB(); /* parse substitution */
1372 break; 1507 break;
1373 case CENDVAR: /* CLOSEBRACE */ 1508 case CENDVAR: /* CLOSEBRACE */
1374 if (varnest > 0 && !ISDBLQUOTE()) { 1509 if (varnest > 0 && !ISDBLQUOTE()) {
1375 TS_POP(); 1510 TS_POP();
1376 USTPUTC(CTLENDVAR, out); 1511 USTPUTC(CTLENDVAR, out);
1377 } else { 1512 } else {
1378 USTPUTC(c, out); 1513 USTPUTC(c, out);
1379 } 1514 }
1380 break; 1515 break;
1381 case CLP: /* '(' in arithmetic */ 1516 case CLP: /* '(' in arithmetic */
1382 parenlevel++; 1517 parenlevel++;
1383 USTPUTC(c, out); 1518 USTPUTC(c, out);
1384 break; 1519 break;
1385 case CRP: /* ')' in arithmetic */ 1520 case CRP: /* ')' in arithmetic */
1386 if (parenlevel > 0) { 1521 if (parenlevel > 0) {
1387 USTPUTC(c, out); 1522 USTPUTC(c, out);
1388 --parenlevel; 1523 --parenlevel;
1389 } else { 1524 } else {
1390 if (pgetc() == ')') { 1525 if (pgetc() == ')') {
1391 if (--arinest == 0) { 1526 if (--arinest == 0) {
1392 TS_POP(); 1527 TS_POP();
1393 USTPUTC(CTLENDARI, out); 1528 USTPUTC(CTLENDARI, out);
1394 } else 1529 } else
1395 USTPUTC(')', out); 1530 USTPUTC(')', out);
1396 } else { 1531 } else {
1397 /* 1532 /*
1398 * unbalanced parens 1533 * unbalanced parens
1399 * (don't 2nd guess - no error) 1534 * (don't 2nd guess - no error)
1400 */ 1535 */
1401 pungetc(); 1536 pungetc();
1402 USTPUTC(')', out); 1537 USTPUTC(')', out);
1403 } 1538 }
1404 } 1539 }
1405 break; 1540 break;
1406 case CBQUOTE: /* '`' */ 1541 case CBQUOTE: /* '`' */
1407 out = parsebackq(stack, out, &bqlist, 1); 1542 out = parsebackq(stack, out, &bqlist, 1);
1408 break; 1543 break;
1409 case CEOF: 1544 case CEOF:
1410 goto endword; /* exit outer loop */ 1545 goto endword; /* exit outer loop */
1411 default: 1546 default:
1412 if (varnest == 0 && !ISDBLQUOTE()) 1547 if (varnest == 0 && !ISDBLQUOTE())
1413 goto endword; /* exit outer loop */ 1548 goto endword; /* exit outer loop */
1414 USTPUTC(c, out); 1549 USTPUTC(c, out);
1415 } 1550 }
1416 c = pgetc_macro(); 1551 c = pgetc_macro();
1417 } 1552 }
1418 } 1553 }
1419endword: 1554endword:
1420 if (syntax == ARISYNTAX) { 1555 if (syntax == ARISYNTAX) {
1421 cleanup_state_stack(stack); 1556 cleanup_state_stack(stack);
1422 synerror("Missing '))'"); 1557 synerror("Missing '))'");
1423 } 1558 }
1424 if (syntax != BASESYNTAX && /* ! parsebackquote && */ eofmark == NULL) { 1559 if (syntax != BASESYNTAX && /* ! parsebackquote && */ !magicq) {
1425 cleanup_state_stack(stack); 1560 cleanup_state_stack(stack);
1426 synerror("Unterminated quoted string"); 1561 synerror("Unterminated quoted string");
1427 } 1562 }
1428 if (varnest != 0) { 1563 if (varnest != 0) {
1429 cleanup_state_stack(stack); 1564 cleanup_state_stack(stack);
1430 startlinno = plinno; 1565 startlinno = plinno;
1431 /* { */ 1566 /* { */
1432 synerror("Missing '}'"); 1567 synerror("Missing '}'");
1433 } 1568 }
1434 USTPUTC('\0', out); 1569 USTPUTC('\0', out);
1435 len = out - stackblock(); 1570 len = out - stackblock();
1436 out = stackblock(); 1571 out = stackblock();
1437 if (eofmark == NULL) { 1572 if (!magicq) {
1438 if ((c == '>' || c == '<') 1573 if ((c == '<' || c == '>')
1439 && quotef == 0 1574 && quotef == 0
1440 && (*out == '\0' || is_number(out))) { 1575 && (*out == '\0' || is_number(out))) {
1441 PARSEREDIR(); 1576 PARSEREDIR();
1442 cleanup_state_stack(stack); 1577 cleanup_state_stack(stack);
1443 return lasttoken = TREDIR; 1578 return lasttoken = TREDIR;
1444 } else { 1579 } else {
1445 pungetc(); 1580 pungetc();
1446 } 1581 }
1447 } 1582 }
1448 quoteflag = quotef; 1583 quoteflag = quotef;
1449 backquotelist = bqlist; 1584 backquotelist = bqlist;
1450 grabstackblock(len); 1585 grabstackblock(len);
1451 wordtext = out; 1586 wordtext = out;
1452 cleanup_state_stack(stack); 1587 cleanup_state_stack(stack);
1453 return lasttoken = TWORD; 1588 return lasttoken = TWORD;
1454/* end of readtoken routine */ 1589/* end of readtoken routine */
1455 1590
1456 1591
1457 
1458/* 
1459 * Check to see whether we are at the end of the here document. When this 
1460 * is called, c is set to the first character of the next input line. If 
1461 * we are at the end of the here document, this routine sets the c to PEOF. 
1462 */ 
1463 
1464checkend: { 
1465 if (eofmark) { 
1466 if (c == PEOF) 
1467 synerror(EOFhere); 
1468 if (striptabs) { 
1469 while (c == '\t') 
1470 c = pgetc(); 
1471 } 
1472 if (c == *eofmark) { 
1473 if (pfgets(line, sizeof line) != NULL) { 
1474 char *p, *q; 
1475 
1476 p = line; 
1477 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++) 
1478 continue; 
1479 if ((*p == '\0' || *p == '\n') && *q == '\0') { 
1480 c = PEOF; 
1481 plinno++; 
1482 needprompt = doprompt; 
1483 } else { 
1484 pushstring(line, strlen(line), NULL); 
1485 } 
1486 } else 
1487 synerror(EOFhere); 
1488 } 
1489 } 
1490 goto checkend_return; 
1491} 
1492 
1493 
1494/* 1592/*
1495 * Parse a redirection operator. The variable "out" points to a string 1593 * Parse a redirection operator. The variable "out" points to a string
1496 * specifying the fd to be redirected. The variable "c" contains the 1594 * specifying the fd to be redirected. The variable "c" contains the
1497 * first character of the redirection operator. 1595 * first character of the redirection operator.
1498 */ 1596 */
1499 1597
1500parseredir: { 1598parseredir: {
1501 char fd[64]; 1599 char fd[64];
1502 union node *np; 1600 union node *np;
1503 strlcpy(fd, out, sizeof(fd)); 1601 strlcpy(fd, out, sizeof(fd));
1504 1602
1505 np = stalloc(sizeof(struct nfile)); 1603 np = stalloc(sizeof(struct nfile));
1506 if (c == '>') { 1604 if (c == '>') {
1507 np->nfile.fd = 1; 1605 np->nfile.fd = 1;
1508 c = pgetc(); 1606 c = pgetc();
1509 if (c == '>') 1607 if (c == '>')
1510 np->type = NAPPEND; 1608 np->type = NAPPEND;
1511 else if (c == '|') 1609 else if (c == '|')
1512 np->type = NCLOBBER; 1610 np->type = NCLOBBER;
1513 else if (c == '&') 1611 else if (c == '&')
1514 np->type = NTOFD; 1612 np->type = NTOFD;
1515 else { 1613 else {
1516 np->type = NTO; 1614 np->type = NTO;
1517 pungetc(); 1615 pungetc();
1518 } 1616 }
1519 } else { /* c == '<' */ 1617 } else { /* c == '<' */
1520 np->nfile.fd = 0; 1618 np->nfile.fd = 0;
1521 switch (c = pgetc()) { 1619 switch (c = pgetc()) {
1522 case '<': 1620 case '<':
1523 if (sizeof (struct nfile) != sizeof (struct nhere)) { 1621 if (sizeof (struct nfile) != sizeof (struct nhere)) {
1524 np = stalloc(sizeof(struct nhere)); 1622 np = stalloc(sizeof(struct nhere));
1525 np->nfile.fd = 0; 1623 np->nfile.fd = 0;
1526 } 1624 }
1527 np->type = NHERE; 1625 np->type = NHERE;
1528 heredoc = stalloc(sizeof(struct heredoc)); 1626 heredoc = stalloc(sizeof(struct heredoc));
1529 heredoc->here = np; 1627 heredoc->here = np;
1530 if ((c = pgetc()) == '-') { 1628 if ((c = pgetc()) == '-') {
1531 heredoc->striptabs = 1; 1629 heredoc->striptabs = 1;
1532 } else { 1630 } else {
1533 heredoc->striptabs = 0; 1631 heredoc->striptabs = 0;
1534 pungetc(); 1632 pungetc();
1535 } 1633 }
1536 break; 1634 break;
1537 1635
1538 case '&': 1636 case '&':
1539 np->type = NFROMFD; 1637 np->type = NFROMFD;
1540 break; 1638 break;
1541 1639
1542 case '>': 1640 case '>':
1543 np->type = NFROMTO; 1641 np->type = NFROMTO;
1544 break; 1642 break;
1545 1643
1546 default: 1644 default:
1547 np->type = NFROM; 1645 np->type = NFROM;
1548 pungetc(); 1646 pungetc();
1549 break; 1647 break;
1550 } 1648 }
1551 } 1649 }
1552 if (*fd != '\0') 1650 if (*fd != '\0')
1553 np->nfile.fd = number(fd); 1651 np->nfile.fd = number(fd);
1554 redirnode = np; 1652 redirnode = np;
1555 goto parseredir_return; 1653 goto parseredir_return;
1556} 1654}
1557 1655
1558 1656
1559/* 1657/*
1560 * Parse a substitution. At this point, we have read the dollar sign 1658 * Parse a substitution. At this point, we have read the dollar sign
1561 * and nothing else. 1659 * and nothing else.
1562 */ 1660 */
1563 1661
1564parsesub: { 1662parsesub: {
1565 char buf[10]; 1663 char buf[10];
1566 int subtype; 1664 int subtype;
1567 int typeloc; 1665 int typeloc;
1568 int flags; 1666 int flags;
1569 char *p; 1667 char *p;
1570 static const char types[] = "}-+?="; 1668 static const char types[] = "}-+?=";
1571 int i; 1669 int i;
1572 int linno; 1670 int linno;
1573 1671
1574 c = pgetc(); 1672 c = pgetc();
1575 if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) { 1673 if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
1576 USTPUTC('$', out); 1674 USTPUTC('$', out);
1577 pungetc(); 1675 pungetc();
1578 } else if (c == '(') { /* $(command) or $((arith)) */ 1676 } else if (c == '(') { /* $(command) or $((arith)) */
1579 if (pgetc() == '(') { 1677 if (pgetc() == '(') {
1580 PARSEARITH(); 1678 PARSEARITH();
1581 } else { 1679 } else {
1582 pungetc(); 1680 pungetc();
1583 out = parsebackq(stack, out, &bqlist, 0); 1681 out = parsebackq(stack, out, &bqlist, 0);
1584 } 1682 }
1585 } else { 1683 } else {
1586 USTPUTC(CTLVAR, out); 1684 USTPUTC(CTLVAR, out);
1587 typeloc = out - stackblock(); 1685 typeloc = out - stackblock();
1588 USTPUTC(VSNORMAL, out); 1686 USTPUTC(VSNORMAL, out);
1589 subtype = VSNORMAL; 1687 subtype = VSNORMAL;
1590 flags = 0; 1688 flags = 0;
1591 if (c == OPENBRACE) { 1689 if (c == OPENBRACE) {
1592 c = pgetc(); 1690 c = pgetc();
1593 if (c == '#') { 1691 if (c == '#') {
1594 if ((c = pgetc()) == CLOSEBRACE) 1692 if ((c = pgetc()) == CLOSEBRACE)
1595 c = '#'; 1693 c = '#';
1596 else 1694 else
1597 subtype = VSLENGTH; 1695 subtype = VSLENGTH;
1598 } 1696 }
1599 else 1697 else
1600 subtype = 0; 1698 subtype = 0;
1601 } 1699 }
1602 if (is_name(c)) { 1700 if (is_name(c)) {
1603 p = out; 1701 p = out;
1604 do { 1702 do {
1605 STPUTC(c, out); 1703 STPUTC(c, out);
1606 c = pgetc(); 1704 c = pgetc();
1607 } while (is_in_name(c)); 1705 } while (is_in_name(c));
1608 if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) { 1706 if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) {
1609 /* Replace the variable name with the 1707 /* Replace the variable name with the
1610 * current line number. */ 1708 * current line number. */
1611 linno = plinno; 1709 linno = plinno;
1612 if (funclinno != 0) 1710 if (funclinno != 0)
1613 linno -= funclinno - 1; 1711 linno -= funclinno - 1;
1614 snprintf(buf, sizeof(buf), "%d", linno); 1712 snprintf(buf, sizeof(buf), "%d", linno);
1615 STADJUST(-6, out); 1713 STADJUST(-6, out);
1616 for (i = 0; buf[i] != '\0'; i++) 1714 for (i = 0; buf[i] != '\0'; i++)
1617 STPUTC(buf[i], out); 1715 STPUTC(buf[i], out);
1618 flags |= VSLINENO; 1716 flags |= VSLINENO;
1619 } 1717 }
1620 } else if (is_digit(c)) { 1718 } else if (is_digit(c)) {
1621 do { 1719 do {
1622 USTPUTC(c, out); 1720 USTPUTC(c, out);
1623 c = pgetc(); 1721 c = pgetc();
1624 } while (is_digit(c)); 1722 } while (is_digit(c));
1625 } 1723 }
1626 else if (is_special(c)) { 1724 else if (is_special(c)) {
1627 USTPUTC(c, out); 1725 USTPUTC(c, out);
1628 c = pgetc(); 1726 c = pgetc();
1629 } 1727 }
1630 else { 1728 else {
1631badsub: 1729badsub:
1632 cleanup_state_stack(stack); 1730 cleanup_state_stack(stack);
1633 synerror("Bad substitution"); 1731 synerror("Bad substitution");
1634 } 1732 }
1635 1733
1636 STPUTC('=', out); 1734 STPUTC('=', out);
1637 if (subtype == 0) { 1735 if (subtype == 0) {
1638 switch (c) { 1736 switch (c) {
1639 case ':': 1737 case ':':
1640 flags |= VSNUL; 1738 flags |= VSNUL;
1641 c = pgetc(); 1739 c = pgetc();
1642 /*FALLTHROUGH*/ 1740 /*FALLTHROUGH*/
1643 default: 1741 default:
1644 p = strchr(types, c); 1742 p = strchr(types, c);
1645 if (p == NULL) 1743 if (p == NULL)
1646 goto badsub; 1744 goto badsub;
1647 subtype = p - types + VSNORMAL; 1745 subtype = p - types + VSNORMAL;
1648 break; 1746 break;
1649 case '%': 1747 case '%':
1650 case '#': 1748 case '#':
1651 { 1749 {
1652 int cc = c; 1750 int cc = c;
1653 subtype = c == '#' ? VSTRIMLEFT : 1751 subtype = c == '#' ? VSTRIMLEFT :
1654 VSTRIMRIGHT; 1752 VSTRIMRIGHT;
1655 c = pgetc(); 1753 c = pgetc();
1656 if (c == cc) 1754 if (c == cc)
1657 subtype++; 1755 subtype++;
1658 else 1756 else
1659 pungetc(); 1757 pungetc();
1660 break; 1758 break;
1661 } 1759 }
1662 } 1760 }
1663 } else { 1761 } else {
1664 pungetc(); 1762 pungetc();
1665 } 1763 }
1666 if (ISDBLQUOTE() || arinest) 1764 if (ISDBLQUOTE() || arinest)
1667 flags |= VSQUOTE; 1765 flags |= VSQUOTE;
1668 if (subtype >= VSTRIMLEFT && subtype <= VSTRIMRIGHTMAX) 1766 if (subtype >= VSTRIMLEFT && subtype <= VSTRIMRIGHTMAX)
1669 flags |= VSPATQ; 1767 flags |= VSPATQ;
1670 *(stackblock() + typeloc) = subtype | flags; 1768 *(stackblock() + typeloc) = subtype | flags;
1671 if (subtype != VSNORMAL) { 1769 if (subtype != VSNORMAL) {
1672 TS_PUSH(); 1770 TS_PUSH();
1673 varnest++; 1771 varnest++;
1674 arinest = 0; 1772 arinest = 0;
1675 if (subtype > VSASSIGN) { /* # ## % %% */ 1773 if (subtype > VSASSIGN) { /* # ## % %% */
1676 syntax = BASESYNTAX; 1774 syntax = BASESYNTAX;
1677 CLRDBLQUOTE(); 1775 CLRDBLQUOTE();
1678 } 1776 }
1679 } 1777 }
1680 } 1778 }
1681 goto parsesub_return; 1779 goto parsesub_return;
1682} 1780}
1683 1781
1684 1782
1685/* 1783/*
1686 * Parse an arithmetic expansion (indicate start of one and set state) 1784 * Parse an arithmetic expansion (indicate start of one and set state)
1687 */ 1785 */
1688parsearith: { 1786parsearith: {
1689 1787
1690 if (syntax == ARISYNTAX) { 1788 if (syntax == ARISYNTAX) {
1691 /* 1789 /*
1692 * we collapse embedded arithmetic expansion to 1790 * we collapse embedded arithmetic expansion to
1693 * parentheses, which should be equivalent 1791 * parentheses, which should be equivalent
1694 */ 1792 */
1695 USTPUTC('(', out); 1793 USTPUTC('(', out);
1696 USTPUTC('(', out); 1794 USTPUTC('(', out);
1697 /* 1795 /*
1698 * Need 2 of them because there will (should be) 1796 * Need 2 of them because there will (should be)
1699 * two closing ))'s to follow later. 1797 * two closing ))'s to follow later.
1700 */ 1798 */
1701 parenlevel += 2; 1799 parenlevel += 2;
1702 } else { 1800 } else {
1703 TS_PUSH(); 1801 TS_PUSH();
1704 syntax = ARISYNTAX; 1802 syntax = ARISYNTAX;
1705 ++arinest; 1803 ++arinest;
1706 varnest = 0; 1804 varnest = 0;
1707 1805
1708 USTPUTC(CTLARI, out); 1806 USTPUTC(CTLARI, out);
1709 if (ISDBLQUOTE()) 1807 if (ISDBLQUOTE())
1710 USTPUTC('"',out); 1808 USTPUTC('"',out);
1711 else 1809 else
1712 USTPUTC(' ',out); 1810 USTPUTC(' ',out);
1713 } 1811 }
1714 goto parsearith_return; 1812 goto parsearith_return;
1715} 1813}
1716 1814
1717} /* end of readtoken */ 1815} /* end of readtoken */
1718 1816
1719 1817
1720 1818
1721#ifdef mkinit 1819#ifdef mkinit
1722RESET { 1820RESET {
1723 tokpushback = 0; 1821 tokpushback = 0;
1724 checkkwd = 0; 1822 checkkwd = 0;
1725} 1823}
1726#endif 1824#endif
1727 1825
1728/* 1826/*
1729 * Returns true if the text contains nothing to expand (no dollar signs 1827 * Returns true if the text contains nothing to expand (no dollar signs
1730 * or backquotes). 1828 * or backquotes).
1731 */ 1829 */
1732 1830
1733STATIC int 1831STATIC int
1734noexpand(char *text) 1832noexpand(char *text)
1735{ 1833{
1736 char *p; 1834 char *p;
1737 char c; 1835 char c;
1738 1836
1739 p = text; 1837 p = text;
1740 while ((c = *p++) != '\0') { 1838 while ((c = *p++) != '\0') {
1741 if (c == CTLQUOTEMARK) 1839 if (c == CTLQUOTEMARK)
1742 continue; 1840 continue;
1743 if (c == CTLESC) 1841 if (c == CTLESC)
1744 p++; 1842 p++;
1745 else if (BASESYNTAX[(int)c] == CCTL) 1843 else if (BASESYNTAX[(int)c] == CCTL)
1746 return 0; 1844 return 0;
1747 } 1845 }
1748 return 1; 1846 return 1;
1749} 1847}
1750 1848
1751 1849
1752/* 1850/*
1753 * Return true if the argument is a legal variable name (a letter or 1851 * Return true if the argument is a legal variable name (a letter or
1754 * underscore followed by zero or more letters, underscores, and digits). 1852 * underscore followed by zero or more letters, underscores, and digits).
1755 */ 1853 */
1756 1854
1757int 1855int
1758goodname(char *name) 1856goodname(char *name)
1759{ 1857{
1760 char *p; 1858 char *p;
1761 1859
1762 p = name; 1860 p = name;
1763 if (! is_name(*p)) 1861 if (! is_name(*p))
1764 return 0; 1862 return 0;
1765 while (*++p) { 1863 while (*++p) {
1766 if (! is_in_name(*p)) 1864 if (! is_in_name(*p))
1767 return 0; 1865 return 0;
1768 } 1866 }
1769 return 1; 1867 return 1;
1770} 1868}
1771 1869
1772 1870
1773/* 1871/*
1774 * Called when an unexpected token is read during the parse. The argument 1872 * Called when an unexpected token is read during the parse. The argument
1775 * is the token that is expected, or -1 if more than one type of token can 1873 * is the token that is expected, or -1 if more than one type of token can
1776 * occur at this point. 1874 * occur at this point.
1777 */ 1875 */
1778 1876
1779STATIC void 1877STATIC void
1780synexpect(int token, const char *text) 1878synexpect(int token, const char *text)
1781{ 1879{
1782 char msg[64]; 1880 char msg[64];
1783 char *p; 1881 char *p;
1784 1882
1785 if (lasttoken == TWORD) { 1883 if (lasttoken == TWORD) {
1786 size_t len = strlen(wordtext); 1884 size_t len = strlen(wordtext);
1787 1885
1788 if (len <= 13) 1886 if (len <= 13)
1789 fmtstr(msg, 34, "Word \"%.13s\" unexpected", wordtext); 1887 fmtstr(msg, 34, "Word \"%.13s\" unexpected", wordtext);
1790 else 1888 else
1791 fmtstr(msg, 34, 1889 fmtstr(msg, 34,
1792 "Word \"%.10s...\" unexpected", wordtext); 1890 "Word \"%.10s...\" unexpected", wordtext);
1793 } else 1891 } else
1794 fmtstr(msg, 34, "%s unexpected", tokname[lasttoken]); 1892 fmtstr(msg, 34, "%s unexpected", tokname[lasttoken]);
1795 1893
1796 p = strchr(msg, '\0'); 1894 p = strchr(msg, '\0');
1797 if (text) 1895 if (text)
1798 fmtstr(p, 30, " (expecting \"%.10s\")", text); 1896 fmtstr(p, 30, " (expecting \"%.10s\")", text);
1799 else if (token >= 0) 1897 else if (token >= 0)
1800 fmtstr(p, 30, " (expecting %s)", tokname[token]); 1898 fmtstr(p, 30, " (expecting %s)", tokname[token]);
1801 1899
1802 synerror(msg); 1900 synerror(msg);
1803 /* NOTREACHED */ 1901 /* NOTREACHED */
1804} 1902}
1805 1903
1806 1904
1807STATIC void 1905STATIC void
1808synerror(const char *msg) 1906synerror(const char *msg)
1809{ 1907{
1810 error("%d: Syntax error: %s\n", startlinno, msg); 1908 error("%d: Syntax error: %s\n", startlinno, msg);
1811 /* NOTREACHED */ 1909 /* NOTREACHED */
1812} 1910}
1813 1911
1814STATIC void 1912STATIC void
1815setprompt(int which) 1913setprompt(int which)
1816{ 1914{
1817 whichprompt = which; 1915 whichprompt = which;
1818 1916
1819#ifndef SMALL 1917#ifndef SMALL
1820 if (!el) 1918 if (!el)
1821#endif 1919#endif
1822 out2str(getprompt(NULL)); 1920 out2str(getprompt(NULL));
1823} 1921}
1824 1922
1825/* 1923/*
1826 * called by editline -- any expansions to the prompt 1924 * called by editline -- any expansions to the prompt
1827 * should be added here. 1925 * should be added here.
1828 */ 1926 */
1829const char * 1927const char *
1830getprompt(void *unused) 1928getprompt(void *unused)
1831{ 1929{
1832 switch (whichprompt) { 1930 switch (whichprompt) {
1833 case 0: 1931 case 0:
1834 return ""; 1932 return "";
1835 case 1: 1933 case 1:
1836 return ps1val(); 1934 return ps1val();
1837 case 2: 1935 case 2:
1838 return ps2val(); 1936 return ps2val();
1839 default: 1937 default:
1840 return "<internal prompt error>"; 1938 return "<internal prompt error>";
1841 } 1939 }
1842} 1940}

cvs diff -r1.19 -r1.20 src/bin/sh/parser.h (switch to unified diff)

--- src/bin/sh/parser.h 2016/02/22 20:02:00 1.19
+++ src/bin/sh/parser.h 2016/03/27 14:39:33 1.20
@@ -1,85 +1,86 @@ @@ -1,85 +1,86 @@
1/* $NetBSD: parser.h,v 1.19 2016/02/22 20:02:00 christos Exp $ */ 1/* $NetBSD: parser.h,v 1.20 2016/03/27 14:39:33 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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 * @(#)parser.h 8.3 (Berkeley) 5/4/95 34 * @(#)parser.h 8.3 (Berkeley) 5/4/95
35 */ 35 */
36 36
37/* control characters in argument strings */ 37/* control characters in argument strings */
38#define CTL_FIRST '\201' /* first 'special' character */ 38#define CTL_FIRST '\201' /* first 'special' character */
39#define CTLESC '\201' /* escape next character */ 39#define CTLESC '\201' /* escape next character */
40#define CTLVAR '\202' /* variable defn */ 40#define CTLVAR '\202' /* variable defn */
41#define CTLENDVAR '\203' 41#define CTLENDVAR '\203'
42#define CTLBACKQ '\204' 42#define CTLBACKQ '\204'
43#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ 43#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
44/* CTLBACKQ | CTLQUOTE == '\205' */ 44/* CTLBACKQ | CTLQUOTE == '\205' */
45#define CTLARI '\206' /* arithmetic expression */ 45#define CTLARI '\206' /* arithmetic expression */
46#define CTLENDARI '\207' 46#define CTLENDARI '\207'
47#define CTLQUOTEMARK '\210' 47#define CTLQUOTEMARK '\210'
48#define CTLQUOTEEND '\211' /* only inside ${...} */ 48#define CTLQUOTEEND '\211' /* only inside ${...} */
49#define CTL_LAST '\211' /* last 'special' character */ 49#define CTL_LAST '\211' /* last 'special' character */
50 50
51/* variable substitution byte (follows CTLVAR) */ 51/* variable substitution byte (follows CTLVAR) */
52#define VSTYPE 0x0f /* type of variable substitution */ 52#define VSTYPE 0x0f /* type of variable substitution */
53#define VSNUL 0x10 /* colon--treat the empty string as unset */ 53#define VSNUL 0x10 /* colon--treat the empty string as unset */
54#define VSLINENO 0x20 /* expansion of $LINENO, the line number 54#define VSLINENO 0x20 /* expansion of $LINENO, the line number
55 follows immediately */ 55 follows immediately */
56#define VSPATQ 0x40 /* ensure correct pattern quoting in ${x#pat} */ 56#define VSPATQ 0x40 /* ensure correct pattern quoting in ${x#pat} */
57#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ 57#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
58 58
59/* values of VSTYPE field */ 59/* values of VSTYPE field */
60#define VSNORMAL 0x1 /* normal variable: $var or ${var} */ 60#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
61#define VSMINUS 0x2 /* ${var-text} */ 61#define VSMINUS 0x2 /* ${var-text} */
62#define VSPLUS 0x3 /* ${var+text} */ 62#define VSPLUS 0x3 /* ${var+text} */
63#define VSQUESTION 0x4 /* ${var?message} */ 63#define VSQUESTION 0x4 /* ${var?message} */
64#define VSASSIGN 0x5 /* ${var=text} */ 64#define VSASSIGN 0x5 /* ${var=text} */
65#define VSTRIMLEFT 0x6 /* ${var#pattern} */ 65#define VSTRIMLEFT 0x6 /* ${var#pattern} */
66#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */ 66#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
67#define VSTRIMRIGHT 0x8 /* ${var%pattern} */ 67#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
68#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ 68#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
69#define VSLENGTH 0xa /* ${#var} */ 69#define VSLENGTH 0xa /* ${#var} */
70 70
71 71
72/* 72/*
73 * NEOF is returned by parsecmd when it encounters an end of file. It 73 * NEOF is returned by parsecmd when it encounters an end of file. It
74 * must be distinct from NULL, so we use the address of a variable that 74 * must be distinct from NULL, so we use the address of a variable that
75 * happens to be handy. 75 * happens to be handy.
76 */ 76 */
77extern int tokpushback; 77extern int tokpushback;
78#define NEOF ((union node *)&tokpushback) 78#define NEOF ((union node *)&tokpushback)
79extern int whichprompt; /* 1 == PS1, 2 == PS2 */ 79extern int whichprompt; /* 1 == PS1, 2 == PS2 */
80 80
81 81
82union node *parsecmd(int); 82union node *parsecmd(int);
83void fixredir(union node *, const char *, int); 83void fixredir(union node *, const char *, int);
 84void parse_heredoc(union node *);
84int goodname(char *); 85int goodname(char *);
85const char *getprompt(void *); 86const char *getprompt(void *);