xref: /aosp_15_r20/external/mksh/src/lex.c (revision 7c356e860f31eadd15fd599fcfdb9fd21f16a9d4)
1*7c356e86SAndroid Build Coastguard Worker /*	$OpenBSD: lex.c,v 1.51 2015/09/10 22:48:58 nicm Exp $	*/
2*7c356e86SAndroid Build Coastguard Worker 
3*7c356e86SAndroid Build Coastguard Worker /*-
4*7c356e86SAndroid Build Coastguard Worker  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5*7c356e86SAndroid Build Coastguard Worker  *		 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
6*7c356e86SAndroid Build Coastguard Worker  *	mirabilos <[email protected]>
7*7c356e86SAndroid Build Coastguard Worker  *
8*7c356e86SAndroid Build Coastguard Worker  * Provided that these terms and disclaimer and all copyright notices
9*7c356e86SAndroid Build Coastguard Worker  * are retained or reproduced in an accompanying document, permission
10*7c356e86SAndroid Build Coastguard Worker  * is granted to deal in this work without restriction, including un-
11*7c356e86SAndroid Build Coastguard Worker  * limited rights to use, publicly perform, distribute, sell, modify,
12*7c356e86SAndroid Build Coastguard Worker  * merge, give away, or sublicence.
13*7c356e86SAndroid Build Coastguard Worker  *
14*7c356e86SAndroid Build Coastguard Worker  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15*7c356e86SAndroid Build Coastguard Worker  * the utmost extent permitted by applicable law, neither express nor
16*7c356e86SAndroid Build Coastguard Worker  * implied; without malicious intent or gross negligence. In no event
17*7c356e86SAndroid Build Coastguard Worker  * may a licensor, author or contributor be held liable for indirect,
18*7c356e86SAndroid Build Coastguard Worker  * direct, other damage, loss, or other issues arising in any way out
19*7c356e86SAndroid Build Coastguard Worker  * of dealing in the work, even if advised of the possibility of such
20*7c356e86SAndroid Build Coastguard Worker  * damage or existence of a defect, except proven that it results out
21*7c356e86SAndroid Build Coastguard Worker  * of said person's immediate fault when using the work as intended.
22*7c356e86SAndroid Build Coastguard Worker  */
23*7c356e86SAndroid Build Coastguard Worker 
24*7c356e86SAndroid Build Coastguard Worker #include "sh.h"
25*7c356e86SAndroid Build Coastguard Worker 
26*7c356e86SAndroid Build Coastguard Worker __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.251 2020/03/10 23:48:40 tg Exp $");
27*7c356e86SAndroid Build Coastguard Worker 
28*7c356e86SAndroid Build Coastguard Worker /*
29*7c356e86SAndroid Build Coastguard Worker  * states while lexing word
30*7c356e86SAndroid Build Coastguard Worker  */
31*7c356e86SAndroid Build Coastguard Worker #define SBASE		0	/* outside any lexical constructs */
32*7c356e86SAndroid Build Coastguard Worker #define SWORD		1	/* implicit quoting for substitute() */
33*7c356e86SAndroid Build Coastguard Worker #define SLETPAREN	2	/* inside (( )), implicit quoting */
34*7c356e86SAndroid Build Coastguard Worker #define SSQUOTE		3	/* inside '' */
35*7c356e86SAndroid Build Coastguard Worker #define SDQUOTE		4	/* inside "" */
36*7c356e86SAndroid Build Coastguard Worker #define SEQUOTE		5	/* inside $'' */
37*7c356e86SAndroid Build Coastguard Worker #define SBRACE		6	/* inside ${} */
38*7c356e86SAndroid Build Coastguard Worker #define SQBRACE		7	/* inside "${}" */
39*7c356e86SAndroid Build Coastguard Worker #define SBQUOTE		8	/* inside `` */
40*7c356e86SAndroid Build Coastguard Worker #define SASPAREN	9	/* inside $(( )) */
41*7c356e86SAndroid Build Coastguard Worker #define SHEREDELIM	10	/* parsing << or <<- delimiter */
42*7c356e86SAndroid Build Coastguard Worker #define SHEREDQUOTE	11	/* parsing " in << or <<- delimiter */
43*7c356e86SAndroid Build Coastguard Worker #define SPATTERN	12	/* parsing *(...|...) pattern (*+?@!) */
44*7c356e86SAndroid Build Coastguard Worker #define SADELIM		13	/* like SBASE, looking for delimiter */
45*7c356e86SAndroid Build Coastguard Worker #define STBRACEKORN	14	/* parsing ${...[#%]...} !FSH */
46*7c356e86SAndroid Build Coastguard Worker #define STBRACEBOURNE	15	/* parsing ${...[#%]...} FSH */
47*7c356e86SAndroid Build Coastguard Worker #define SINVALID	255	/* invalid state */
48*7c356e86SAndroid Build Coastguard Worker 
49*7c356e86SAndroid Build Coastguard Worker struct sretrace_info {
50*7c356e86SAndroid Build Coastguard Worker 	struct sretrace_info *next;
51*7c356e86SAndroid Build Coastguard Worker 	XString xs;
52*7c356e86SAndroid Build Coastguard Worker 	char *xp;
53*7c356e86SAndroid Build Coastguard Worker };
54*7c356e86SAndroid Build Coastguard Worker 
55*7c356e86SAndroid Build Coastguard Worker /*
56*7c356e86SAndroid Build Coastguard Worker  * Structure to keep track of the lexing state and the various pieces of info
57*7c356e86SAndroid Build Coastguard Worker  * needed for each particular state.
58*7c356e86SAndroid Build Coastguard Worker  */
59*7c356e86SAndroid Build Coastguard Worker typedef struct lex_state {
60*7c356e86SAndroid Build Coastguard Worker 	union {
61*7c356e86SAndroid Build Coastguard Worker 		/* point to the next state block */
62*7c356e86SAndroid Build Coastguard Worker 		struct lex_state *base;
63*7c356e86SAndroid Build Coastguard Worker 		/* marks start of state output in output string */
64*7c356e86SAndroid Build Coastguard Worker 		size_t start;
65*7c356e86SAndroid Build Coastguard Worker 		/* SBQUOTE: true if in double quotes: "`...`" */
66*7c356e86SAndroid Build Coastguard Worker 		/* SEQUOTE: got NUL, ignore rest of string */
67*7c356e86SAndroid Build Coastguard Worker 		bool abool;
68*7c356e86SAndroid Build Coastguard Worker 		/* SADELIM information */
69*7c356e86SAndroid Build Coastguard Worker 		struct {
70*7c356e86SAndroid Build Coastguard Worker 			/* character to search for */
71*7c356e86SAndroid Build Coastguard Worker 			unsigned char delimiter;
72*7c356e86SAndroid Build Coastguard Worker 			/* max. number of delimiters */
73*7c356e86SAndroid Build Coastguard Worker 			unsigned char num;
74*7c356e86SAndroid Build Coastguard Worker 		} adelim;
75*7c356e86SAndroid Build Coastguard Worker 	} u;
76*7c356e86SAndroid Build Coastguard Worker 	/* count open parentheses */
77*7c356e86SAndroid Build Coastguard Worker 	short nparen;
78*7c356e86SAndroid Build Coastguard Worker 	/* type of this state */
79*7c356e86SAndroid Build Coastguard Worker 	uint8_t type;
80*7c356e86SAndroid Build Coastguard Worker 	/* extra flags */
81*7c356e86SAndroid Build Coastguard Worker 	uint8_t ls_flags;
82*7c356e86SAndroid Build Coastguard Worker } Lex_state;
83*7c356e86SAndroid Build Coastguard Worker #define ls_base		u.base
84*7c356e86SAndroid Build Coastguard Worker #define ls_start	u.start
85*7c356e86SAndroid Build Coastguard Worker #define ls_bool		u.abool
86*7c356e86SAndroid Build Coastguard Worker #define ls_adelim	u.adelim
87*7c356e86SAndroid Build Coastguard Worker 
88*7c356e86SAndroid Build Coastguard Worker /* ls_flags */
89*7c356e86SAndroid Build Coastguard Worker #define LS_HEREDOC	BIT(0)
90*7c356e86SAndroid Build Coastguard Worker 
91*7c356e86SAndroid Build Coastguard Worker typedef struct {
92*7c356e86SAndroid Build Coastguard Worker 	Lex_state *base;
93*7c356e86SAndroid Build Coastguard Worker 	Lex_state *end;
94*7c356e86SAndroid Build Coastguard Worker } State_info;
95*7c356e86SAndroid Build Coastguard Worker 
96*7c356e86SAndroid Build Coastguard Worker static void readhere(struct ioword *);
97*7c356e86SAndroid Build Coastguard Worker static void ungetsc(int);
98*7c356e86SAndroid Build Coastguard Worker static void ungetsc_i(int);
99*7c356e86SAndroid Build Coastguard Worker static int getsc_uu(void);
100*7c356e86SAndroid Build Coastguard Worker static void getsc_line(Source *);
101*7c356e86SAndroid Build Coastguard Worker static int getsc_bn(void);
102*7c356e86SAndroid Build Coastguard Worker static int getsc_i(void);
103*7c356e86SAndroid Build Coastguard Worker static char *get_brace_var(XString *, char *);
104*7c356e86SAndroid Build Coastguard Worker static bool arraysub(char **);
105*7c356e86SAndroid Build Coastguard Worker static void gethere(void);
106*7c356e86SAndroid Build Coastguard Worker static Lex_state *push_state_i(State_info *, Lex_state *);
107*7c356e86SAndroid Build Coastguard Worker static Lex_state *pop_state_i(State_info *, Lex_state *);
108*7c356e86SAndroid Build Coastguard Worker 
109*7c356e86SAndroid Build Coastguard Worker static int backslash_skip;
110*7c356e86SAndroid Build Coastguard Worker static int ignore_backslash_newline;
111*7c356e86SAndroid Build Coastguard Worker 
112*7c356e86SAndroid Build Coastguard Worker /* optimised getsc_bn() */
113*7c356e86SAndroid Build Coastguard Worker #define o_getsc()	(*source->str != '\0' && *source->str != '\\' && \
114*7c356e86SAndroid Build Coastguard Worker 			    !backslash_skip ? *source->str++ : getsc_bn())
115*7c356e86SAndroid Build Coastguard Worker /* optimised getsc_uu() */
116*7c356e86SAndroid Build Coastguard Worker #define	o_getsc_u()	((*source->str != '\0') ? *source->str++ : getsc_uu())
117*7c356e86SAndroid Build Coastguard Worker 
118*7c356e86SAndroid Build Coastguard Worker /* retrace helper */
119*7c356e86SAndroid Build Coastguard Worker #define o_getsc_r(carg)					\
120*7c356e86SAndroid Build Coastguard Worker 	int cev = (carg);				\
121*7c356e86SAndroid Build Coastguard Worker 	struct sretrace_info *rp = retrace_info;	\
122*7c356e86SAndroid Build Coastguard Worker 							\
123*7c356e86SAndroid Build Coastguard Worker 	while (rp) {					\
124*7c356e86SAndroid Build Coastguard Worker 		Xcheck(rp->xs, rp->xp);			\
125*7c356e86SAndroid Build Coastguard Worker 		*rp->xp++ = cev;			\
126*7c356e86SAndroid Build Coastguard Worker 		rp = rp->next;				\
127*7c356e86SAndroid Build Coastguard Worker 	}						\
128*7c356e86SAndroid Build Coastguard Worker 							\
129*7c356e86SAndroid Build Coastguard Worker 	return (cev);
130*7c356e86SAndroid Build Coastguard Worker 
131*7c356e86SAndroid Build Coastguard Worker /* callback */
132*7c356e86SAndroid Build Coastguard Worker static int
getsc_i(void)133*7c356e86SAndroid Build Coastguard Worker getsc_i(void)
134*7c356e86SAndroid Build Coastguard Worker {
135*7c356e86SAndroid Build Coastguard Worker 	o_getsc_r((unsigned int)(unsigned char)o_getsc());
136*7c356e86SAndroid Build Coastguard Worker }
137*7c356e86SAndroid Build Coastguard Worker 
138*7c356e86SAndroid Build Coastguard Worker #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
139*7c356e86SAndroid Build Coastguard Worker #define getsc()		getsc_i()
140*7c356e86SAndroid Build Coastguard Worker #else
141*7c356e86SAndroid Build Coastguard Worker static int getsc_r(int);
142*7c356e86SAndroid Build Coastguard Worker 
143*7c356e86SAndroid Build Coastguard Worker static int
getsc_r(int c)144*7c356e86SAndroid Build Coastguard Worker getsc_r(int c)
145*7c356e86SAndroid Build Coastguard Worker {
146*7c356e86SAndroid Build Coastguard Worker 	o_getsc_r(c);
147*7c356e86SAndroid Build Coastguard Worker }
148*7c356e86SAndroid Build Coastguard Worker 
149*7c356e86SAndroid Build Coastguard Worker #define getsc()		getsc_r((unsigned int)(unsigned char)o_getsc())
150*7c356e86SAndroid Build Coastguard Worker #endif
151*7c356e86SAndroid Build Coastguard Worker 
152*7c356e86SAndroid Build Coastguard Worker #define STATE_BSIZE	8
153*7c356e86SAndroid Build Coastguard Worker 
154*7c356e86SAndroid Build Coastguard Worker #define PUSH_STATE(s)	do {					\
155*7c356e86SAndroid Build Coastguard Worker 	uint8_t state_flags = statep->ls_flags;			\
156*7c356e86SAndroid Build Coastguard Worker 	if (++statep == state_info.end)				\
157*7c356e86SAndroid Build Coastguard Worker 		statep = push_state_i(&state_info, statep);	\
158*7c356e86SAndroid Build Coastguard Worker 	state = statep->type = (s);				\
159*7c356e86SAndroid Build Coastguard Worker 	statep->ls_flags = state_flags;				\
160*7c356e86SAndroid Build Coastguard Worker } while (/* CONSTCOND */ 0)
161*7c356e86SAndroid Build Coastguard Worker 
162*7c356e86SAndroid Build Coastguard Worker #define POP_STATE()	do {					\
163*7c356e86SAndroid Build Coastguard Worker 	if (--statep == state_info.base)			\
164*7c356e86SAndroid Build Coastguard Worker 		statep = pop_state_i(&state_info, statep);	\
165*7c356e86SAndroid Build Coastguard Worker 	state = statep->type;					\
166*7c356e86SAndroid Build Coastguard Worker } while (/* CONSTCOND */ 0)
167*7c356e86SAndroid Build Coastguard Worker 
168*7c356e86SAndroid Build Coastguard Worker #define PUSH_SRETRACE(s) do {					\
169*7c356e86SAndroid Build Coastguard Worker 	struct sretrace_info *ri;				\
170*7c356e86SAndroid Build Coastguard Worker 								\
171*7c356e86SAndroid Build Coastguard Worker 	PUSH_STATE(s);						\
172*7c356e86SAndroid Build Coastguard Worker 	statep->ls_start = Xsavepos(ws, wp);			\
173*7c356e86SAndroid Build Coastguard Worker 	ri = alloc(sizeof(struct sretrace_info), ATEMP);	\
174*7c356e86SAndroid Build Coastguard Worker 	Xinit(ri->xs, ri->xp, 64, ATEMP);			\
175*7c356e86SAndroid Build Coastguard Worker 	ri->next = retrace_info;				\
176*7c356e86SAndroid Build Coastguard Worker 	retrace_info = ri;					\
177*7c356e86SAndroid Build Coastguard Worker } while (/* CONSTCOND */ 0)
178*7c356e86SAndroid Build Coastguard Worker 
179*7c356e86SAndroid Build Coastguard Worker #define POP_SRETRACE()	do {					\
180*7c356e86SAndroid Build Coastguard Worker 	wp = Xrestpos(ws, wp, statep->ls_start);		\
181*7c356e86SAndroid Build Coastguard Worker 	*retrace_info->xp = '\0';				\
182*7c356e86SAndroid Build Coastguard Worker 	sp = Xstring(retrace_info->xs, retrace_info->xp);	\
183*7c356e86SAndroid Build Coastguard Worker 	dp = (void *)retrace_info;				\
184*7c356e86SAndroid Build Coastguard Worker 	retrace_info = retrace_info->next;			\
185*7c356e86SAndroid Build Coastguard Worker 	afree(dp, ATEMP);					\
186*7c356e86SAndroid Build Coastguard Worker 	POP_STATE();						\
187*7c356e86SAndroid Build Coastguard Worker } while (/* CONSTCOND */ 0)
188*7c356e86SAndroid Build Coastguard Worker 
189*7c356e86SAndroid Build Coastguard Worker /**
190*7c356e86SAndroid Build Coastguard Worker  * Lexical analyser
191*7c356e86SAndroid Build Coastguard Worker  *
192*7c356e86SAndroid Build Coastguard Worker  * tokens are not regular expressions, they are LL(1).
193*7c356e86SAndroid Build Coastguard Worker  * for example, "${var:-${PWD}}", and "$(size $(whence ksh))".
194*7c356e86SAndroid Build Coastguard Worker  * hence the state stack. Note "$(...)" are now parsed recursively.
195*7c356e86SAndroid Build Coastguard Worker  */
196*7c356e86SAndroid Build Coastguard Worker 
197*7c356e86SAndroid Build Coastguard Worker int
yylex(int cf)198*7c356e86SAndroid Build Coastguard Worker yylex(int cf)
199*7c356e86SAndroid Build Coastguard Worker {
200*7c356e86SAndroid Build Coastguard Worker 	Lex_state states[STATE_BSIZE], *statep, *s2, *base;
201*7c356e86SAndroid Build Coastguard Worker 	State_info state_info;
202*7c356e86SAndroid Build Coastguard Worker 	int c, c2, state;
203*7c356e86SAndroid Build Coastguard Worker 	size_t cz;
204*7c356e86SAndroid Build Coastguard Worker 	XString ws;		/* expandable output word */
205*7c356e86SAndroid Build Coastguard Worker 	char *wp;		/* output word pointer */
206*7c356e86SAndroid Build Coastguard Worker 	char *sp, *dp;
207*7c356e86SAndroid Build Coastguard Worker 
208*7c356e86SAndroid Build Coastguard Worker  Again:
209*7c356e86SAndroid Build Coastguard Worker 	states[0].type = SINVALID;
210*7c356e86SAndroid Build Coastguard Worker 	states[0].ls_base = NULL;
211*7c356e86SAndroid Build Coastguard Worker 	statep = &states[1];
212*7c356e86SAndroid Build Coastguard Worker 	state_info.base = states;
213*7c356e86SAndroid Build Coastguard Worker 	state_info.end = &state_info.base[STATE_BSIZE];
214*7c356e86SAndroid Build Coastguard Worker 
215*7c356e86SAndroid Build Coastguard Worker 	Xinit(ws, wp, 64, ATEMP);
216*7c356e86SAndroid Build Coastguard Worker 
217*7c356e86SAndroid Build Coastguard Worker 	backslash_skip = 0;
218*7c356e86SAndroid Build Coastguard Worker 	ignore_backslash_newline = 0;
219*7c356e86SAndroid Build Coastguard Worker 
220*7c356e86SAndroid Build Coastguard Worker 	if (cf & ONEWORD)
221*7c356e86SAndroid Build Coastguard Worker 		state = SWORD;
222*7c356e86SAndroid Build Coastguard Worker 	else if (cf & LETEXPR) {
223*7c356e86SAndroid Build Coastguard Worker 		/* enclose arguments in (double) quotes */
224*7c356e86SAndroid Build Coastguard Worker 		*wp++ = OQUOTE;
225*7c356e86SAndroid Build Coastguard Worker 		state = SLETPAREN;
226*7c356e86SAndroid Build Coastguard Worker 		statep->nparen = 0;
227*7c356e86SAndroid Build Coastguard Worker 	} else {
228*7c356e86SAndroid Build Coastguard Worker 		/* normal lexing */
229*7c356e86SAndroid Build Coastguard Worker 		state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
230*7c356e86SAndroid Build Coastguard Worker 		do {
231*7c356e86SAndroid Build Coastguard Worker 			c = getsc();
232*7c356e86SAndroid Build Coastguard Worker 		} while (ctype(c, C_BLANK));
233*7c356e86SAndroid Build Coastguard Worker 		if (c == '#') {
234*7c356e86SAndroid Build Coastguard Worker 			ignore_backslash_newline++;
235*7c356e86SAndroid Build Coastguard Worker 			do {
236*7c356e86SAndroid Build Coastguard Worker 				c = getsc();
237*7c356e86SAndroid Build Coastguard Worker 			} while (!ctype(c, C_NUL | C_LF));
238*7c356e86SAndroid Build Coastguard Worker 			ignore_backslash_newline--;
239*7c356e86SAndroid Build Coastguard Worker 		}
240*7c356e86SAndroid Build Coastguard Worker 		ungetsc(c);
241*7c356e86SAndroid Build Coastguard Worker 	}
242*7c356e86SAndroid Build Coastguard Worker 	if (source->flags & SF_ALIAS) {
243*7c356e86SAndroid Build Coastguard Worker 		/* trailing ' ' in alias definition */
244*7c356e86SAndroid Build Coastguard Worker 		source->flags &= ~SF_ALIAS;
245*7c356e86SAndroid Build Coastguard Worker 		/* POSIX: trailing space only counts if parsing simple cmd */
246*7c356e86SAndroid Build Coastguard Worker 		if (!Flag(FPOSIX) || (cf & CMDWORD))
247*7c356e86SAndroid Build Coastguard Worker 			cf |= ALIAS;
248*7c356e86SAndroid Build Coastguard Worker 	}
249*7c356e86SAndroid Build Coastguard Worker 
250*7c356e86SAndroid Build Coastguard Worker 	/* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */
251*7c356e86SAndroid Build Coastguard Worker 	statep->type = state;
252*7c356e86SAndroid Build Coastguard Worker 	statep->ls_flags = (cf & HEREDOC) ? LS_HEREDOC : 0;
253*7c356e86SAndroid Build Coastguard Worker 
254*7c356e86SAndroid Build Coastguard Worker 	/* collect non-special or quoted characters to form word */
255*7c356e86SAndroid Build Coastguard Worker 	while (!((c = getsc()) == 0 ||
256*7c356e86SAndroid Build Coastguard Worker 	    ((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
257*7c356e86SAndroid Build Coastguard Worker 		if (state == SBASE &&
258*7c356e86SAndroid Build Coastguard Worker 		    subshell_nesting_type == ORD(/*{*/ '}') &&
259*7c356e86SAndroid Build Coastguard Worker 		    (unsigned int)c == ORD(/*{*/ '}'))
260*7c356e86SAndroid Build Coastguard Worker 			/* possibly end ${ :;} */
261*7c356e86SAndroid Build Coastguard Worker 			break;
262*7c356e86SAndroid Build Coastguard Worker 		Xcheck(ws, wp);
263*7c356e86SAndroid Build Coastguard Worker 		switch (state) {
264*7c356e86SAndroid Build Coastguard Worker 		case SADELIM:
265*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('('))
266*7c356e86SAndroid Build Coastguard Worker 				statep->nparen++;
267*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD(')'))
268*7c356e86SAndroid Build Coastguard Worker 				statep->nparen--;
269*7c356e86SAndroid Build Coastguard Worker 			else if (statep->nparen == 0 &&
270*7c356e86SAndroid Build Coastguard Worker 			    ((unsigned int)c == ORD(/*{*/ '}') ||
271*7c356e86SAndroid Build Coastguard Worker 			    c == (int)statep->ls_adelim.delimiter)) {
272*7c356e86SAndroid Build Coastguard Worker 				*wp++ = ADELIM;
273*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
274*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)c == ORD(/*{*/ '}') ||
275*7c356e86SAndroid Build Coastguard Worker 				    --statep->ls_adelim.num == 0)
276*7c356e86SAndroid Build Coastguard Worker 					POP_STATE();
277*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)c == ORD(/*{*/ '}'))
278*7c356e86SAndroid Build Coastguard Worker 					POP_STATE();
279*7c356e86SAndroid Build Coastguard Worker 				break;
280*7c356e86SAndroid Build Coastguard Worker 			}
281*7c356e86SAndroid Build Coastguard Worker 			/* FALLTHROUGH */
282*7c356e86SAndroid Build Coastguard Worker 		case SBASE:
283*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('[') && (cf & CMDASN)) {
284*7c356e86SAndroid Build Coastguard Worker 				/* temporary */
285*7c356e86SAndroid Build Coastguard Worker 				*wp = EOS;
286*7c356e86SAndroid Build Coastguard Worker 				if (is_wdvarname(Xstring(ws, wp), false)) {
287*7c356e86SAndroid Build Coastguard Worker 					char *p, *tmp;
288*7c356e86SAndroid Build Coastguard Worker 
289*7c356e86SAndroid Build Coastguard Worker 					if (arraysub(&tmp)) {
290*7c356e86SAndroid Build Coastguard Worker 						*wp++ = CHAR;
291*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
292*7c356e86SAndroid Build Coastguard Worker 						for (p = tmp; *p; ) {
293*7c356e86SAndroid Build Coastguard Worker 							Xcheck(ws, wp);
294*7c356e86SAndroid Build Coastguard Worker 							*wp++ = CHAR;
295*7c356e86SAndroid Build Coastguard Worker 							*wp++ = *p++;
296*7c356e86SAndroid Build Coastguard Worker 						}
297*7c356e86SAndroid Build Coastguard Worker 						afree(tmp, ATEMP);
298*7c356e86SAndroid Build Coastguard Worker 						break;
299*7c356e86SAndroid Build Coastguard Worker 					}
300*7c356e86SAndroid Build Coastguard Worker 				}
301*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CHAR;
302*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
303*7c356e86SAndroid Build Coastguard Worker 				break;
304*7c356e86SAndroid Build Coastguard Worker 			}
305*7c356e86SAndroid Build Coastguard Worker 			/* FALLTHROUGH */
306*7c356e86SAndroid Build Coastguard Worker  Sbase1:		/* includes *(...|...) pattern (*+?@!) */
307*7c356e86SAndroid Build Coastguard Worker 			if (ctype(c, C_PATMO)) {
308*7c356e86SAndroid Build Coastguard Worker 				c2 = getsc();
309*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)c2 == ORD('(' /*)*/)) {
310*7c356e86SAndroid Build Coastguard Worker 					*wp++ = OPAT;
311*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
312*7c356e86SAndroid Build Coastguard Worker 					PUSH_STATE(SPATTERN);
313*7c356e86SAndroid Build Coastguard Worker 					break;
314*7c356e86SAndroid Build Coastguard Worker 				}
315*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c2);
316*7c356e86SAndroid Build Coastguard Worker 			}
317*7c356e86SAndroid Build Coastguard Worker 			/* FALLTHROUGH */
318*7c356e86SAndroid Build Coastguard Worker  Sbase2:		/* doesn't include *(...|...) pattern (*+?@!) */
319*7c356e86SAndroid Build Coastguard Worker 			switch (c) {
320*7c356e86SAndroid Build Coastguard Worker 			case ORD('\\'):
321*7c356e86SAndroid Build Coastguard Worker  getsc_qchar:
322*7c356e86SAndroid Build Coastguard Worker 				if ((c = getsc())) {
323*7c356e86SAndroid Build Coastguard Worker 					/* trailing \ is lost */
324*7c356e86SAndroid Build Coastguard Worker 					*wp++ = QCHAR;
325*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
326*7c356e86SAndroid Build Coastguard Worker 				}
327*7c356e86SAndroid Build Coastguard Worker 				break;
328*7c356e86SAndroid Build Coastguard Worker 			case ORD('\''):
329*7c356e86SAndroid Build Coastguard Worker  open_ssquote_unless_heredoc:
330*7c356e86SAndroid Build Coastguard Worker 				if ((statep->ls_flags & LS_HEREDOC))
331*7c356e86SAndroid Build Coastguard Worker 					goto store_char;
332*7c356e86SAndroid Build Coastguard Worker 				*wp++ = OQUOTE;
333*7c356e86SAndroid Build Coastguard Worker 				ignore_backslash_newline++;
334*7c356e86SAndroid Build Coastguard Worker 				PUSH_STATE(SSQUOTE);
335*7c356e86SAndroid Build Coastguard Worker 				break;
336*7c356e86SAndroid Build Coastguard Worker 			case ORD('"'):
337*7c356e86SAndroid Build Coastguard Worker  open_sdquote:
338*7c356e86SAndroid Build Coastguard Worker 				*wp++ = OQUOTE;
339*7c356e86SAndroid Build Coastguard Worker 				PUSH_STATE(SDQUOTE);
340*7c356e86SAndroid Build Coastguard Worker 				break;
341*7c356e86SAndroid Build Coastguard Worker 			case ORD('$'):
342*7c356e86SAndroid Build Coastguard Worker 				/*
343*7c356e86SAndroid Build Coastguard Worker 				 * processing of dollar sign belongs into
344*7c356e86SAndroid Build Coastguard Worker 				 * Subst, except for those which can open
345*7c356e86SAndroid Build Coastguard Worker 				 * a string: $'…' and $"…"
346*7c356e86SAndroid Build Coastguard Worker 				 */
347*7c356e86SAndroid Build Coastguard Worker  subst_dollar_ex:
348*7c356e86SAndroid Build Coastguard Worker 				c = getsc();
349*7c356e86SAndroid Build Coastguard Worker 				switch (c) {
350*7c356e86SAndroid Build Coastguard Worker 				case ORD('"'):
351*7c356e86SAndroid Build Coastguard Worker 					goto open_sdquote;
352*7c356e86SAndroid Build Coastguard Worker 				case ORD('\''):
353*7c356e86SAndroid Build Coastguard Worker 					goto open_sequote;
354*7c356e86SAndroid Build Coastguard Worker 				default:
355*7c356e86SAndroid Build Coastguard Worker 					goto SubstS;
356*7c356e86SAndroid Build Coastguard Worker 				}
357*7c356e86SAndroid Build Coastguard Worker 			default:
358*7c356e86SAndroid Build Coastguard Worker 				goto Subst;
359*7c356e86SAndroid Build Coastguard Worker 			}
360*7c356e86SAndroid Build Coastguard Worker 			break;
361*7c356e86SAndroid Build Coastguard Worker 
362*7c356e86SAndroid Build Coastguard Worker  Subst:
363*7c356e86SAndroid Build Coastguard Worker 			switch (c) {
364*7c356e86SAndroid Build Coastguard Worker 			case ORD('\\'):
365*7c356e86SAndroid Build Coastguard Worker 				c = getsc();
366*7c356e86SAndroid Build Coastguard Worker 				switch (c) {
367*7c356e86SAndroid Build Coastguard Worker 				case ORD('"'):
368*7c356e86SAndroid Build Coastguard Worker 					if ((statep->ls_flags & LS_HEREDOC))
369*7c356e86SAndroid Build Coastguard Worker 						goto heredocquote;
370*7c356e86SAndroid Build Coastguard Worker 					/* FALLTHROUGH */
371*7c356e86SAndroid Build Coastguard Worker 				case ORD('\\'):
372*7c356e86SAndroid Build Coastguard Worker 				case ORD('$'):
373*7c356e86SAndroid Build Coastguard Worker 				case ORD('`'):
374*7c356e86SAndroid Build Coastguard Worker  store_qchar:
375*7c356e86SAndroid Build Coastguard Worker 					*wp++ = QCHAR;
376*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
377*7c356e86SAndroid Build Coastguard Worker 					break;
378*7c356e86SAndroid Build Coastguard Worker 				default:
379*7c356e86SAndroid Build Coastguard Worker  heredocquote:
380*7c356e86SAndroid Build Coastguard Worker 					Xcheck(ws, wp);
381*7c356e86SAndroid Build Coastguard Worker 					if (c) {
382*7c356e86SAndroid Build Coastguard Worker 						/* trailing \ is lost */
383*7c356e86SAndroid Build Coastguard Worker 						*wp++ = CHAR;
384*7c356e86SAndroid Build Coastguard Worker 						*wp++ = '\\';
385*7c356e86SAndroid Build Coastguard Worker 						*wp++ = CHAR;
386*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
387*7c356e86SAndroid Build Coastguard Worker 					}
388*7c356e86SAndroid Build Coastguard Worker 					break;
389*7c356e86SAndroid Build Coastguard Worker 				}
390*7c356e86SAndroid Build Coastguard Worker 				break;
391*7c356e86SAndroid Build Coastguard Worker 			case ORD('$'):
392*7c356e86SAndroid Build Coastguard Worker 				c = getsc();
393*7c356e86SAndroid Build Coastguard Worker  SubstS:
394*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)c == ORD('(' /*)*/)) {
395*7c356e86SAndroid Build Coastguard Worker 					c = getsc();
396*7c356e86SAndroid Build Coastguard Worker 					if ((unsigned int)c == ORD('(' /*)*/)) {
397*7c356e86SAndroid Build Coastguard Worker 						*wp++ = EXPRSUB;
398*7c356e86SAndroid Build Coastguard Worker 						PUSH_SRETRACE(SASPAREN);
399*7c356e86SAndroid Build Coastguard Worker 						/* unneeded? */
400*7c356e86SAndroid Build Coastguard Worker 						/*statep->ls_flags &= ~LS_HEREDOC;*/
401*7c356e86SAndroid Build Coastguard Worker 						statep->nparen = 2;
402*7c356e86SAndroid Build Coastguard Worker 						*retrace_info->xp++ = '(';
403*7c356e86SAndroid Build Coastguard Worker 					} else {
404*7c356e86SAndroid Build Coastguard Worker 						ungetsc(c);
405*7c356e86SAndroid Build Coastguard Worker  subst_command:
406*7c356e86SAndroid Build Coastguard Worker 						c = COMSUB;
407*7c356e86SAndroid Build Coastguard Worker  subst_command2:
408*7c356e86SAndroid Build Coastguard Worker 						sp = yyrecursive(c);
409*7c356e86SAndroid Build Coastguard Worker 						cz = strlen(sp) + 1;
410*7c356e86SAndroid Build Coastguard Worker 						XcheckN(ws, wp, cz);
411*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
412*7c356e86SAndroid Build Coastguard Worker 						memcpy(wp, sp, cz);
413*7c356e86SAndroid Build Coastguard Worker 						wp += cz;
414*7c356e86SAndroid Build Coastguard Worker 					}
415*7c356e86SAndroid Build Coastguard Worker 				} else if ((unsigned int)c == ORD('{' /*}*/)) {
416*7c356e86SAndroid Build Coastguard Worker 					if ((unsigned int)(c = getsc()) == ORD('|')) {
417*7c356e86SAndroid Build Coastguard Worker 						/*
418*7c356e86SAndroid Build Coastguard Worker 						 * non-subenvironment
419*7c356e86SAndroid Build Coastguard Worker 						 * value substitution
420*7c356e86SAndroid Build Coastguard Worker 						 */
421*7c356e86SAndroid Build Coastguard Worker 						c = VALSUB;
422*7c356e86SAndroid Build Coastguard Worker 						goto subst_command2;
423*7c356e86SAndroid Build Coastguard Worker 					} else if (ctype(c, C_IFSWS)) {
424*7c356e86SAndroid Build Coastguard Worker 						/*
425*7c356e86SAndroid Build Coastguard Worker 						 * non-subenvironment
426*7c356e86SAndroid Build Coastguard Worker 						 * "command" substitution
427*7c356e86SAndroid Build Coastguard Worker 						 */
428*7c356e86SAndroid Build Coastguard Worker 						c = FUNSUB;
429*7c356e86SAndroid Build Coastguard Worker 						goto subst_command2;
430*7c356e86SAndroid Build Coastguard Worker 					}
431*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c);
432*7c356e86SAndroid Build Coastguard Worker 					*wp++ = OSUBST;
433*7c356e86SAndroid Build Coastguard Worker 					*wp++ = '{' /*}*/;
434*7c356e86SAndroid Build Coastguard Worker 					wp = get_brace_var(&ws, wp);
435*7c356e86SAndroid Build Coastguard Worker 					c = getsc();
436*7c356e86SAndroid Build Coastguard Worker 					/* allow :# and :% (ksh88 compat) */
437*7c356e86SAndroid Build Coastguard Worker 					if ((unsigned int)c == ORD(':')) {
438*7c356e86SAndroid Build Coastguard Worker 						*wp++ = CHAR;
439*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
440*7c356e86SAndroid Build Coastguard Worker 						c = getsc();
441*7c356e86SAndroid Build Coastguard Worker 						if ((unsigned int)c == ORD(':')) {
442*7c356e86SAndroid Build Coastguard Worker 							*wp++ = CHAR;
443*7c356e86SAndroid Build Coastguard Worker 							*wp++ = '0';
444*7c356e86SAndroid Build Coastguard Worker 							*wp++ = ADELIM;
445*7c356e86SAndroid Build Coastguard Worker 							*wp++ = ':';
446*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(SBRACE);
447*7c356e86SAndroid Build Coastguard Worker 							/* perhaps unneeded? */
448*7c356e86SAndroid Build Coastguard Worker 							statep->ls_flags &= ~LS_HEREDOC;
449*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(SADELIM);
450*7c356e86SAndroid Build Coastguard Worker 							statep->ls_adelim.delimiter = ':';
451*7c356e86SAndroid Build Coastguard Worker 							statep->ls_adelim.num = 1;
452*7c356e86SAndroid Build Coastguard Worker 							statep->nparen = 0;
453*7c356e86SAndroid Build Coastguard Worker 							break;
454*7c356e86SAndroid Build Coastguard Worker 						} else if (ctype(c, C_ALNUX | C_DOLAR | C_SPC) ||
455*7c356e86SAndroid Build Coastguard Worker 						    c == '(' /*)*/) {
456*7c356e86SAndroid Build Coastguard Worker 							/* substring subst. */
457*7c356e86SAndroid Build Coastguard Worker 							if (c != ' ') {
458*7c356e86SAndroid Build Coastguard Worker 								*wp++ = CHAR;
459*7c356e86SAndroid Build Coastguard Worker 								*wp++ = ' ';
460*7c356e86SAndroid Build Coastguard Worker 							}
461*7c356e86SAndroid Build Coastguard Worker 							ungetsc(c);
462*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(SBRACE);
463*7c356e86SAndroid Build Coastguard Worker 							/* perhaps unneeded? */
464*7c356e86SAndroid Build Coastguard Worker 							statep->ls_flags &= ~LS_HEREDOC;
465*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(SADELIM);
466*7c356e86SAndroid Build Coastguard Worker 							statep->ls_adelim.delimiter = ':';
467*7c356e86SAndroid Build Coastguard Worker 							statep->ls_adelim.num = 2;
468*7c356e86SAndroid Build Coastguard Worker 							statep->nparen = 0;
469*7c356e86SAndroid Build Coastguard Worker 							break;
470*7c356e86SAndroid Build Coastguard Worker 						}
471*7c356e86SAndroid Build Coastguard Worker 					} else if (c == '/') {
472*7c356e86SAndroid Build Coastguard Worker 						c2 = ADELIM;
473*7c356e86SAndroid Build Coastguard Worker  parse_adelim_slash:
474*7c356e86SAndroid Build Coastguard Worker 						*wp++ = CHAR;
475*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
476*7c356e86SAndroid Build Coastguard Worker 						if ((unsigned int)(c = getsc()) == ORD('/')) {
477*7c356e86SAndroid Build Coastguard Worker 							*wp++ = c2;
478*7c356e86SAndroid Build Coastguard Worker 							*wp++ = c;
479*7c356e86SAndroid Build Coastguard Worker 						} else
480*7c356e86SAndroid Build Coastguard Worker 							ungetsc(c);
481*7c356e86SAndroid Build Coastguard Worker 						PUSH_STATE(SBRACE);
482*7c356e86SAndroid Build Coastguard Worker 						/* perhaps unneeded? */
483*7c356e86SAndroid Build Coastguard Worker 						statep->ls_flags &= ~LS_HEREDOC;
484*7c356e86SAndroid Build Coastguard Worker 						PUSH_STATE(SADELIM);
485*7c356e86SAndroid Build Coastguard Worker 						statep->ls_adelim.delimiter = '/';
486*7c356e86SAndroid Build Coastguard Worker 						statep->ls_adelim.num = 1;
487*7c356e86SAndroid Build Coastguard Worker 						statep->nparen = 0;
488*7c356e86SAndroid Build Coastguard Worker 						break;
489*7c356e86SAndroid Build Coastguard Worker 					} else if (c == '@') {
490*7c356e86SAndroid Build Coastguard Worker 						c2 = getsc();
491*7c356e86SAndroid Build Coastguard Worker 						ungetsc(c2);
492*7c356e86SAndroid Build Coastguard Worker 						if ((unsigned int)c2 == ORD('/')) {
493*7c356e86SAndroid Build Coastguard Worker 							c2 = CHAR;
494*7c356e86SAndroid Build Coastguard Worker 							goto parse_adelim_slash;
495*7c356e86SAndroid Build Coastguard Worker 						}
496*7c356e86SAndroid Build Coastguard Worker 					}
497*7c356e86SAndroid Build Coastguard Worker 					/*
498*7c356e86SAndroid Build Coastguard Worker 					 * If this is a trim operation,
499*7c356e86SAndroid Build Coastguard Worker 					 * treat (,|,) specially in STBRACE.
500*7c356e86SAndroid Build Coastguard Worker 					 */
501*7c356e86SAndroid Build Coastguard Worker 					if (ctype(c, C_SUB2)) {
502*7c356e86SAndroid Build Coastguard Worker 						ungetsc(c);
503*7c356e86SAndroid Build Coastguard Worker 						if (Flag(FSH))
504*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(STBRACEBOURNE);
505*7c356e86SAndroid Build Coastguard Worker 						else
506*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(STBRACEKORN);
507*7c356e86SAndroid Build Coastguard Worker 						/* single-quotes-in-heredoc-trim */
508*7c356e86SAndroid Build Coastguard Worker 						statep->ls_flags &= ~LS_HEREDOC;
509*7c356e86SAndroid Build Coastguard Worker 					} else {
510*7c356e86SAndroid Build Coastguard Worker 						ungetsc(c);
511*7c356e86SAndroid Build Coastguard Worker 						if (state == SDQUOTE ||
512*7c356e86SAndroid Build Coastguard Worker 						    state == SQBRACE)
513*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(SQBRACE);
514*7c356e86SAndroid Build Coastguard Worker 						else
515*7c356e86SAndroid Build Coastguard Worker 							PUSH_STATE(SBRACE);
516*7c356e86SAndroid Build Coastguard Worker 						/* here no LS_HEREDOC removal */
517*7c356e86SAndroid Build Coastguard Worker 						/* single-quotes-in-heredoc-braces */
518*7c356e86SAndroid Build Coastguard Worker 					}
519*7c356e86SAndroid Build Coastguard Worker 				} else if (ctype(c, C_ALPHX)) {
520*7c356e86SAndroid Build Coastguard Worker 					*wp++ = OSUBST;
521*7c356e86SAndroid Build Coastguard Worker 					*wp++ = 'X';
522*7c356e86SAndroid Build Coastguard Worker 					do {
523*7c356e86SAndroid Build Coastguard Worker 						Xcheck(ws, wp);
524*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
525*7c356e86SAndroid Build Coastguard Worker 						c = getsc();
526*7c356e86SAndroid Build Coastguard Worker 					} while (ctype(c, C_ALNUX));
527*7c356e86SAndroid Build Coastguard Worker 					*wp++ = '\0';
528*7c356e86SAndroid Build Coastguard Worker 					*wp++ = CSUBST;
529*7c356e86SAndroid Build Coastguard Worker 					*wp++ = 'X';
530*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c);
531*7c356e86SAndroid Build Coastguard Worker 				} else if (ctype(c, C_VAR1 | C_DIGIT)) {
532*7c356e86SAndroid Build Coastguard Worker 					Xcheck(ws, wp);
533*7c356e86SAndroid Build Coastguard Worker 					*wp++ = OSUBST;
534*7c356e86SAndroid Build Coastguard Worker 					*wp++ = 'X';
535*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
536*7c356e86SAndroid Build Coastguard Worker 					*wp++ = '\0';
537*7c356e86SAndroid Build Coastguard Worker 					*wp++ = CSUBST;
538*7c356e86SAndroid Build Coastguard Worker 					*wp++ = 'X';
539*7c356e86SAndroid Build Coastguard Worker 				} else {
540*7c356e86SAndroid Build Coastguard Worker 					*wp++ = CHAR;
541*7c356e86SAndroid Build Coastguard Worker 					*wp++ = '$';
542*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c);
543*7c356e86SAndroid Build Coastguard Worker 				}
544*7c356e86SAndroid Build Coastguard Worker 				break;
545*7c356e86SAndroid Build Coastguard Worker 			case ORD('`'):
546*7c356e86SAndroid Build Coastguard Worker  subst_gravis:
547*7c356e86SAndroid Build Coastguard Worker 				PUSH_STATE(SBQUOTE);
548*7c356e86SAndroid Build Coastguard Worker 				*wp++ = COMASUB;
549*7c356e86SAndroid Build Coastguard Worker 				/*
550*7c356e86SAndroid Build Coastguard Worker 				 * We need to know whether we are within double
551*7c356e86SAndroid Build Coastguard Worker 				 * quotes in order to translate \" to " within
552*7c356e86SAndroid Build Coastguard Worker 				 * "…`…\"…`…" because, unlike for COMSUBs, the
553*7c356e86SAndroid Build Coastguard Worker 				 * outer double quoteing changes the backslash
554*7c356e86SAndroid Build Coastguard Worker 				 * meaning for the inside. For more details:
555*7c356e86SAndroid Build Coastguard Worker 				 * http://austingroupbugs.net/view.php?id=1015
556*7c356e86SAndroid Build Coastguard Worker 				 */
557*7c356e86SAndroid Build Coastguard Worker 				statep->ls_bool = false;
558*7c356e86SAndroid Build Coastguard Worker 				s2 = statep;
559*7c356e86SAndroid Build Coastguard Worker 				base = state_info.base;
560*7c356e86SAndroid Build Coastguard Worker 				while (/* CONSTCOND */ 1) {
561*7c356e86SAndroid Build Coastguard Worker 					for (; s2 != base; s2--) {
562*7c356e86SAndroid Build Coastguard Worker 						if (s2->type == SDQUOTE) {
563*7c356e86SAndroid Build Coastguard Worker 							statep->ls_bool = true;
564*7c356e86SAndroid Build Coastguard Worker 							break;
565*7c356e86SAndroid Build Coastguard Worker 						}
566*7c356e86SAndroid Build Coastguard Worker 					}
567*7c356e86SAndroid Build Coastguard Worker 					if (s2 != base)
568*7c356e86SAndroid Build Coastguard Worker 						break;
569*7c356e86SAndroid Build Coastguard Worker 					if (!(s2 = s2->ls_base))
570*7c356e86SAndroid Build Coastguard Worker 						break;
571*7c356e86SAndroid Build Coastguard Worker 					base = s2-- - STATE_BSIZE;
572*7c356e86SAndroid Build Coastguard Worker 				}
573*7c356e86SAndroid Build Coastguard Worker 				break;
574*7c356e86SAndroid Build Coastguard Worker 			case QCHAR:
575*7c356e86SAndroid Build Coastguard Worker 				if (cf & LQCHAR) {
576*7c356e86SAndroid Build Coastguard Worker 					*wp++ = QCHAR;
577*7c356e86SAndroid Build Coastguard Worker 					*wp++ = getsc();
578*7c356e86SAndroid Build Coastguard Worker 					break;
579*7c356e86SAndroid Build Coastguard Worker 				}
580*7c356e86SAndroid Build Coastguard Worker 				/* FALLTHROUGH */
581*7c356e86SAndroid Build Coastguard Worker 			default:
582*7c356e86SAndroid Build Coastguard Worker  store_char:
583*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CHAR;
584*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
585*7c356e86SAndroid Build Coastguard Worker 			}
586*7c356e86SAndroid Build Coastguard Worker 			break;
587*7c356e86SAndroid Build Coastguard Worker 
588*7c356e86SAndroid Build Coastguard Worker 		case SEQUOTE:
589*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('\'')) {
590*7c356e86SAndroid Build Coastguard Worker 				POP_STATE();
591*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CQUOTE;
592*7c356e86SAndroid Build Coastguard Worker 				ignore_backslash_newline--;
593*7c356e86SAndroid Build Coastguard Worker 			} else if ((unsigned int)c == ORD('\\')) {
594*7c356e86SAndroid Build Coastguard Worker 				if ((c2 = unbksl(true, getsc_i, ungetsc)) == -1)
595*7c356e86SAndroid Build Coastguard Worker 					c2 = getsc();
596*7c356e86SAndroid Build Coastguard Worker 				if (c2 == 0)
597*7c356e86SAndroid Build Coastguard Worker 					statep->ls_bool = true;
598*7c356e86SAndroid Build Coastguard Worker 				if (!statep->ls_bool) {
599*7c356e86SAndroid Build Coastguard Worker 					char ts[4];
600*7c356e86SAndroid Build Coastguard Worker 
601*7c356e86SAndroid Build Coastguard Worker 					if ((unsigned int)c2 < 0x100) {
602*7c356e86SAndroid Build Coastguard Worker 						*wp++ = QCHAR;
603*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c2;
604*7c356e86SAndroid Build Coastguard Worker 					} else {
605*7c356e86SAndroid Build Coastguard Worker 						cz = utf_wctomb(ts, c2 - 0x100);
606*7c356e86SAndroid Build Coastguard Worker 						ts[cz] = 0;
607*7c356e86SAndroid Build Coastguard Worker 						cz = 0;
608*7c356e86SAndroid Build Coastguard Worker 						do {
609*7c356e86SAndroid Build Coastguard Worker 							*wp++ = QCHAR;
610*7c356e86SAndroid Build Coastguard Worker 							*wp++ = ts[cz];
611*7c356e86SAndroid Build Coastguard Worker 						} while (ts[++cz]);
612*7c356e86SAndroid Build Coastguard Worker 					}
613*7c356e86SAndroid Build Coastguard Worker 				}
614*7c356e86SAndroid Build Coastguard Worker 			} else if (!statep->ls_bool) {
615*7c356e86SAndroid Build Coastguard Worker 				*wp++ = QCHAR;
616*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
617*7c356e86SAndroid Build Coastguard Worker 			}
618*7c356e86SAndroid Build Coastguard Worker 			break;
619*7c356e86SAndroid Build Coastguard Worker 
620*7c356e86SAndroid Build Coastguard Worker 		case SSQUOTE:
621*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('\'')) {
622*7c356e86SAndroid Build Coastguard Worker 				POP_STATE();
623*7c356e86SAndroid Build Coastguard Worker 				if ((statep->ls_flags & LS_HEREDOC) ||
624*7c356e86SAndroid Build Coastguard Worker 				    state == SQBRACE)
625*7c356e86SAndroid Build Coastguard Worker 					goto store_char;
626*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CQUOTE;
627*7c356e86SAndroid Build Coastguard Worker 				ignore_backslash_newline--;
628*7c356e86SAndroid Build Coastguard Worker 			} else {
629*7c356e86SAndroid Build Coastguard Worker 				*wp++ = QCHAR;
630*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
631*7c356e86SAndroid Build Coastguard Worker 			}
632*7c356e86SAndroid Build Coastguard Worker 			break;
633*7c356e86SAndroid Build Coastguard Worker 
634*7c356e86SAndroid Build Coastguard Worker 		case SDQUOTE:
635*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('"')) {
636*7c356e86SAndroid Build Coastguard Worker 				POP_STATE();
637*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CQUOTE;
638*7c356e86SAndroid Build Coastguard Worker 			} else
639*7c356e86SAndroid Build Coastguard Worker 				goto Subst;
640*7c356e86SAndroid Build Coastguard Worker 			break;
641*7c356e86SAndroid Build Coastguard Worker 
642*7c356e86SAndroid Build Coastguard Worker 		/* $(( ... )) */
643*7c356e86SAndroid Build Coastguard Worker 		case SASPAREN:
644*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('('))
645*7c356e86SAndroid Build Coastguard Worker 				statep->nparen++;
646*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD(')')) {
647*7c356e86SAndroid Build Coastguard Worker 				statep->nparen--;
648*7c356e86SAndroid Build Coastguard Worker 				if (statep->nparen == 1) {
649*7c356e86SAndroid Build Coastguard Worker 					/* end of EXPRSUB */
650*7c356e86SAndroid Build Coastguard Worker 					POP_SRETRACE();
651*7c356e86SAndroid Build Coastguard Worker 
652*7c356e86SAndroid Build Coastguard Worker 					if ((unsigned int)(c2 = getsc()) == ORD(/*(*/ ')')) {
653*7c356e86SAndroid Build Coastguard Worker 						cz = strlen(sp) - 2;
654*7c356e86SAndroid Build Coastguard Worker 						XcheckN(ws, wp, cz);
655*7c356e86SAndroid Build Coastguard Worker 						memcpy(wp, sp + 1, cz);
656*7c356e86SAndroid Build Coastguard Worker 						wp += cz;
657*7c356e86SAndroid Build Coastguard Worker 						afree(sp, ATEMP);
658*7c356e86SAndroid Build Coastguard Worker 						*wp++ = '\0';
659*7c356e86SAndroid Build Coastguard Worker 						break;
660*7c356e86SAndroid Build Coastguard Worker 					} else {
661*7c356e86SAndroid Build Coastguard Worker 						Source *s;
662*7c356e86SAndroid Build Coastguard Worker 
663*7c356e86SAndroid Build Coastguard Worker 						ungetsc(c2);
664*7c356e86SAndroid Build Coastguard Worker 						/*
665*7c356e86SAndroid Build Coastguard Worker 						 * mismatched parenthesis -
666*7c356e86SAndroid Build Coastguard Worker 						 * assume we were really
667*7c356e86SAndroid Build Coastguard Worker 						 * parsing a $(...) expression
668*7c356e86SAndroid Build Coastguard Worker 						 */
669*7c356e86SAndroid Build Coastguard Worker 						--wp;
670*7c356e86SAndroid Build Coastguard Worker 						s = pushs(SREREAD,
671*7c356e86SAndroid Build Coastguard Worker 						    source->areap);
672*7c356e86SAndroid Build Coastguard Worker 						s->start = s->str =
673*7c356e86SAndroid Build Coastguard Worker 						    s->u.freeme = sp;
674*7c356e86SAndroid Build Coastguard Worker 						s->next = source;
675*7c356e86SAndroid Build Coastguard Worker 						source = s;
676*7c356e86SAndroid Build Coastguard Worker 						goto subst_command;
677*7c356e86SAndroid Build Coastguard Worker 					}
678*7c356e86SAndroid Build Coastguard Worker 				}
679*7c356e86SAndroid Build Coastguard Worker 			}
680*7c356e86SAndroid Build Coastguard Worker 			/* reuse existing state machine */
681*7c356e86SAndroid Build Coastguard Worker 			goto Sbase2;
682*7c356e86SAndroid Build Coastguard Worker 
683*7c356e86SAndroid Build Coastguard Worker 		case SQBRACE:
684*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('\\')) {
685*7c356e86SAndroid Build Coastguard Worker 				/*
686*7c356e86SAndroid Build Coastguard Worker 				 * perform POSIX "quote removal" if the back-
687*7c356e86SAndroid Build Coastguard Worker 				 * slash is "special", i.e. same cases as the
688*7c356e86SAndroid Build Coastguard Worker 				 * {case '\\':} in Subst: plus closing brace;
689*7c356e86SAndroid Build Coastguard Worker 				 * in mksh code "quote removal" on '\c' means
690*7c356e86SAndroid Build Coastguard Worker 				 * write QCHAR+c, otherwise CHAR+\+CHAR+c are
691*7c356e86SAndroid Build Coastguard Worker 				 * emitted (in heredocquote:)
692*7c356e86SAndroid Build Coastguard Worker 				 */
693*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)(c = getsc()) == ORD('"') ||
694*7c356e86SAndroid Build Coastguard Worker 				    (unsigned int)c == ORD('\\') ||
695*7c356e86SAndroid Build Coastguard Worker 				    ctype(c, C_DOLAR | C_GRAVE) ||
696*7c356e86SAndroid Build Coastguard Worker 				    (unsigned int)c == ORD(/*{*/ '}'))
697*7c356e86SAndroid Build Coastguard Worker 					goto store_qchar;
698*7c356e86SAndroid Build Coastguard Worker 				goto heredocquote;
699*7c356e86SAndroid Build Coastguard Worker 			}
700*7c356e86SAndroid Build Coastguard Worker 			goto common_SQBRACE;
701*7c356e86SAndroid Build Coastguard Worker 
702*7c356e86SAndroid Build Coastguard Worker 		case SBRACE:
703*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('\''))
704*7c356e86SAndroid Build Coastguard Worker 				goto open_ssquote_unless_heredoc;
705*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD('\\'))
706*7c356e86SAndroid Build Coastguard Worker 				goto getsc_qchar;
707*7c356e86SAndroid Build Coastguard Worker  common_SQBRACE:
708*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('"'))
709*7c356e86SAndroid Build Coastguard Worker 				goto open_sdquote;
710*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD('$'))
711*7c356e86SAndroid Build Coastguard Worker 				goto subst_dollar_ex;
712*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD('`'))
713*7c356e86SAndroid Build Coastguard Worker 				goto subst_gravis;
714*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c != ORD(/*{*/ '}'))
715*7c356e86SAndroid Build Coastguard Worker 				goto store_char;
716*7c356e86SAndroid Build Coastguard Worker 			POP_STATE();
717*7c356e86SAndroid Build Coastguard Worker 			*wp++ = CSUBST;
718*7c356e86SAndroid Build Coastguard Worker 			*wp++ = /*{*/ '}';
719*7c356e86SAndroid Build Coastguard Worker 			break;
720*7c356e86SAndroid Build Coastguard Worker 
721*7c356e86SAndroid Build Coastguard Worker 		/* Same as SBASE, except (,|,) treated specially */
722*7c356e86SAndroid Build Coastguard Worker 		case STBRACEKORN:
723*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('|'))
724*7c356e86SAndroid Build Coastguard Worker 				*wp++ = SPAT;
725*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD('(')) {
726*7c356e86SAndroid Build Coastguard Worker 				*wp++ = OPAT;
727*7c356e86SAndroid Build Coastguard Worker 				/* simile for @ */
728*7c356e86SAndroid Build Coastguard Worker 				*wp++ = ' ';
729*7c356e86SAndroid Build Coastguard Worker 				PUSH_STATE(SPATTERN);
730*7c356e86SAndroid Build Coastguard Worker 			} else /* FALLTHROUGH */
731*7c356e86SAndroid Build Coastguard Worker 		case STBRACEBOURNE:
732*7c356e86SAndroid Build Coastguard Worker 			  if ((unsigned int)c == ORD(/*{*/ '}')) {
733*7c356e86SAndroid Build Coastguard Worker 				POP_STATE();
734*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CSUBST;
735*7c356e86SAndroid Build Coastguard Worker 				*wp++ = /*{*/ '}';
736*7c356e86SAndroid Build Coastguard Worker 			} else
737*7c356e86SAndroid Build Coastguard Worker 				goto Sbase1;
738*7c356e86SAndroid Build Coastguard Worker 			break;
739*7c356e86SAndroid Build Coastguard Worker 
740*7c356e86SAndroid Build Coastguard Worker 		case SBQUOTE:
741*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('`')) {
742*7c356e86SAndroid Build Coastguard Worker 				*wp++ = 0;
743*7c356e86SAndroid Build Coastguard Worker 				POP_STATE();
744*7c356e86SAndroid Build Coastguard Worker 			} else if ((unsigned int)c == ORD('\\')) {
745*7c356e86SAndroid Build Coastguard Worker 				switch (c = getsc()) {
746*7c356e86SAndroid Build Coastguard Worker 				case 0:
747*7c356e86SAndroid Build Coastguard Worker 					/* trailing \ is lost */
748*7c356e86SAndroid Build Coastguard Worker 					break;
749*7c356e86SAndroid Build Coastguard Worker 				case ORD('$'):
750*7c356e86SAndroid Build Coastguard Worker 				case ORD('`'):
751*7c356e86SAndroid Build Coastguard Worker 				case ORD('\\'):
752*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
753*7c356e86SAndroid Build Coastguard Worker 					break;
754*7c356e86SAndroid Build Coastguard Worker 				case ORD('"'):
755*7c356e86SAndroid Build Coastguard Worker 					if (statep->ls_bool) {
756*7c356e86SAndroid Build Coastguard Worker 						*wp++ = c;
757*7c356e86SAndroid Build Coastguard Worker 						break;
758*7c356e86SAndroid Build Coastguard Worker 					}
759*7c356e86SAndroid Build Coastguard Worker 					/* FALLTHROUGH */
760*7c356e86SAndroid Build Coastguard Worker 				default:
761*7c356e86SAndroid Build Coastguard Worker 					*wp++ = '\\';
762*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
763*7c356e86SAndroid Build Coastguard Worker 					break;
764*7c356e86SAndroid Build Coastguard Worker 				}
765*7c356e86SAndroid Build Coastguard Worker 			} else
766*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
767*7c356e86SAndroid Build Coastguard Worker 			break;
768*7c356e86SAndroid Build Coastguard Worker 
769*7c356e86SAndroid Build Coastguard Worker 		/* ONEWORD */
770*7c356e86SAndroid Build Coastguard Worker 		case SWORD:
771*7c356e86SAndroid Build Coastguard Worker 			goto Subst;
772*7c356e86SAndroid Build Coastguard Worker 
773*7c356e86SAndroid Build Coastguard Worker 		/* LETEXPR: (( ... )) */
774*7c356e86SAndroid Build Coastguard Worker 		case SLETPAREN:
775*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD(/*(*/ ')')) {
776*7c356e86SAndroid Build Coastguard Worker 				if (statep->nparen > 0)
777*7c356e86SAndroid Build Coastguard Worker 					--statep->nparen;
778*7c356e86SAndroid Build Coastguard Worker 				else if ((unsigned int)(c2 = getsc()) == ORD(/*(*/ ')')) {
779*7c356e86SAndroid Build Coastguard Worker 					c = 0;
780*7c356e86SAndroid Build Coastguard Worker 					*wp++ = CQUOTE;
781*7c356e86SAndroid Build Coastguard Worker 					goto Done;
782*7c356e86SAndroid Build Coastguard Worker 				} else {
783*7c356e86SAndroid Build Coastguard Worker 					Source *s;
784*7c356e86SAndroid Build Coastguard Worker 
785*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c2);
786*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c);
787*7c356e86SAndroid Build Coastguard Worker 					/*
788*7c356e86SAndroid Build Coastguard Worker 					 * mismatched parenthesis -
789*7c356e86SAndroid Build Coastguard Worker 					 * assume we were really
790*7c356e86SAndroid Build Coastguard Worker 					 * parsing a (...) expression
791*7c356e86SAndroid Build Coastguard Worker 					 */
792*7c356e86SAndroid Build Coastguard Worker 					*wp = EOS;
793*7c356e86SAndroid Build Coastguard Worker 					sp = Xstring(ws, wp);
794*7c356e86SAndroid Build Coastguard Worker 					dp = wdstrip(sp + 1, WDS_TPUTS);
795*7c356e86SAndroid Build Coastguard Worker 					s = pushs(SREREAD, source->areap);
796*7c356e86SAndroid Build Coastguard Worker 					s->start = s->str = s->u.freeme = dp;
797*7c356e86SAndroid Build Coastguard Worker 					s->next = source;
798*7c356e86SAndroid Build Coastguard Worker 					source = s;
799*7c356e86SAndroid Build Coastguard Worker 					ungetsc('(' /*)*/);
800*7c356e86SAndroid Build Coastguard Worker 					return (ORD('(' /*)*/));
801*7c356e86SAndroid Build Coastguard Worker 				}
802*7c356e86SAndroid Build Coastguard Worker 			} else if ((unsigned int)c == ORD('('))
803*7c356e86SAndroid Build Coastguard Worker 				/*
804*7c356e86SAndroid Build Coastguard Worker 				 * parentheses inside quotes and
805*7c356e86SAndroid Build Coastguard Worker 				 * backslashes are lost, but AT&T ksh
806*7c356e86SAndroid Build Coastguard Worker 				 * doesn't count them either
807*7c356e86SAndroid Build Coastguard Worker 				 */
808*7c356e86SAndroid Build Coastguard Worker 				++statep->nparen;
809*7c356e86SAndroid Build Coastguard Worker 			goto Sbase2;
810*7c356e86SAndroid Build Coastguard Worker 
811*7c356e86SAndroid Build Coastguard Worker 		/* << or <<- delimiter */
812*7c356e86SAndroid Build Coastguard Worker 		case SHEREDELIM:
813*7c356e86SAndroid Build Coastguard Worker 			/*
814*7c356e86SAndroid Build Coastguard Worker 			 * here delimiters need a special case since
815*7c356e86SAndroid Build Coastguard Worker 			 * $ and `...` are not to be treated specially
816*7c356e86SAndroid Build Coastguard Worker 			 */
817*7c356e86SAndroid Build Coastguard Worker 			switch (c) {
818*7c356e86SAndroid Build Coastguard Worker 			case ORD('\\'):
819*7c356e86SAndroid Build Coastguard Worker 				if ((c = getsc())) {
820*7c356e86SAndroid Build Coastguard Worker 					/* trailing \ is lost */
821*7c356e86SAndroid Build Coastguard Worker 					*wp++ = QCHAR;
822*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
823*7c356e86SAndroid Build Coastguard Worker 				}
824*7c356e86SAndroid Build Coastguard Worker 				break;
825*7c356e86SAndroid Build Coastguard Worker 			case ORD('\''):
826*7c356e86SAndroid Build Coastguard Worker 				goto open_ssquote_unless_heredoc;
827*7c356e86SAndroid Build Coastguard Worker 			case ORD('$'):
828*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)(c2 = getsc()) == ORD('\'')) {
829*7c356e86SAndroid Build Coastguard Worker  open_sequote:
830*7c356e86SAndroid Build Coastguard Worker 					*wp++ = OQUOTE;
831*7c356e86SAndroid Build Coastguard Worker 					ignore_backslash_newline++;
832*7c356e86SAndroid Build Coastguard Worker 					PUSH_STATE(SEQUOTE);
833*7c356e86SAndroid Build Coastguard Worker 					statep->ls_bool = false;
834*7c356e86SAndroid Build Coastguard Worker 					break;
835*7c356e86SAndroid Build Coastguard Worker 				} else if ((unsigned int)c2 == ORD('"')) {
836*7c356e86SAndroid Build Coastguard Worker 					/* FALLTHROUGH */
837*7c356e86SAndroid Build Coastguard Worker 			case ORD('"'):
838*7c356e86SAndroid Build Coastguard Worker 					PUSH_SRETRACE(SHEREDQUOTE);
839*7c356e86SAndroid Build Coastguard Worker 					break;
840*7c356e86SAndroid Build Coastguard Worker 				}
841*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c2);
842*7c356e86SAndroid Build Coastguard Worker 				/* FALLTHROUGH */
843*7c356e86SAndroid Build Coastguard Worker 			default:
844*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CHAR;
845*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
846*7c356e86SAndroid Build Coastguard Worker 			}
847*7c356e86SAndroid Build Coastguard Worker 			break;
848*7c356e86SAndroid Build Coastguard Worker 
849*7c356e86SAndroid Build Coastguard Worker 		/* " in << or <<- delimiter */
850*7c356e86SAndroid Build Coastguard Worker 		case SHEREDQUOTE:
851*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c != ORD('"'))
852*7c356e86SAndroid Build Coastguard Worker 				goto Subst;
853*7c356e86SAndroid Build Coastguard Worker 			POP_SRETRACE();
854*7c356e86SAndroid Build Coastguard Worker 			dp = strnul(sp) - 1;
855*7c356e86SAndroid Build Coastguard Worker 			/* remove the trailing double quote */
856*7c356e86SAndroid Build Coastguard Worker 			*dp = '\0';
857*7c356e86SAndroid Build Coastguard Worker 			/* store the quoted string */
858*7c356e86SAndroid Build Coastguard Worker 			*wp++ = OQUOTE;
859*7c356e86SAndroid Build Coastguard Worker 			XcheckN(ws, wp, (dp - sp) * 2);
860*7c356e86SAndroid Build Coastguard Worker 			dp = sp;
861*7c356e86SAndroid Build Coastguard Worker 			while ((c = *dp++)) {
862*7c356e86SAndroid Build Coastguard Worker 				if (c == '\\') {
863*7c356e86SAndroid Build Coastguard Worker 					switch ((c = *dp++)) {
864*7c356e86SAndroid Build Coastguard Worker 					case ORD('\\'):
865*7c356e86SAndroid Build Coastguard Worker 					case ORD('"'):
866*7c356e86SAndroid Build Coastguard Worker 					case ORD('$'):
867*7c356e86SAndroid Build Coastguard Worker 					case ORD('`'):
868*7c356e86SAndroid Build Coastguard Worker 						break;
869*7c356e86SAndroid Build Coastguard Worker 					default:
870*7c356e86SAndroid Build Coastguard Worker 						*wp++ = CHAR;
871*7c356e86SAndroid Build Coastguard Worker 						*wp++ = '\\';
872*7c356e86SAndroid Build Coastguard Worker 						break;
873*7c356e86SAndroid Build Coastguard Worker 					}
874*7c356e86SAndroid Build Coastguard Worker 				}
875*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CHAR;
876*7c356e86SAndroid Build Coastguard Worker 				*wp++ = c;
877*7c356e86SAndroid Build Coastguard Worker 			}
878*7c356e86SAndroid Build Coastguard Worker 			afree(sp, ATEMP);
879*7c356e86SAndroid Build Coastguard Worker 			*wp++ = CQUOTE;
880*7c356e86SAndroid Build Coastguard Worker 			state = statep->type = SHEREDELIM;
881*7c356e86SAndroid Build Coastguard Worker 			break;
882*7c356e86SAndroid Build Coastguard Worker 
883*7c356e86SAndroid Build Coastguard Worker 		/* in *(...|...) pattern (*+?@!) */
884*7c356e86SAndroid Build Coastguard Worker 		case SPATTERN:
885*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD(/*(*/ ')')) {
886*7c356e86SAndroid Build Coastguard Worker 				*wp++ = CPAT;
887*7c356e86SAndroid Build Coastguard Worker 				POP_STATE();
888*7c356e86SAndroid Build Coastguard Worker 			} else if ((unsigned int)c == ORD('|')) {
889*7c356e86SAndroid Build Coastguard Worker 				*wp++ = SPAT;
890*7c356e86SAndroid Build Coastguard Worker 			} else if ((unsigned int)c == ORD('(')) {
891*7c356e86SAndroid Build Coastguard Worker 				*wp++ = OPAT;
892*7c356e86SAndroid Build Coastguard Worker 				/* simile for @ */
893*7c356e86SAndroid Build Coastguard Worker 				*wp++ = ' ';
894*7c356e86SAndroid Build Coastguard Worker 				PUSH_STATE(SPATTERN);
895*7c356e86SAndroid Build Coastguard Worker 			} else
896*7c356e86SAndroid Build Coastguard Worker 				goto Sbase1;
897*7c356e86SAndroid Build Coastguard Worker 			break;
898*7c356e86SAndroid Build Coastguard Worker 		}
899*7c356e86SAndroid Build Coastguard Worker 	}
900*7c356e86SAndroid Build Coastguard Worker  Done:
901*7c356e86SAndroid Build Coastguard Worker 	Xcheck(ws, wp);
902*7c356e86SAndroid Build Coastguard Worker 	if (statep != &states[1])
903*7c356e86SAndroid Build Coastguard Worker 		/* XXX figure out what is missing */
904*7c356e86SAndroid Build Coastguard Worker 		yyerror("no closing quote");
905*7c356e86SAndroid Build Coastguard Worker 
906*7c356e86SAndroid Build Coastguard Worker 	/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
907*7c356e86SAndroid Build Coastguard Worker 	if (state == SHEREDELIM)
908*7c356e86SAndroid Build Coastguard Worker 		state = SBASE;
909*7c356e86SAndroid Build Coastguard Worker 
910*7c356e86SAndroid Build Coastguard Worker 	dp = Xstring(ws, wp);
911*7c356e86SAndroid Build Coastguard Worker 	if (state == SBASE && (
912*7c356e86SAndroid Build Coastguard Worker 	    (c == '&' && !Flag(FSH) && !Flag(FPOSIX)) ||
913*7c356e86SAndroid Build Coastguard Worker 	    ctype(c, C_ANGLE)) && ((c2 = Xlength(ws, wp)) == 0 ||
914*7c356e86SAndroid Build Coastguard Worker 	    (c2 == 2 && dp[0] == CHAR && ctype(dp[1], C_DIGIT)))) {
915*7c356e86SAndroid Build Coastguard Worker 		struct ioword *iop = alloc(sizeof(struct ioword), ATEMP);
916*7c356e86SAndroid Build Coastguard Worker 
917*7c356e86SAndroid Build Coastguard Worker 		iop->unit = c2 == 2 ? ksh_numdig(dp[1]) : c == '<' ? 0 : 1;
918*7c356e86SAndroid Build Coastguard Worker 
919*7c356e86SAndroid Build Coastguard Worker 		if (c == '&') {
920*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)(c2 = getsc()) != ORD('>')) {
921*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c2);
922*7c356e86SAndroid Build Coastguard Worker 				goto no_iop;
923*7c356e86SAndroid Build Coastguard Worker 			}
924*7c356e86SAndroid Build Coastguard Worker 			c = c2;
925*7c356e86SAndroid Build Coastguard Worker 			iop->ioflag = IOBASH;
926*7c356e86SAndroid Build Coastguard Worker 		} else
927*7c356e86SAndroid Build Coastguard Worker 			iop->ioflag = 0;
928*7c356e86SAndroid Build Coastguard Worker 
929*7c356e86SAndroid Build Coastguard Worker 		c2 = getsc();
930*7c356e86SAndroid Build Coastguard Worker 		/* <<, >>, <> are ok, >< is not */
931*7c356e86SAndroid Build Coastguard Worker 		if (c == c2 || ((unsigned int)c == ORD('<') &&
932*7c356e86SAndroid Build Coastguard Worker 		    (unsigned int)c2 == ORD('>'))) {
933*7c356e86SAndroid Build Coastguard Worker 			iop->ioflag |= c == c2 ?
934*7c356e86SAndroid Build Coastguard Worker 			    ((unsigned int)c == ORD('>') ? IOCAT : IOHERE) : IORDWR;
935*7c356e86SAndroid Build Coastguard Worker 			if (iop->ioflag == IOHERE) {
936*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)(c2 = getsc()) == ORD('-'))
937*7c356e86SAndroid Build Coastguard Worker 					iop->ioflag |= IOSKIP;
938*7c356e86SAndroid Build Coastguard Worker 				else if ((unsigned int)c2 == ORD('<'))
939*7c356e86SAndroid Build Coastguard Worker 					iop->ioflag |= IOHERESTR;
940*7c356e86SAndroid Build Coastguard Worker 				else
941*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c2);
942*7c356e86SAndroid Build Coastguard Worker 			}
943*7c356e86SAndroid Build Coastguard Worker 		} else if ((unsigned int)c2 == ORD('&'))
944*7c356e86SAndroid Build Coastguard Worker 			iop->ioflag |= IODUP | ((unsigned int)c == ORD('<') ? IORDUP : 0);
945*7c356e86SAndroid Build Coastguard Worker 		else {
946*7c356e86SAndroid Build Coastguard Worker 			iop->ioflag |= (unsigned int)c == ORD('>') ? IOWRITE : IOREAD;
947*7c356e86SAndroid Build Coastguard Worker 			if ((unsigned int)c == ORD('>') && (unsigned int)c2 == ORD('|'))
948*7c356e86SAndroid Build Coastguard Worker 				iop->ioflag |= IOCLOB;
949*7c356e86SAndroid Build Coastguard Worker 			else
950*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c2);
951*7c356e86SAndroid Build Coastguard Worker 		}
952*7c356e86SAndroid Build Coastguard Worker 
953*7c356e86SAndroid Build Coastguard Worker 		iop->ioname = NULL;
954*7c356e86SAndroid Build Coastguard Worker 		iop->delim = NULL;
955*7c356e86SAndroid Build Coastguard Worker 		iop->heredoc = NULL;
956*7c356e86SAndroid Build Coastguard Worker 		/* free word */
957*7c356e86SAndroid Build Coastguard Worker 		Xfree(ws, wp);
958*7c356e86SAndroid Build Coastguard Worker 		yylval.iop = iop;
959*7c356e86SAndroid Build Coastguard Worker 		return (REDIR);
960*7c356e86SAndroid Build Coastguard Worker  no_iop:
961*7c356e86SAndroid Build Coastguard Worker 		afree(iop, ATEMP);
962*7c356e86SAndroid Build Coastguard Worker 	}
963*7c356e86SAndroid Build Coastguard Worker 
964*7c356e86SAndroid Build Coastguard Worker 	if (wp == dp && state == SBASE) {
965*7c356e86SAndroid Build Coastguard Worker 		/* free word */
966*7c356e86SAndroid Build Coastguard Worker 		Xfree(ws, wp);
967*7c356e86SAndroid Build Coastguard Worker 		/* no word, process LEX1 character */
968*7c356e86SAndroid Build Coastguard Worker 		if (((unsigned int)c == ORD('|')) ||
969*7c356e86SAndroid Build Coastguard Worker 		    ((unsigned int)c == ORD('&')) ||
970*7c356e86SAndroid Build Coastguard Worker 		    ((unsigned int)c == ORD(';')) ||
971*7c356e86SAndroid Build Coastguard Worker 		    ((unsigned int)c == ORD('(' /*)*/))) {
972*7c356e86SAndroid Build Coastguard Worker 			if ((c2 = getsc()) == c)
973*7c356e86SAndroid Build Coastguard Worker 				c = ((unsigned int)c == ORD(';')) ? BREAK :
974*7c356e86SAndroid Build Coastguard Worker 				    ((unsigned int)c == ORD('|')) ? LOGOR :
975*7c356e86SAndroid Build Coastguard Worker 				    ((unsigned int)c == ORD('&')) ? LOGAND :
976*7c356e86SAndroid Build Coastguard Worker 				    /* (unsigned int)c == ORD('(' )) */ MDPAREN;
977*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD('|') && (unsigned int)c2 == ORD('&'))
978*7c356e86SAndroid Build Coastguard Worker 				c = COPROC;
979*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD(';') && (unsigned int)c2 == ORD('|'))
980*7c356e86SAndroid Build Coastguard Worker 				c = BRKEV;
981*7c356e86SAndroid Build Coastguard Worker 			else if ((unsigned int)c == ORD(';') && (unsigned int)c2 == ORD('&'))
982*7c356e86SAndroid Build Coastguard Worker 				c = BRKFT;
983*7c356e86SAndroid Build Coastguard Worker 			else
984*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c2);
985*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
986*7c356e86SAndroid Build Coastguard Worker 			if (c == BREAK) {
987*7c356e86SAndroid Build Coastguard Worker 				if ((unsigned int)(c2 = getsc()) == ORD('&'))
988*7c356e86SAndroid Build Coastguard Worker 					c = BRKEV;
989*7c356e86SAndroid Build Coastguard Worker 				else
990*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c2);
991*7c356e86SAndroid Build Coastguard Worker 			}
992*7c356e86SAndroid Build Coastguard Worker #endif
993*7c356e86SAndroid Build Coastguard Worker 		} else if ((unsigned int)c == ORD('\n')) {
994*7c356e86SAndroid Build Coastguard Worker 			if (cf & HEREDELIM)
995*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c);
996*7c356e86SAndroid Build Coastguard Worker 			else {
997*7c356e86SAndroid Build Coastguard Worker 				gethere();
998*7c356e86SAndroid Build Coastguard Worker 				if (cf & CONTIN)
999*7c356e86SAndroid Build Coastguard Worker 					goto Again;
1000*7c356e86SAndroid Build Coastguard Worker 			}
1001*7c356e86SAndroid Build Coastguard Worker 		} else if (c == '\0' && !(cf & HEREDELIM)) {
1002*7c356e86SAndroid Build Coastguard Worker 			struct ioword **p = heres;
1003*7c356e86SAndroid Build Coastguard Worker 
1004*7c356e86SAndroid Build Coastguard Worker 			while (p < herep)
1005*7c356e86SAndroid Build Coastguard Worker 				if ((*p)->ioflag & IOHERESTR)
1006*7c356e86SAndroid Build Coastguard Worker 					++p;
1007*7c356e86SAndroid Build Coastguard Worker 				else
1008*7c356e86SAndroid Build Coastguard Worker 					/* ksh -c 'cat <<EOF' can cause this */
1009*7c356e86SAndroid Build Coastguard Worker 					yyerror(Tf_heredoc,
1010*7c356e86SAndroid Build Coastguard Worker 					    evalstr((*p)->delim, 0));
1011*7c356e86SAndroid Build Coastguard Worker 		}
1012*7c356e86SAndroid Build Coastguard Worker 		return (c);
1013*7c356e86SAndroid Build Coastguard Worker 	}
1014*7c356e86SAndroid Build Coastguard Worker 
1015*7c356e86SAndroid Build Coastguard Worker 	/* terminate word */
1016*7c356e86SAndroid Build Coastguard Worker 	*wp++ = EOS;
1017*7c356e86SAndroid Build Coastguard Worker 	yylval.cp = Xclose(ws, wp);
1018*7c356e86SAndroid Build Coastguard Worker 	if (state == SWORD || state == SLETPAREN
1019*7c356e86SAndroid Build Coastguard Worker 	    /* XXX ONEWORD? */)
1020*7c356e86SAndroid Build Coastguard Worker 		return (LWORD);
1021*7c356e86SAndroid Build Coastguard Worker 
1022*7c356e86SAndroid Build Coastguard Worker 	/* unget terminator */
1023*7c356e86SAndroid Build Coastguard Worker 	ungetsc(c);
1024*7c356e86SAndroid Build Coastguard Worker 
1025*7c356e86SAndroid Build Coastguard Worker 	/*
1026*7c356e86SAndroid Build Coastguard Worker 	 * note: the alias-vs-function code below depends on several
1027*7c356e86SAndroid Build Coastguard Worker 	 * interna: starting from here, source->str is not modified;
1028*7c356e86SAndroid Build Coastguard Worker 	 * the way getsc() and ungetsc() operate; etc.
1029*7c356e86SAndroid Build Coastguard Worker 	 */
1030*7c356e86SAndroid Build Coastguard Worker 
1031*7c356e86SAndroid Build Coastguard Worker 	/* copy word to unprefixed string ident */
1032*7c356e86SAndroid Build Coastguard Worker 	sp = yylval.cp;
1033*7c356e86SAndroid Build Coastguard Worker 	dp = ident;
1034*7c356e86SAndroid Build Coastguard Worker 	while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
1035*7c356e86SAndroid Build Coastguard Worker 		*dp++ = *sp++;
1036*7c356e86SAndroid Build Coastguard Worker 	if (c != EOS)
1037*7c356e86SAndroid Build Coastguard Worker 		/* word is not unquoted, or space ran out */
1038*7c356e86SAndroid Build Coastguard Worker 		dp = ident;
1039*7c356e86SAndroid Build Coastguard Worker 	/* make sure the ident array stays NUL padded */
1040*7c356e86SAndroid Build Coastguard Worker 	memset(dp, 0, (ident + IDENT) - dp + 1);
1041*7c356e86SAndroid Build Coastguard Worker 
1042*7c356e86SAndroid Build Coastguard Worker 	if (*ident != '\0' && (cf & (KEYWORD | ALIAS))) {
1043*7c356e86SAndroid Build Coastguard Worker 		struct tbl *p;
1044*7c356e86SAndroid Build Coastguard Worker 		uint32_t h = hash(ident);
1045*7c356e86SAndroid Build Coastguard Worker 
1046*7c356e86SAndroid Build Coastguard Worker 		if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
1047*7c356e86SAndroid Build Coastguard Worker 		    (!(cf & ESACONLY) || p->val.i == ESAC ||
1048*7c356e86SAndroid Build Coastguard Worker 		    (unsigned int)p->val.i == ORD(/*{*/ '}'))) {
1049*7c356e86SAndroid Build Coastguard Worker 			afree(yylval.cp, ATEMP);
1050*7c356e86SAndroid Build Coastguard Worker 			return (p->val.i);
1051*7c356e86SAndroid Build Coastguard Worker 		}
1052*7c356e86SAndroid Build Coastguard Worker 		if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h)) &&
1053*7c356e86SAndroid Build Coastguard Worker 		    (p->flag & ISSET)) {
1054*7c356e86SAndroid Build Coastguard Worker 			/*
1055*7c356e86SAndroid Build Coastguard Worker 			 * this still points to the same character as the
1056*7c356e86SAndroid Build Coastguard Worker 			 * ungetsc'd terminator from above
1057*7c356e86SAndroid Build Coastguard Worker 			 */
1058*7c356e86SAndroid Build Coastguard Worker 			const char *cp = source->str;
1059*7c356e86SAndroid Build Coastguard Worker 
1060*7c356e86SAndroid Build Coastguard Worker 			/* prefer POSIX but not Korn functions over aliases */
1061*7c356e86SAndroid Build Coastguard Worker 			while (ctype(*cp, C_BLANK))
1062*7c356e86SAndroid Build Coastguard Worker 				/*
1063*7c356e86SAndroid Build Coastguard Worker 				 * this is like getsc() without skipping
1064*7c356e86SAndroid Build Coastguard Worker 				 * over Source boundaries (including not
1065*7c356e86SAndroid Build Coastguard Worker 				 * parsing ungetsc'd characters that got
1066*7c356e86SAndroid Build Coastguard Worker 				 * pushed into an SREREAD) which is what
1067*7c356e86SAndroid Build Coastguard Worker 				 * we want here anyway: find out whether
1068*7c356e86SAndroid Build Coastguard Worker 				 * the alias name is followed by a POSIX
1069*7c356e86SAndroid Build Coastguard Worker 				 * function definition
1070*7c356e86SAndroid Build Coastguard Worker 				 */
1071*7c356e86SAndroid Build Coastguard Worker 				++cp;
1072*7c356e86SAndroid Build Coastguard Worker 			/* prefer functions over aliases */
1073*7c356e86SAndroid Build Coastguard Worker 			if (cp[0] != '(' || cp[1] != ')') {
1074*7c356e86SAndroid Build Coastguard Worker 				Source *s = source;
1075*7c356e86SAndroid Build Coastguard Worker 
1076*7c356e86SAndroid Build Coastguard Worker 				while (s && (s->flags & SF_HASALIAS))
1077*7c356e86SAndroid Build Coastguard Worker 					if (s->u.tblp == p)
1078*7c356e86SAndroid Build Coastguard Worker 						return (LWORD);
1079*7c356e86SAndroid Build Coastguard Worker 					else
1080*7c356e86SAndroid Build Coastguard Worker 						s = s->next;
1081*7c356e86SAndroid Build Coastguard Worker 				/* push alias expansion */
1082*7c356e86SAndroid Build Coastguard Worker 				s = pushs(SALIAS, source->areap);
1083*7c356e86SAndroid Build Coastguard Worker 				s->start = s->str = p->val.s;
1084*7c356e86SAndroid Build Coastguard Worker 				s->u.tblp = p;
1085*7c356e86SAndroid Build Coastguard Worker 				s->flags |= SF_HASALIAS;
1086*7c356e86SAndroid Build Coastguard Worker 				s->line = source->line;
1087*7c356e86SAndroid Build Coastguard Worker 				s->next = source;
1088*7c356e86SAndroid Build Coastguard Worker 				if (source->type == SEOF) {
1089*7c356e86SAndroid Build Coastguard Worker 					/* prevent infinite recursion at EOS */
1090*7c356e86SAndroid Build Coastguard Worker 					source->u.tblp = p;
1091*7c356e86SAndroid Build Coastguard Worker 					source->flags |= SF_HASALIAS;
1092*7c356e86SAndroid Build Coastguard Worker 				}
1093*7c356e86SAndroid Build Coastguard Worker 				source = s;
1094*7c356e86SAndroid Build Coastguard Worker 				afree(yylval.cp, ATEMP);
1095*7c356e86SAndroid Build Coastguard Worker 				goto Again;
1096*7c356e86SAndroid Build Coastguard Worker 			}
1097*7c356e86SAndroid Build Coastguard Worker 		}
1098*7c356e86SAndroid Build Coastguard Worker 	} else if (*ident == '\0') {
1099*7c356e86SAndroid Build Coastguard Worker 		/* retain typeset et al. even when quoted */
1100*7c356e86SAndroid Build Coastguard Worker 		struct tbl *tt = get_builtin((dp = wdstrip(yylval.cp, 0)));
1101*7c356e86SAndroid Build Coastguard Worker 		uint32_t flag = tt ? tt->flag : 0;
1102*7c356e86SAndroid Build Coastguard Worker 
1103*7c356e86SAndroid Build Coastguard Worker 		if (flag & (DECL_UTIL | DECL_FWDR))
1104*7c356e86SAndroid Build Coastguard Worker 			strlcpy(ident, dp, sizeof(ident));
1105*7c356e86SAndroid Build Coastguard Worker 		afree(dp, ATEMP);
1106*7c356e86SAndroid Build Coastguard Worker 	}
1107*7c356e86SAndroid Build Coastguard Worker 
1108*7c356e86SAndroid Build Coastguard Worker 	return (LWORD);
1109*7c356e86SAndroid Build Coastguard Worker }
1110*7c356e86SAndroid Build Coastguard Worker 
1111*7c356e86SAndroid Build Coastguard Worker static void
gethere(void)1112*7c356e86SAndroid Build Coastguard Worker gethere(void)
1113*7c356e86SAndroid Build Coastguard Worker {
1114*7c356e86SAndroid Build Coastguard Worker 	struct ioword **p;
1115*7c356e86SAndroid Build Coastguard Worker 
1116*7c356e86SAndroid Build Coastguard Worker 	for (p = heres; p < herep; p++)
1117*7c356e86SAndroid Build Coastguard Worker 		if (!((*p)->ioflag & IOHERESTR))
1118*7c356e86SAndroid Build Coastguard Worker 			readhere(*p);
1119*7c356e86SAndroid Build Coastguard Worker 	herep = heres;
1120*7c356e86SAndroid Build Coastguard Worker }
1121*7c356e86SAndroid Build Coastguard Worker 
1122*7c356e86SAndroid Build Coastguard Worker /*
1123*7c356e86SAndroid Build Coastguard Worker  * read "<<word" text into temp file
1124*7c356e86SAndroid Build Coastguard Worker  */
1125*7c356e86SAndroid Build Coastguard Worker 
1126*7c356e86SAndroid Build Coastguard Worker static void
readhere(struct ioword * iop)1127*7c356e86SAndroid Build Coastguard Worker readhere(struct ioword *iop)
1128*7c356e86SAndroid Build Coastguard Worker {
1129*7c356e86SAndroid Build Coastguard Worker 	int c;
1130*7c356e86SAndroid Build Coastguard Worker 	const char *eof, *eofp;
1131*7c356e86SAndroid Build Coastguard Worker 	XString xs;
1132*7c356e86SAndroid Build Coastguard Worker 	char *xp;
1133*7c356e86SAndroid Build Coastguard Worker 	size_t xpos;
1134*7c356e86SAndroid Build Coastguard Worker 
1135*7c356e86SAndroid Build Coastguard Worker 	eof = evalstr(iop->delim, 0);
1136*7c356e86SAndroid Build Coastguard Worker 
1137*7c356e86SAndroid Build Coastguard Worker 	if (!(iop->ioflag & IOEVAL))
1138*7c356e86SAndroid Build Coastguard Worker 		ignore_backslash_newline++;
1139*7c356e86SAndroid Build Coastguard Worker 
1140*7c356e86SAndroid Build Coastguard Worker 	Xinit(xs, xp, 256, ATEMP);
1141*7c356e86SAndroid Build Coastguard Worker 
1142*7c356e86SAndroid Build Coastguard Worker  heredoc_read_line:
1143*7c356e86SAndroid Build Coastguard Worker 	/* beginning of line */
1144*7c356e86SAndroid Build Coastguard Worker 	eofp = eof;
1145*7c356e86SAndroid Build Coastguard Worker 	xpos = Xsavepos(xs, xp);
1146*7c356e86SAndroid Build Coastguard Worker 	if (iop->ioflag & IOSKIP) {
1147*7c356e86SAndroid Build Coastguard Worker 		/* skip over leading tabs */
1148*7c356e86SAndroid Build Coastguard Worker 		while ((c = getsc()) == '\t')
1149*7c356e86SAndroid Build Coastguard Worker 			;	/* nothing */
1150*7c356e86SAndroid Build Coastguard Worker 		goto heredoc_parse_char;
1151*7c356e86SAndroid Build Coastguard Worker 	}
1152*7c356e86SAndroid Build Coastguard Worker  heredoc_read_char:
1153*7c356e86SAndroid Build Coastguard Worker 	c = getsc();
1154*7c356e86SAndroid Build Coastguard Worker  heredoc_parse_char:
1155*7c356e86SAndroid Build Coastguard Worker 	/* compare with here document marker */
1156*7c356e86SAndroid Build Coastguard Worker 	if (!*eofp) {
1157*7c356e86SAndroid Build Coastguard Worker 		/* end of here document marker, what to do? */
1158*7c356e86SAndroid Build Coastguard Worker 		switch (c) {
1159*7c356e86SAndroid Build Coastguard Worker 		case ORD(/*(*/ ')'):
1160*7c356e86SAndroid Build Coastguard Worker 			if (!subshell_nesting_type)
1161*7c356e86SAndroid Build Coastguard Worker 				/*-
1162*7c356e86SAndroid Build Coastguard Worker 				 * not allowed outside $(...) or (...)
1163*7c356e86SAndroid Build Coastguard Worker 				 * => mismatch
1164*7c356e86SAndroid Build Coastguard Worker 				 */
1165*7c356e86SAndroid Build Coastguard Worker 				break;
1166*7c356e86SAndroid Build Coastguard Worker 			/* allow $(...) or (...) to close here */
1167*7c356e86SAndroid Build Coastguard Worker 			ungetsc(/*(*/ ')');
1168*7c356e86SAndroid Build Coastguard Worker 			/* FALLTHROUGH */
1169*7c356e86SAndroid Build Coastguard Worker 		case 0:
1170*7c356e86SAndroid Build Coastguard Worker 			/*
1171*7c356e86SAndroid Build Coastguard Worker 			 * Allow EOF here to commands without trailing
1172*7c356e86SAndroid Build Coastguard Worker 			 * newlines (mksh -c '...') will work as well.
1173*7c356e86SAndroid Build Coastguard Worker 			 */
1174*7c356e86SAndroid Build Coastguard Worker 		case ORD('\n'):
1175*7c356e86SAndroid Build Coastguard Worker 			/* Newline terminates here document marker */
1176*7c356e86SAndroid Build Coastguard Worker 			goto heredoc_found_terminator;
1177*7c356e86SAndroid Build Coastguard Worker 		}
1178*7c356e86SAndroid Build Coastguard Worker 	} else if ((unsigned int)c == ord(*eofp++))
1179*7c356e86SAndroid Build Coastguard Worker 		/* store; then read and compare next character */
1180*7c356e86SAndroid Build Coastguard Worker 		goto heredoc_store_and_loop;
1181*7c356e86SAndroid Build Coastguard Worker 	/* nope, mismatch; read until end of line */
1182*7c356e86SAndroid Build Coastguard Worker 	while (c != '\n') {
1183*7c356e86SAndroid Build Coastguard Worker 		if (!c)
1184*7c356e86SAndroid Build Coastguard Worker 			/* oops, reached EOF */
1185*7c356e86SAndroid Build Coastguard Worker 			yyerror(Tf_heredoc, eof);
1186*7c356e86SAndroid Build Coastguard Worker 		/* store character */
1187*7c356e86SAndroid Build Coastguard Worker 		Xcheck(xs, xp);
1188*7c356e86SAndroid Build Coastguard Worker 		Xput(xs, xp, c);
1189*7c356e86SAndroid Build Coastguard Worker 		/* read next character */
1190*7c356e86SAndroid Build Coastguard Worker 		c = getsc();
1191*7c356e86SAndroid Build Coastguard Worker 	}
1192*7c356e86SAndroid Build Coastguard Worker 	/* we read a newline as last character */
1193*7c356e86SAndroid Build Coastguard Worker  heredoc_store_and_loop:
1194*7c356e86SAndroid Build Coastguard Worker 	/* store character */
1195*7c356e86SAndroid Build Coastguard Worker 	Xcheck(xs, xp);
1196*7c356e86SAndroid Build Coastguard Worker 	Xput(xs, xp, c);
1197*7c356e86SAndroid Build Coastguard Worker 	if (c == '\n')
1198*7c356e86SAndroid Build Coastguard Worker 		goto heredoc_read_line;
1199*7c356e86SAndroid Build Coastguard Worker 	goto heredoc_read_char;
1200*7c356e86SAndroid Build Coastguard Worker 
1201*7c356e86SAndroid Build Coastguard Worker  heredoc_found_terminator:
1202*7c356e86SAndroid Build Coastguard Worker 	/* jump back to saved beginning of line */
1203*7c356e86SAndroid Build Coastguard Worker 	xp = Xrestpos(xs, xp, xpos);
1204*7c356e86SAndroid Build Coastguard Worker 	/* terminate, close and store */
1205*7c356e86SAndroid Build Coastguard Worker 	Xput(xs, xp, '\0');
1206*7c356e86SAndroid Build Coastguard Worker 	iop->heredoc = Xclose(xs, xp);
1207*7c356e86SAndroid Build Coastguard Worker 
1208*7c356e86SAndroid Build Coastguard Worker 	if (!(iop->ioflag & IOEVAL))
1209*7c356e86SAndroid Build Coastguard Worker 		ignore_backslash_newline--;
1210*7c356e86SAndroid Build Coastguard Worker }
1211*7c356e86SAndroid Build Coastguard Worker 
1212*7c356e86SAndroid Build Coastguard Worker void
yyerror(const char * fmt,...)1213*7c356e86SAndroid Build Coastguard Worker yyerror(const char *fmt, ...)
1214*7c356e86SAndroid Build Coastguard Worker {
1215*7c356e86SAndroid Build Coastguard Worker 	va_list va;
1216*7c356e86SAndroid Build Coastguard Worker 
1217*7c356e86SAndroid Build Coastguard Worker 	/* pop aliases and re-reads */
1218*7c356e86SAndroid Build Coastguard Worker 	while (source->type == SALIAS || source->type == SREREAD)
1219*7c356e86SAndroid Build Coastguard Worker 		source = source->next;
1220*7c356e86SAndroid Build Coastguard Worker 	/* zap pending input */
1221*7c356e86SAndroid Build Coastguard Worker 	source->str = null;
1222*7c356e86SAndroid Build Coastguard Worker 
1223*7c356e86SAndroid Build Coastguard Worker 	error_prefix(true);
1224*7c356e86SAndroid Build Coastguard Worker 	va_start(va, fmt);
1225*7c356e86SAndroid Build Coastguard Worker 	shf_vfprintf(shl_out, fmt, va);
1226*7c356e86SAndroid Build Coastguard Worker 	shf_putc('\n', shl_out);
1227*7c356e86SAndroid Build Coastguard Worker 	va_end(va);
1228*7c356e86SAndroid Build Coastguard Worker 	errorfz();
1229*7c356e86SAndroid Build Coastguard Worker }
1230*7c356e86SAndroid Build Coastguard Worker 
1231*7c356e86SAndroid Build Coastguard Worker /*
1232*7c356e86SAndroid Build Coastguard Worker  * input for yylex with alias expansion
1233*7c356e86SAndroid Build Coastguard Worker  */
1234*7c356e86SAndroid Build Coastguard Worker 
1235*7c356e86SAndroid Build Coastguard Worker Source *
pushs(int type,Area * areap)1236*7c356e86SAndroid Build Coastguard Worker pushs(int type, Area *areap)
1237*7c356e86SAndroid Build Coastguard Worker {
1238*7c356e86SAndroid Build Coastguard Worker 	Source *s;
1239*7c356e86SAndroid Build Coastguard Worker 
1240*7c356e86SAndroid Build Coastguard Worker 	s = alloc(sizeof(Source), areap);
1241*7c356e86SAndroid Build Coastguard Worker 	memset(s, 0, sizeof(Source));
1242*7c356e86SAndroid Build Coastguard Worker 	s->type = type;
1243*7c356e86SAndroid Build Coastguard Worker 	s->str = null;
1244*7c356e86SAndroid Build Coastguard Worker 	s->areap = areap;
1245*7c356e86SAndroid Build Coastguard Worker 	if (type == SFILE || type == SSTDIN)
1246*7c356e86SAndroid Build Coastguard Worker 		XinitN(s->xs, 256, s->areap);
1247*7c356e86SAndroid Build Coastguard Worker 	return (s);
1248*7c356e86SAndroid Build Coastguard Worker }
1249*7c356e86SAndroid Build Coastguard Worker 
1250*7c356e86SAndroid Build Coastguard Worker static int
getsc_uu(void)1251*7c356e86SAndroid Build Coastguard Worker getsc_uu(void)
1252*7c356e86SAndroid Build Coastguard Worker {
1253*7c356e86SAndroid Build Coastguard Worker 	Source *s = source;
1254*7c356e86SAndroid Build Coastguard Worker 	int c;
1255*7c356e86SAndroid Build Coastguard Worker 
1256*7c356e86SAndroid Build Coastguard Worker 	while ((c = ord(*s->str++)) == 0) {
1257*7c356e86SAndroid Build Coastguard Worker 		/* return 0 for EOF by default */
1258*7c356e86SAndroid Build Coastguard Worker 		s->str = NULL;
1259*7c356e86SAndroid Build Coastguard Worker 		switch (s->type) {
1260*7c356e86SAndroid Build Coastguard Worker 		case SEOF:
1261*7c356e86SAndroid Build Coastguard Worker 			s->str = null;
1262*7c356e86SAndroid Build Coastguard Worker 			return (0);
1263*7c356e86SAndroid Build Coastguard Worker 
1264*7c356e86SAndroid Build Coastguard Worker 		case SSTDIN:
1265*7c356e86SAndroid Build Coastguard Worker 		case SFILE:
1266*7c356e86SAndroid Build Coastguard Worker 			getsc_line(s);
1267*7c356e86SAndroid Build Coastguard Worker 			break;
1268*7c356e86SAndroid Build Coastguard Worker 
1269*7c356e86SAndroid Build Coastguard Worker 		case SWSTR:
1270*7c356e86SAndroid Build Coastguard Worker 			break;
1271*7c356e86SAndroid Build Coastguard Worker 
1272*7c356e86SAndroid Build Coastguard Worker 		case SSTRING:
1273*7c356e86SAndroid Build Coastguard Worker 		case SSTRINGCMDLINE:
1274*7c356e86SAndroid Build Coastguard Worker 			break;
1275*7c356e86SAndroid Build Coastguard Worker 
1276*7c356e86SAndroid Build Coastguard Worker 		case SWORDS:
1277*7c356e86SAndroid Build Coastguard Worker 			s->start = s->str = *s->u.strv++;
1278*7c356e86SAndroid Build Coastguard Worker 			s->type = SWORDSEP;
1279*7c356e86SAndroid Build Coastguard Worker 			break;
1280*7c356e86SAndroid Build Coastguard Worker 
1281*7c356e86SAndroid Build Coastguard Worker 		case SWORDSEP:
1282*7c356e86SAndroid Build Coastguard Worker 			if (*s->u.strv == NULL) {
1283*7c356e86SAndroid Build Coastguard Worker 				s->start = s->str = "\n";
1284*7c356e86SAndroid Build Coastguard Worker 				s->type = SEOF;
1285*7c356e86SAndroid Build Coastguard Worker 			} else {
1286*7c356e86SAndroid Build Coastguard Worker 				s->start = s->str = T1space;
1287*7c356e86SAndroid Build Coastguard Worker 				s->type = SWORDS;
1288*7c356e86SAndroid Build Coastguard Worker 			}
1289*7c356e86SAndroid Build Coastguard Worker 			break;
1290*7c356e86SAndroid Build Coastguard Worker 
1291*7c356e86SAndroid Build Coastguard Worker 		case SALIAS:
1292*7c356e86SAndroid Build Coastguard Worker 			if (s->flags & SF_ALIASEND) {
1293*7c356e86SAndroid Build Coastguard Worker 				/* pass on an unused SF_ALIAS flag */
1294*7c356e86SAndroid Build Coastguard Worker 				source = s->next;
1295*7c356e86SAndroid Build Coastguard Worker 				source->flags |= s->flags & SF_ALIAS;
1296*7c356e86SAndroid Build Coastguard Worker 				s = source;
1297*7c356e86SAndroid Build Coastguard Worker 			} else if (*s->u.tblp->val.s &&
1298*7c356e86SAndroid Build Coastguard Worker 			    ctype((c = strnul(s->u.tblp->val.s)[-1]), C_SPACE)) {
1299*7c356e86SAndroid Build Coastguard Worker 				/* pop source stack */
1300*7c356e86SAndroid Build Coastguard Worker 				source = s = s->next;
1301*7c356e86SAndroid Build Coastguard Worker 				/*
1302*7c356e86SAndroid Build Coastguard Worker 				 * Note that this alias ended with a
1303*7c356e86SAndroid Build Coastguard Worker 				 * space, enabling alias expansion on
1304*7c356e86SAndroid Build Coastguard Worker 				 * the following word.
1305*7c356e86SAndroid Build Coastguard Worker 				 */
1306*7c356e86SAndroid Build Coastguard Worker 				s->flags |= SF_ALIAS;
1307*7c356e86SAndroid Build Coastguard Worker 			} else {
1308*7c356e86SAndroid Build Coastguard Worker 				/*
1309*7c356e86SAndroid Build Coastguard Worker 				 * At this point, we need to keep the current
1310*7c356e86SAndroid Build Coastguard Worker 				 * alias in the source list so recursive
1311*7c356e86SAndroid Build Coastguard Worker 				 * aliases can be detected and we also need to
1312*7c356e86SAndroid Build Coastguard Worker 				 * return the next character. Do this by
1313*7c356e86SAndroid Build Coastguard Worker 				 * temporarily popping the alias to get the
1314*7c356e86SAndroid Build Coastguard Worker 				 * next character and then put it back in the
1315*7c356e86SAndroid Build Coastguard Worker 				 * source list with the SF_ALIASEND flag set.
1316*7c356e86SAndroid Build Coastguard Worker 				 */
1317*7c356e86SAndroid Build Coastguard Worker 				/* pop source stack */
1318*7c356e86SAndroid Build Coastguard Worker 				source = s->next;
1319*7c356e86SAndroid Build Coastguard Worker 				source->flags |= s->flags & SF_ALIAS;
1320*7c356e86SAndroid Build Coastguard Worker 				c = getsc_uu();
1321*7c356e86SAndroid Build Coastguard Worker 				if (c) {
1322*7c356e86SAndroid Build Coastguard Worker 					s->flags |= SF_ALIASEND;
1323*7c356e86SAndroid Build Coastguard Worker 					s->ugbuf[0] = c; s->ugbuf[1] = '\0';
1324*7c356e86SAndroid Build Coastguard Worker 					s->start = s->str = s->ugbuf;
1325*7c356e86SAndroid Build Coastguard Worker 					s->next = source;
1326*7c356e86SAndroid Build Coastguard Worker 					source = s;
1327*7c356e86SAndroid Build Coastguard Worker 				} else {
1328*7c356e86SAndroid Build Coastguard Worker 					s = source;
1329*7c356e86SAndroid Build Coastguard Worker 					/* avoid reading EOF twice */
1330*7c356e86SAndroid Build Coastguard Worker 					s->str = NULL;
1331*7c356e86SAndroid Build Coastguard Worker 					break;
1332*7c356e86SAndroid Build Coastguard Worker 				}
1333*7c356e86SAndroid Build Coastguard Worker 			}
1334*7c356e86SAndroid Build Coastguard Worker 			continue;
1335*7c356e86SAndroid Build Coastguard Worker 
1336*7c356e86SAndroid Build Coastguard Worker 		case SREREAD:
1337*7c356e86SAndroid Build Coastguard Worker 			if (s->start != s->ugbuf)
1338*7c356e86SAndroid Build Coastguard Worker 				/* yuck */
1339*7c356e86SAndroid Build Coastguard Worker 				afree(s->u.freeme, ATEMP);
1340*7c356e86SAndroid Build Coastguard Worker 			source = s = s->next;
1341*7c356e86SAndroid Build Coastguard Worker 			continue;
1342*7c356e86SAndroid Build Coastguard Worker 		}
1343*7c356e86SAndroid Build Coastguard Worker 		if (s->str == NULL) {
1344*7c356e86SAndroid Build Coastguard Worker 			s->type = SEOF;
1345*7c356e86SAndroid Build Coastguard Worker 			s->start = s->str = null;
1346*7c356e86SAndroid Build Coastguard Worker 			return ('\0');
1347*7c356e86SAndroid Build Coastguard Worker 		}
1348*7c356e86SAndroid Build Coastguard Worker 		if (s->flags & SF_ECHO) {
1349*7c356e86SAndroid Build Coastguard Worker 			shf_puts(s->str, shl_out);
1350*7c356e86SAndroid Build Coastguard Worker 			shf_flush(shl_out);
1351*7c356e86SAndroid Build Coastguard Worker 		}
1352*7c356e86SAndroid Build Coastguard Worker 	}
1353*7c356e86SAndroid Build Coastguard Worker 	return (c);
1354*7c356e86SAndroid Build Coastguard Worker }
1355*7c356e86SAndroid Build Coastguard Worker 
1356*7c356e86SAndroid Build Coastguard Worker static void
getsc_line(Source * s)1357*7c356e86SAndroid Build Coastguard Worker getsc_line(Source *s)
1358*7c356e86SAndroid Build Coastguard Worker {
1359*7c356e86SAndroid Build Coastguard Worker 	char *xp = Xstring(s->xs, xp), *cp;
1360*7c356e86SAndroid Build Coastguard Worker 	bool interactive = Flag(FTALKING) && s->type == SSTDIN;
1361*7c356e86SAndroid Build Coastguard Worker 	bool have_tty = interactive && (s->flags & SF_TTY) && tty_hasstate;
1362*7c356e86SAndroid Build Coastguard Worker 
1363*7c356e86SAndroid Build Coastguard Worker 	/* Done here to ensure nothing odd happens when a timeout occurs */
1364*7c356e86SAndroid Build Coastguard Worker 	XcheckN(s->xs, xp, LINE);
1365*7c356e86SAndroid Build Coastguard Worker 	*xp = '\0';
1366*7c356e86SAndroid Build Coastguard Worker 	s->start = s->str = xp;
1367*7c356e86SAndroid Build Coastguard Worker 
1368*7c356e86SAndroid Build Coastguard Worker 	if (have_tty && ksh_tmout) {
1369*7c356e86SAndroid Build Coastguard Worker 		ksh_tmout_state = TMOUT_READING;
1370*7c356e86SAndroid Build Coastguard Worker 		alarm(ksh_tmout);
1371*7c356e86SAndroid Build Coastguard Worker 	}
1372*7c356e86SAndroid Build Coastguard Worker 	if (interactive) {
1373*7c356e86SAndroid Build Coastguard Worker 		if (cur_prompt == PS1)
1374*7c356e86SAndroid Build Coastguard Worker 			histsave(&s->line, NULL, HIST_FLUSH, true);
1375*7c356e86SAndroid Build Coastguard Worker 		change_winsz();
1376*7c356e86SAndroid Build Coastguard Worker 	}
1377*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_NO_CMDLINE_EDITING
1378*7c356e86SAndroid Build Coastguard Worker 	if (have_tty && (
1379*7c356e86SAndroid Build Coastguard Worker #if !MKSH_S_NOVI
1380*7c356e86SAndroid Build Coastguard Worker 	    Flag(FVI) ||
1381*7c356e86SAndroid Build Coastguard Worker #endif
1382*7c356e86SAndroid Build Coastguard Worker 	    Flag(FEMACS) || Flag(FGMACS))) {
1383*7c356e86SAndroid Build Coastguard Worker 		int nread;
1384*7c356e86SAndroid Build Coastguard Worker 
1385*7c356e86SAndroid Build Coastguard Worker 		nread = x_read(xp);
1386*7c356e86SAndroid Build Coastguard Worker 		if (nread < 0)
1387*7c356e86SAndroid Build Coastguard Worker 			/* read error */
1388*7c356e86SAndroid Build Coastguard Worker 			nread = 0;
1389*7c356e86SAndroid Build Coastguard Worker 		xp[nread] = '\0';
1390*7c356e86SAndroid Build Coastguard Worker 		xp += nread;
1391*7c356e86SAndroid Build Coastguard Worker 	} else
1392*7c356e86SAndroid Build Coastguard Worker #endif
1393*7c356e86SAndroid Build Coastguard Worker 	  {
1394*7c356e86SAndroid Build Coastguard Worker 		if (interactive)
1395*7c356e86SAndroid Build Coastguard Worker 			pprompt(prompt, 0);
1396*7c356e86SAndroid Build Coastguard Worker 		else
1397*7c356e86SAndroid Build Coastguard Worker 			s->line++;
1398*7c356e86SAndroid Build Coastguard Worker 
1399*7c356e86SAndroid Build Coastguard Worker 		while (/* CONSTCOND */ 1) {
1400*7c356e86SAndroid Build Coastguard Worker 			char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);
1401*7c356e86SAndroid Build Coastguard Worker 
1402*7c356e86SAndroid Build Coastguard Worker 			if (!p && shf_error(s->u.shf) &&
1403*7c356e86SAndroid Build Coastguard Worker 			    shf_errno(s->u.shf) == EINTR) {
1404*7c356e86SAndroid Build Coastguard Worker 				shf_clearerr(s->u.shf);
1405*7c356e86SAndroid Build Coastguard Worker 				if (trap)
1406*7c356e86SAndroid Build Coastguard Worker 					runtraps(0);
1407*7c356e86SAndroid Build Coastguard Worker 				continue;
1408*7c356e86SAndroid Build Coastguard Worker 			}
1409*7c356e86SAndroid Build Coastguard Worker 			if (!p || (xp = p, xp[-1] == '\n'))
1410*7c356e86SAndroid Build Coastguard Worker 				break;
1411*7c356e86SAndroid Build Coastguard Worker 			/* double buffer size */
1412*7c356e86SAndroid Build Coastguard Worker 			/* move past NUL so doubling works... */
1413*7c356e86SAndroid Build Coastguard Worker 			xp++;
1414*7c356e86SAndroid Build Coastguard Worker 			XcheckN(s->xs, xp, Xlength(s->xs, xp));
1415*7c356e86SAndroid Build Coastguard Worker 			/* ...and move back again */
1416*7c356e86SAndroid Build Coastguard Worker 			xp--;
1417*7c356e86SAndroid Build Coastguard Worker 		}
1418*7c356e86SAndroid Build Coastguard Worker 		/*
1419*7c356e86SAndroid Build Coastguard Worker 		 * flush any unwanted input so other programs/builtins
1420*7c356e86SAndroid Build Coastguard Worker 		 * can read it. Not very optimal, but less error prone
1421*7c356e86SAndroid Build Coastguard Worker 		 * than flushing else where, dealing with redirections,
1422*7c356e86SAndroid Build Coastguard Worker 		 * etc.
1423*7c356e86SAndroid Build Coastguard Worker 		 * TODO: reduce size of shf buffer (~128?) if SSTDIN
1424*7c356e86SAndroid Build Coastguard Worker 		 */
1425*7c356e86SAndroid Build Coastguard Worker 		if (s->type == SSTDIN)
1426*7c356e86SAndroid Build Coastguard Worker 			shf_flush(s->u.shf);
1427*7c356e86SAndroid Build Coastguard Worker 	}
1428*7c356e86SAndroid Build Coastguard Worker 	/*
1429*7c356e86SAndroid Build Coastguard Worker 	 * XXX: temporary kludge to restore source after a
1430*7c356e86SAndroid Build Coastguard Worker 	 * trap may have been executed.
1431*7c356e86SAndroid Build Coastguard Worker 	 */
1432*7c356e86SAndroid Build Coastguard Worker 	source = s;
1433*7c356e86SAndroid Build Coastguard Worker 	if (have_tty && ksh_tmout) {
1434*7c356e86SAndroid Build Coastguard Worker 		ksh_tmout_state = TMOUT_EXECUTING;
1435*7c356e86SAndroid Build Coastguard Worker 		alarm(0);
1436*7c356e86SAndroid Build Coastguard Worker 	}
1437*7c356e86SAndroid Build Coastguard Worker 	cp = Xstring(s->xs, xp);
1438*7c356e86SAndroid Build Coastguard Worker 	rndpush(cp);
1439*7c356e86SAndroid Build Coastguard Worker 	s->start = s->str = cp;
1440*7c356e86SAndroid Build Coastguard Worker 	strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
1441*7c356e86SAndroid Build Coastguard Worker 	/* Note: if input is all nulls, this is not eof */
1442*7c356e86SAndroid Build Coastguard Worker 	if (Xlength(s->xs, xp) == 0) {
1443*7c356e86SAndroid Build Coastguard Worker 		/* EOF */
1444*7c356e86SAndroid Build Coastguard Worker 		if (s->type == SFILE)
1445*7c356e86SAndroid Build Coastguard Worker 			shf_fdclose(s->u.shf);
1446*7c356e86SAndroid Build Coastguard Worker 		s->str = NULL;
1447*7c356e86SAndroid Build Coastguard Worker 	} else if (interactive && *s->str) {
1448*7c356e86SAndroid Build Coastguard Worker 		if (cur_prompt != PS1)
1449*7c356e86SAndroid Build Coastguard Worker 			histsave(&s->line, s->str, HIST_APPEND, true);
1450*7c356e86SAndroid Build Coastguard Worker 		else if (!ctype(*s->str, C_IFS | C_IFSWS))
1451*7c356e86SAndroid Build Coastguard Worker 			histsave(&s->line, s->str, HIST_QUEUE, true);
1452*7c356e86SAndroid Build Coastguard Worker #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
1453*7c356e86SAndroid Build Coastguard Worker 		else
1454*7c356e86SAndroid Build Coastguard Worker 			goto check_for_sole_return;
1455*7c356e86SAndroid Build Coastguard Worker 	} else if (interactive && cur_prompt == PS1) {
1456*7c356e86SAndroid Build Coastguard Worker  check_for_sole_return:
1457*7c356e86SAndroid Build Coastguard Worker 		cp = Xstring(s->xs, xp);
1458*7c356e86SAndroid Build Coastguard Worker 		while (ctype(*cp, C_IFSWS))
1459*7c356e86SAndroid Build Coastguard Worker 			++cp;
1460*7c356e86SAndroid Build Coastguard Worker 		if (!*cp) {
1461*7c356e86SAndroid Build Coastguard Worker 			histsave(&s->line, NULL, HIST_FLUSH, true);
1462*7c356e86SAndroid Build Coastguard Worker 			histsync();
1463*7c356e86SAndroid Build Coastguard Worker 		}
1464*7c356e86SAndroid Build Coastguard Worker #endif
1465*7c356e86SAndroid Build Coastguard Worker 	}
1466*7c356e86SAndroid Build Coastguard Worker 	if (interactive)
1467*7c356e86SAndroid Build Coastguard Worker 		set_prompt(PS2, NULL);
1468*7c356e86SAndroid Build Coastguard Worker }
1469*7c356e86SAndroid Build Coastguard Worker 
1470*7c356e86SAndroid Build Coastguard Worker void
set_prompt(int to,Source * s)1471*7c356e86SAndroid Build Coastguard Worker set_prompt(int to, Source *s)
1472*7c356e86SAndroid Build Coastguard Worker {
1473*7c356e86SAndroid Build Coastguard Worker 	cur_prompt = (uint8_t)to;
1474*7c356e86SAndroid Build Coastguard Worker 
1475*7c356e86SAndroid Build Coastguard Worker 	switch (to) {
1476*7c356e86SAndroid Build Coastguard Worker 	/* command */
1477*7c356e86SAndroid Build Coastguard Worker 	case PS1:
1478*7c356e86SAndroid Build Coastguard Worker 		/*
1479*7c356e86SAndroid Build Coastguard Worker 		 * Substitute ! and !! here, before substitutions are done
1480*7c356e86SAndroid Build Coastguard Worker 		 * so ! in expanded variables are not expanded.
1481*7c356e86SAndroid Build Coastguard Worker 		 * NOTE: this is not what AT&T ksh does (it does it after
1482*7c356e86SAndroid Build Coastguard Worker 		 * substitutions, POSIX doesn't say which is to be done.
1483*7c356e86SAndroid Build Coastguard Worker 		 */
1484*7c356e86SAndroid Build Coastguard Worker 		{
1485*7c356e86SAndroid Build Coastguard Worker 			struct shf *shf;
1486*7c356e86SAndroid Build Coastguard Worker 			char * volatile ps1;
1487*7c356e86SAndroid Build Coastguard Worker 			Area *saved_atemp;
1488*7c356e86SAndroid Build Coastguard Worker 			int saved_lineno;
1489*7c356e86SAndroid Build Coastguard Worker 
1490*7c356e86SAndroid Build Coastguard Worker 			ps1 = str_val(global("PS1"));
1491*7c356e86SAndroid Build Coastguard Worker 			shf = shf_sopen(NULL, strlen(ps1) * 2,
1492*7c356e86SAndroid Build Coastguard Worker 			    SHF_WR | SHF_DYNAMIC, NULL);
1493*7c356e86SAndroid Build Coastguard Worker 			while (*ps1)
1494*7c356e86SAndroid Build Coastguard Worker 				if (*ps1 != '!' || *++ps1 == '!')
1495*7c356e86SAndroid Build Coastguard Worker 					shf_putchar(*ps1++, shf);
1496*7c356e86SAndroid Build Coastguard Worker 				else
1497*7c356e86SAndroid Build Coastguard Worker 					shf_fprintf(shf, Tf_lu, s ?
1498*7c356e86SAndroid Build Coastguard Worker 					    (unsigned long)s->line + 1 : 0UL);
1499*7c356e86SAndroid Build Coastguard Worker 			ps1 = shf_sclose(shf);
1500*7c356e86SAndroid Build Coastguard Worker 			saved_lineno = current_lineno;
1501*7c356e86SAndroid Build Coastguard Worker 			if (s)
1502*7c356e86SAndroid Build Coastguard Worker 				current_lineno = s->line + 1;
1503*7c356e86SAndroid Build Coastguard Worker 			saved_atemp = ATEMP;
1504*7c356e86SAndroid Build Coastguard Worker 			newenv(E_ERRH);
1505*7c356e86SAndroid Build Coastguard Worker 			if (kshsetjmp(e->jbuf)) {
1506*7c356e86SAndroid Build Coastguard Worker 				prompt = safe_prompt;
1507*7c356e86SAndroid Build Coastguard Worker 				/*
1508*7c356e86SAndroid Build Coastguard Worker 				 * Don't print an error - assume it has already
1509*7c356e86SAndroid Build Coastguard Worker 				 * been printed. Reason is we may have forked
1510*7c356e86SAndroid Build Coastguard Worker 				 * to run a command and the child may be
1511*7c356e86SAndroid Build Coastguard Worker 				 * unwinding its stack through this code as it
1512*7c356e86SAndroid Build Coastguard Worker 				 * exits.
1513*7c356e86SAndroid Build Coastguard Worker 				 */
1514*7c356e86SAndroid Build Coastguard Worker 			} else {
1515*7c356e86SAndroid Build Coastguard Worker 				char *cp = substitute(ps1, 0);
1516*7c356e86SAndroid Build Coastguard Worker 				strdupx(prompt, cp, saved_atemp);
1517*7c356e86SAndroid Build Coastguard Worker 			}
1518*7c356e86SAndroid Build Coastguard Worker 			current_lineno = saved_lineno;
1519*7c356e86SAndroid Build Coastguard Worker 			quitenv(NULL);
1520*7c356e86SAndroid Build Coastguard Worker 		}
1521*7c356e86SAndroid Build Coastguard Worker 		break;
1522*7c356e86SAndroid Build Coastguard Worker 	/* command continuation */
1523*7c356e86SAndroid Build Coastguard Worker 	case PS2:
1524*7c356e86SAndroid Build Coastguard Worker 		prompt = str_val(global("PS2"));
1525*7c356e86SAndroid Build Coastguard Worker 		break;
1526*7c356e86SAndroid Build Coastguard Worker 	}
1527*7c356e86SAndroid Build Coastguard Worker }
1528*7c356e86SAndroid Build Coastguard Worker 
1529*7c356e86SAndroid Build Coastguard Worker int
pprompt(const char * cp,int ntruncate)1530*7c356e86SAndroid Build Coastguard Worker pprompt(const char *cp, int ntruncate)
1531*7c356e86SAndroid Build Coastguard Worker {
1532*7c356e86SAndroid Build Coastguard Worker 	char delimiter = 0;
1533*7c356e86SAndroid Build Coastguard Worker 	bool doprint = (ntruncate != -1);
1534*7c356e86SAndroid Build Coastguard Worker 	bool indelimit = false;
1535*7c356e86SAndroid Build Coastguard Worker 	int columns = 0, lines = 0;
1536*7c356e86SAndroid Build Coastguard Worker 
1537*7c356e86SAndroid Build Coastguard Worker 	/*
1538*7c356e86SAndroid Build Coastguard Worker 	 * Undocumented AT&T ksh feature:
1539*7c356e86SAndroid Build Coastguard Worker 	 * If the second char in the prompt string is \r then the first
1540*7c356e86SAndroid Build Coastguard Worker 	 * char is taken to be a non-printing delimiter and any chars
1541*7c356e86SAndroid Build Coastguard Worker 	 * between two instances of the delimiter are not considered to
1542*7c356e86SAndroid Build Coastguard Worker 	 * be part of the prompt length
1543*7c356e86SAndroid Build Coastguard Worker 	 */
1544*7c356e86SAndroid Build Coastguard Worker 	if (*cp && cp[1] == '\r') {
1545*7c356e86SAndroid Build Coastguard Worker 		delimiter = *cp;
1546*7c356e86SAndroid Build Coastguard Worker 		cp += 2;
1547*7c356e86SAndroid Build Coastguard Worker 	}
1548*7c356e86SAndroid Build Coastguard Worker 	for (; *cp; cp++) {
1549*7c356e86SAndroid Build Coastguard Worker 		if (indelimit && *cp != delimiter)
1550*7c356e86SAndroid Build Coastguard Worker 			;
1551*7c356e86SAndroid Build Coastguard Worker 		else if (ctype(*cp, C_CR | C_LF)) {
1552*7c356e86SAndroid Build Coastguard Worker 			lines += columns / x_cols + ((*cp == '\n') ? 1 : 0);
1553*7c356e86SAndroid Build Coastguard Worker 			columns = 0;
1554*7c356e86SAndroid Build Coastguard Worker 		} else if (*cp == '\t') {
1555*7c356e86SAndroid Build Coastguard Worker 			columns = (columns | 7) + 1;
1556*7c356e86SAndroid Build Coastguard Worker 		} else if (*cp == '\b') {
1557*7c356e86SAndroid Build Coastguard Worker 			if (columns > 0)
1558*7c356e86SAndroid Build Coastguard Worker 				columns--;
1559*7c356e86SAndroid Build Coastguard Worker 		} else if (*cp == delimiter)
1560*7c356e86SAndroid Build Coastguard Worker 			indelimit = !indelimit;
1561*7c356e86SAndroid Build Coastguard Worker 		else if (UTFMODE && (rtt2asc(*cp) > 0x7F)) {
1562*7c356e86SAndroid Build Coastguard Worker 			const char *cp2;
1563*7c356e86SAndroid Build Coastguard Worker 			columns += utf_widthadj(cp, &cp2);
1564*7c356e86SAndroid Build Coastguard Worker 			if (doprint && (indelimit ||
1565*7c356e86SAndroid Build Coastguard Worker 			    (ntruncate < (x_cols * lines + columns))))
1566*7c356e86SAndroid Build Coastguard Worker 				shf_write(cp, cp2 - cp, shl_out);
1567*7c356e86SAndroid Build Coastguard Worker 			cp = cp2 - /* loop increment */ 1;
1568*7c356e86SAndroid Build Coastguard Worker 			continue;
1569*7c356e86SAndroid Build Coastguard Worker 		} else
1570*7c356e86SAndroid Build Coastguard Worker 			columns++;
1571*7c356e86SAndroid Build Coastguard Worker 		if (doprint && (*cp != delimiter) &&
1572*7c356e86SAndroid Build Coastguard Worker 		    (indelimit || (ntruncate < (x_cols * lines + columns))))
1573*7c356e86SAndroid Build Coastguard Worker 			shf_putc(*cp, shl_out);
1574*7c356e86SAndroid Build Coastguard Worker 	}
1575*7c356e86SAndroid Build Coastguard Worker 	if (doprint)
1576*7c356e86SAndroid Build Coastguard Worker 		shf_flush(shl_out);
1577*7c356e86SAndroid Build Coastguard Worker 	return (x_cols * lines + columns);
1578*7c356e86SAndroid Build Coastguard Worker }
1579*7c356e86SAndroid Build Coastguard Worker 
1580*7c356e86SAndroid Build Coastguard Worker /*
1581*7c356e86SAndroid Build Coastguard Worker  * Read the variable part of a ${...} expression (i.e. up to but not
1582*7c356e86SAndroid Build Coastguard Worker  * including the :[-+?=#%] or close-brace).
1583*7c356e86SAndroid Build Coastguard Worker  */
1584*7c356e86SAndroid Build Coastguard Worker static char *
get_brace_var(XString * wsp,char * wp)1585*7c356e86SAndroid Build Coastguard Worker get_brace_var(XString *wsp, char *wp)
1586*7c356e86SAndroid Build Coastguard Worker {
1587*7c356e86SAndroid Build Coastguard Worker 	char c;
1588*7c356e86SAndroid Build Coastguard Worker 	enum parse_state {
1589*7c356e86SAndroid Build Coastguard Worker 		PS_INITIAL, PS_SAW_PERCENT, PS_SAW_HASH, PS_SAW_BANG,
1590*7c356e86SAndroid Build Coastguard Worker 		PS_IDENT, PS_NUMBER, PS_VAR1
1591*7c356e86SAndroid Build Coastguard Worker 	} state = PS_INITIAL;
1592*7c356e86SAndroid Build Coastguard Worker 
1593*7c356e86SAndroid Build Coastguard Worker 	while (/* CONSTCOND */ 1) {
1594*7c356e86SAndroid Build Coastguard Worker 		c = getsc();
1595*7c356e86SAndroid Build Coastguard Worker 		/* State machine to figure out where the variable part ends. */
1596*7c356e86SAndroid Build Coastguard Worker 		switch (state) {
1597*7c356e86SAndroid Build Coastguard Worker 		case PS_SAW_HASH:
1598*7c356e86SAndroid Build Coastguard Worker 			if (ctype(c, C_VAR1)) {
1599*7c356e86SAndroid Build Coastguard Worker 				char c2;
1600*7c356e86SAndroid Build Coastguard Worker 
1601*7c356e86SAndroid Build Coastguard Worker 				c2 = getsc();
1602*7c356e86SAndroid Build Coastguard Worker 				ungetsc(c2);
1603*7c356e86SAndroid Build Coastguard Worker 				if (ord(c2) != ORD(/*{*/ '}')) {
1604*7c356e86SAndroid Build Coastguard Worker 					ungetsc(c);
1605*7c356e86SAndroid Build Coastguard Worker 					goto out;
1606*7c356e86SAndroid Build Coastguard Worker 				}
1607*7c356e86SAndroid Build Coastguard Worker 			}
1608*7c356e86SAndroid Build Coastguard Worker 			goto ps_common;
1609*7c356e86SAndroid Build Coastguard Worker 		case PS_SAW_BANG:
1610*7c356e86SAndroid Build Coastguard Worker 			switch (ord(c)) {
1611*7c356e86SAndroid Build Coastguard Worker 			case ORD('@'):
1612*7c356e86SAndroid Build Coastguard Worker 			case ORD('#'):
1613*7c356e86SAndroid Build Coastguard Worker 			case ORD('-'):
1614*7c356e86SAndroid Build Coastguard Worker 			case ORD('?'):
1615*7c356e86SAndroid Build Coastguard Worker 				goto out;
1616*7c356e86SAndroid Build Coastguard Worker 			}
1617*7c356e86SAndroid Build Coastguard Worker 			goto ps_common;
1618*7c356e86SAndroid Build Coastguard Worker 		case PS_INITIAL:
1619*7c356e86SAndroid Build Coastguard Worker 			switch (ord(c)) {
1620*7c356e86SAndroid Build Coastguard Worker 			case ORD('%'):
1621*7c356e86SAndroid Build Coastguard Worker 				state = PS_SAW_PERCENT;
1622*7c356e86SAndroid Build Coastguard Worker 				goto next;
1623*7c356e86SAndroid Build Coastguard Worker 			case ORD('#'):
1624*7c356e86SAndroid Build Coastguard Worker 				state = PS_SAW_HASH;
1625*7c356e86SAndroid Build Coastguard Worker 				goto next;
1626*7c356e86SAndroid Build Coastguard Worker 			case ORD('!'):
1627*7c356e86SAndroid Build Coastguard Worker 				state = PS_SAW_BANG;
1628*7c356e86SAndroid Build Coastguard Worker 				goto next;
1629*7c356e86SAndroid Build Coastguard Worker 			}
1630*7c356e86SAndroid Build Coastguard Worker 			/* FALLTHROUGH */
1631*7c356e86SAndroid Build Coastguard Worker 		case PS_SAW_PERCENT:
1632*7c356e86SAndroid Build Coastguard Worker  ps_common:
1633*7c356e86SAndroid Build Coastguard Worker 			if (ctype(c, C_ALPHX))
1634*7c356e86SAndroid Build Coastguard Worker 				state = PS_IDENT;
1635*7c356e86SAndroid Build Coastguard Worker 			else if (ctype(c, C_DIGIT))
1636*7c356e86SAndroid Build Coastguard Worker 				state = PS_NUMBER;
1637*7c356e86SAndroid Build Coastguard Worker 			else if (ctype(c, C_VAR1))
1638*7c356e86SAndroid Build Coastguard Worker 				state = PS_VAR1;
1639*7c356e86SAndroid Build Coastguard Worker 			else
1640*7c356e86SAndroid Build Coastguard Worker 				goto out;
1641*7c356e86SAndroid Build Coastguard Worker 			break;
1642*7c356e86SAndroid Build Coastguard Worker 		case PS_IDENT:
1643*7c356e86SAndroid Build Coastguard Worker 			if (!ctype(c, C_ALNUX)) {
1644*7c356e86SAndroid Build Coastguard Worker 				if (ord(c) == ORD('[')) {
1645*7c356e86SAndroid Build Coastguard Worker 					char *tmp, *p;
1646*7c356e86SAndroid Build Coastguard Worker 
1647*7c356e86SAndroid Build Coastguard Worker 					if (!arraysub(&tmp))
1648*7c356e86SAndroid Build Coastguard Worker 						yyerror("missing ]");
1649*7c356e86SAndroid Build Coastguard Worker 					*wp++ = c;
1650*7c356e86SAndroid Build Coastguard Worker 					p = tmp;
1651*7c356e86SAndroid Build Coastguard Worker 					while (*p) {
1652*7c356e86SAndroid Build Coastguard Worker 						Xcheck(*wsp, wp);
1653*7c356e86SAndroid Build Coastguard Worker 						*wp++ = *p++;
1654*7c356e86SAndroid Build Coastguard Worker 					}
1655*7c356e86SAndroid Build Coastguard Worker 					afree(tmp, ATEMP);
1656*7c356e86SAndroid Build Coastguard Worker 					/* the ] */
1657*7c356e86SAndroid Build Coastguard Worker 					c = getsc();
1658*7c356e86SAndroid Build Coastguard Worker 				}
1659*7c356e86SAndroid Build Coastguard Worker 				goto out;
1660*7c356e86SAndroid Build Coastguard Worker 			}
1661*7c356e86SAndroid Build Coastguard Worker  next:
1662*7c356e86SAndroid Build Coastguard Worker 			break;
1663*7c356e86SAndroid Build Coastguard Worker 		case PS_NUMBER:
1664*7c356e86SAndroid Build Coastguard Worker 			if (!ctype(c, C_DIGIT))
1665*7c356e86SAndroid Build Coastguard Worker 				goto out;
1666*7c356e86SAndroid Build Coastguard Worker 			break;
1667*7c356e86SAndroid Build Coastguard Worker 		case PS_VAR1:
1668*7c356e86SAndroid Build Coastguard Worker 			goto out;
1669*7c356e86SAndroid Build Coastguard Worker 		}
1670*7c356e86SAndroid Build Coastguard Worker 		Xcheck(*wsp, wp);
1671*7c356e86SAndroid Build Coastguard Worker 		*wp++ = c;
1672*7c356e86SAndroid Build Coastguard Worker 	}
1673*7c356e86SAndroid Build Coastguard Worker  out:
1674*7c356e86SAndroid Build Coastguard Worker 	/* end of variable part */
1675*7c356e86SAndroid Build Coastguard Worker 	*wp++ = '\0';
1676*7c356e86SAndroid Build Coastguard Worker 	ungetsc(c);
1677*7c356e86SAndroid Build Coastguard Worker 	return (wp);
1678*7c356e86SAndroid Build Coastguard Worker }
1679*7c356e86SAndroid Build Coastguard Worker 
1680*7c356e86SAndroid Build Coastguard Worker /*
1681*7c356e86SAndroid Build Coastguard Worker  * Save an array subscript - returns true if matching bracket found, false
1682*7c356e86SAndroid Build Coastguard Worker  * if eof or newline was found.
1683*7c356e86SAndroid Build Coastguard Worker  * (Returned string double null terminated)
1684*7c356e86SAndroid Build Coastguard Worker  */
1685*7c356e86SAndroid Build Coastguard Worker static bool
arraysub(char ** strp)1686*7c356e86SAndroid Build Coastguard Worker arraysub(char **strp)
1687*7c356e86SAndroid Build Coastguard Worker {
1688*7c356e86SAndroid Build Coastguard Worker 	XString ws;
1689*7c356e86SAndroid Build Coastguard Worker 	char *wp, c;
1690*7c356e86SAndroid Build Coastguard Worker 	/* we are just past the initial [ */
1691*7c356e86SAndroid Build Coastguard Worker 	unsigned int depth = 1;
1692*7c356e86SAndroid Build Coastguard Worker 
1693*7c356e86SAndroid Build Coastguard Worker 	Xinit(ws, wp, 32, ATEMP);
1694*7c356e86SAndroid Build Coastguard Worker 
1695*7c356e86SAndroid Build Coastguard Worker 	do {
1696*7c356e86SAndroid Build Coastguard Worker 		c = getsc();
1697*7c356e86SAndroid Build Coastguard Worker 		Xcheck(ws, wp);
1698*7c356e86SAndroid Build Coastguard Worker 		*wp++ = c;
1699*7c356e86SAndroid Build Coastguard Worker 		if (ord(c) == ORD('['))
1700*7c356e86SAndroid Build Coastguard Worker 			depth++;
1701*7c356e86SAndroid Build Coastguard Worker 		else if (ord(c) == ORD(']'))
1702*7c356e86SAndroid Build Coastguard Worker 			depth--;
1703*7c356e86SAndroid Build Coastguard Worker 	} while (depth > 0 && c && c != '\n');
1704*7c356e86SAndroid Build Coastguard Worker 
1705*7c356e86SAndroid Build Coastguard Worker 	*wp++ = '\0';
1706*7c356e86SAndroid Build Coastguard Worker 	*strp = Xclose(ws, wp);
1707*7c356e86SAndroid Build Coastguard Worker 
1708*7c356e86SAndroid Build Coastguard Worker 	return (tobool(depth == 0));
1709*7c356e86SAndroid Build Coastguard Worker }
1710*7c356e86SAndroid Build Coastguard Worker 
1711*7c356e86SAndroid Build Coastguard Worker /* Unget a char: handles case when we are already at the start of the buffer */
1712*7c356e86SAndroid Build Coastguard Worker static void
ungetsc(int c)1713*7c356e86SAndroid Build Coastguard Worker ungetsc(int c)
1714*7c356e86SAndroid Build Coastguard Worker {
1715*7c356e86SAndroid Build Coastguard Worker 	struct sretrace_info *rp = retrace_info;
1716*7c356e86SAndroid Build Coastguard Worker 
1717*7c356e86SAndroid Build Coastguard Worker 	if (backslash_skip)
1718*7c356e86SAndroid Build Coastguard Worker 		backslash_skip--;
1719*7c356e86SAndroid Build Coastguard Worker 	/* Don't unget EOF... */
1720*7c356e86SAndroid Build Coastguard Worker 	if (source->str == null && c == '\0')
1721*7c356e86SAndroid Build Coastguard Worker 		return;
1722*7c356e86SAndroid Build Coastguard Worker 	while (rp) {
1723*7c356e86SAndroid Build Coastguard Worker 		if (Xlength(rp->xs, rp->xp))
1724*7c356e86SAndroid Build Coastguard Worker 			rp->xp--;
1725*7c356e86SAndroid Build Coastguard Worker 		rp = rp->next;
1726*7c356e86SAndroid Build Coastguard Worker 	}
1727*7c356e86SAndroid Build Coastguard Worker 	ungetsc_i(c);
1728*7c356e86SAndroid Build Coastguard Worker }
1729*7c356e86SAndroid Build Coastguard Worker static void
ungetsc_i(int c)1730*7c356e86SAndroid Build Coastguard Worker ungetsc_i(int c)
1731*7c356e86SAndroid Build Coastguard Worker {
1732*7c356e86SAndroid Build Coastguard Worker 	if (source->str > source->start)
1733*7c356e86SAndroid Build Coastguard Worker 		source->str--;
1734*7c356e86SAndroid Build Coastguard Worker 	else {
1735*7c356e86SAndroid Build Coastguard Worker 		Source *s;
1736*7c356e86SAndroid Build Coastguard Worker 
1737*7c356e86SAndroid Build Coastguard Worker 		s = pushs(SREREAD, source->areap);
1738*7c356e86SAndroid Build Coastguard Worker 		s->ugbuf[0] = c; s->ugbuf[1] = '\0';
1739*7c356e86SAndroid Build Coastguard Worker 		s->start = s->str = s->ugbuf;
1740*7c356e86SAndroid Build Coastguard Worker 		s->next = source;
1741*7c356e86SAndroid Build Coastguard Worker 		source = s;
1742*7c356e86SAndroid Build Coastguard Worker 	}
1743*7c356e86SAndroid Build Coastguard Worker }
1744*7c356e86SAndroid Build Coastguard Worker 
1745*7c356e86SAndroid Build Coastguard Worker 
1746*7c356e86SAndroid Build Coastguard Worker /* Called to get a char that isn't a \newline sequence. */
1747*7c356e86SAndroid Build Coastguard Worker static int
getsc_bn(void)1748*7c356e86SAndroid Build Coastguard Worker getsc_bn(void)
1749*7c356e86SAndroid Build Coastguard Worker {
1750*7c356e86SAndroid Build Coastguard Worker 	int c, c2;
1751*7c356e86SAndroid Build Coastguard Worker 
1752*7c356e86SAndroid Build Coastguard Worker 	if (ignore_backslash_newline)
1753*7c356e86SAndroid Build Coastguard Worker 		return (o_getsc_u());
1754*7c356e86SAndroid Build Coastguard Worker 
1755*7c356e86SAndroid Build Coastguard Worker 	if (backslash_skip == 1) {
1756*7c356e86SAndroid Build Coastguard Worker 		backslash_skip = 2;
1757*7c356e86SAndroid Build Coastguard Worker 		return (o_getsc_u());
1758*7c356e86SAndroid Build Coastguard Worker 	}
1759*7c356e86SAndroid Build Coastguard Worker 
1760*7c356e86SAndroid Build Coastguard Worker 	backslash_skip = 0;
1761*7c356e86SAndroid Build Coastguard Worker 
1762*7c356e86SAndroid Build Coastguard Worker 	while (/* CONSTCOND */ 1) {
1763*7c356e86SAndroid Build Coastguard Worker 		c = o_getsc_u();
1764*7c356e86SAndroid Build Coastguard Worker 		if (c == '\\') {
1765*7c356e86SAndroid Build Coastguard Worker 			if ((c2 = o_getsc_u()) == '\n')
1766*7c356e86SAndroid Build Coastguard Worker 				/* ignore the \newline; get the next char... */
1767*7c356e86SAndroid Build Coastguard Worker 				continue;
1768*7c356e86SAndroid Build Coastguard Worker 			ungetsc_i(c2);
1769*7c356e86SAndroid Build Coastguard Worker 			backslash_skip = 1;
1770*7c356e86SAndroid Build Coastguard Worker 		}
1771*7c356e86SAndroid Build Coastguard Worker 		return (c);
1772*7c356e86SAndroid Build Coastguard Worker 	}
1773*7c356e86SAndroid Build Coastguard Worker }
1774*7c356e86SAndroid Build Coastguard Worker 
1775*7c356e86SAndroid Build Coastguard Worker void
yyskiputf8bom(void)1776*7c356e86SAndroid Build Coastguard Worker yyskiputf8bom(void)
1777*7c356e86SAndroid Build Coastguard Worker {
1778*7c356e86SAndroid Build Coastguard Worker 	int c;
1779*7c356e86SAndroid Build Coastguard Worker 
1780*7c356e86SAndroid Build Coastguard Worker 	if (rtt2asc((c = o_getsc_u())) != 0xEF) {
1781*7c356e86SAndroid Build Coastguard Worker 		ungetsc_i(c);
1782*7c356e86SAndroid Build Coastguard Worker 		return;
1783*7c356e86SAndroid Build Coastguard Worker 	}
1784*7c356e86SAndroid Build Coastguard Worker 	if (rtt2asc((c = o_getsc_u())) != 0xBB) {
1785*7c356e86SAndroid Build Coastguard Worker 		ungetsc_i(c);
1786*7c356e86SAndroid Build Coastguard Worker 		ungetsc_i(asc2rtt(0xEF));
1787*7c356e86SAndroid Build Coastguard Worker 		return;
1788*7c356e86SAndroid Build Coastguard Worker 	}
1789*7c356e86SAndroid Build Coastguard Worker 	if (rtt2asc((c = o_getsc_u())) != 0xBF) {
1790*7c356e86SAndroid Build Coastguard Worker 		ungetsc_i(c);
1791*7c356e86SAndroid Build Coastguard Worker 		ungetsc_i(asc2rtt(0xBB));
1792*7c356e86SAndroid Build Coastguard Worker 		ungetsc_i(asc2rtt(0xEF));
1793*7c356e86SAndroid Build Coastguard Worker 		return;
1794*7c356e86SAndroid Build Coastguard Worker 	}
1795*7c356e86SAndroid Build Coastguard Worker 	UTFMODE |= 8;
1796*7c356e86SAndroid Build Coastguard Worker }
1797*7c356e86SAndroid Build Coastguard Worker 
1798*7c356e86SAndroid Build Coastguard Worker static Lex_state *
push_state_i(State_info * si,Lex_state * old_end)1799*7c356e86SAndroid Build Coastguard Worker push_state_i(State_info *si, Lex_state *old_end)
1800*7c356e86SAndroid Build Coastguard Worker {
1801*7c356e86SAndroid Build Coastguard Worker 	Lex_state *news = alloc2(STATE_BSIZE, sizeof(Lex_state), ATEMP);
1802*7c356e86SAndroid Build Coastguard Worker 
1803*7c356e86SAndroid Build Coastguard Worker 	news[0].ls_base = old_end;
1804*7c356e86SAndroid Build Coastguard Worker 	si->base = &news[0];
1805*7c356e86SAndroid Build Coastguard Worker 	si->end = &news[STATE_BSIZE];
1806*7c356e86SAndroid Build Coastguard Worker 	return (&news[1]);
1807*7c356e86SAndroid Build Coastguard Worker }
1808*7c356e86SAndroid Build Coastguard Worker 
1809*7c356e86SAndroid Build Coastguard Worker static Lex_state *
pop_state_i(State_info * si,Lex_state * old_end)1810*7c356e86SAndroid Build Coastguard Worker pop_state_i(State_info *si, Lex_state *old_end)
1811*7c356e86SAndroid Build Coastguard Worker {
1812*7c356e86SAndroid Build Coastguard Worker 	Lex_state *old_base = si->base;
1813*7c356e86SAndroid Build Coastguard Worker 
1814*7c356e86SAndroid Build Coastguard Worker 	si->base = old_end->ls_base - STATE_BSIZE;
1815*7c356e86SAndroid Build Coastguard Worker 	si->end = old_end->ls_base;
1816*7c356e86SAndroid Build Coastguard Worker 
1817*7c356e86SAndroid Build Coastguard Worker 	afree(old_base, ATEMP);
1818*7c356e86SAndroid Build Coastguard Worker 
1819*7c356e86SAndroid Build Coastguard Worker 	return (si->base + STATE_BSIZE - 1);
1820*7c356e86SAndroid Build Coastguard Worker }
1821