1427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes/*	$OpenBSD: lex.c,v 1.49 2013/12/17 16:37:06 deraadt Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
4c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes *		 2011, 2012, 2013, 2014
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Thorsten Glaser <tg@mirbsd.org>
75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193 2014/06/29 11:28:28 tg Exp $");
275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * states while lexing word
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SBASE		0	/* outside any lexical constructs */
325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SWORD		1	/* implicit quoting for substitute() */
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SLETPAREN	2	/* inside (( )), implicit quoting */
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SSQUOTE		3	/* inside '' */
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SDQUOTE		4	/* inside "" */
365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SEQUOTE		5	/* inside $'' */
375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SBRACE		6	/* inside ${} */
385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SQBRACE		7	/* inside "${}" */
3903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define SBQUOTE		8	/* inside `` */
4003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define SASPAREN	9	/* inside $(( )) */
41c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define SHEREDELIM	10	/* parsing <<,<<-,<<< delimiter */
42c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define SHEREDQUOTE	11	/* parsing " in <<,<<-,<<< delimiter */
4303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define SPATTERN	12	/* parsing *(...|...) pattern (*+?@!) */
4403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define SADELIM		13	/* like SBASE, looking for delimiter */
45c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define STBRACEKORN	14	/* parsing ${...[#%]...} !FSH */
46c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define STBRACEBOURNE	15	/* parsing ${...[#%]...} FSH */
4703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define SINVALID	255	/* invalid state */
4803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
4903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastruct sretrace_info {
5003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct sretrace_info *next;
5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	XString xs;
5203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *xp;
5303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra};
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
5603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Structure to keep track of the lexing state and the various pieces of info
5703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * needed for each particular state.
5803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */
5903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condratypedef struct lex_state {
6003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	union {
6103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* point to the next state block */
6203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		struct lex_state *base;
6303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* marks start of state output in output string */
6403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		int start;
6503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* SBQUOTE: true if in double quotes: "`...`" */
6603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* SEQUOTE: got NUL, ignore rest of string */
6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bool abool;
6803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* SADELIM information */
6903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		struct {
7003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* character to search for */
715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char delimiter;
7203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* max. number of delimiters */
735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char num;
7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} adelim;
7503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} u;
7603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* count open parentheses */
7703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	short nparen;
7803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* type of this state */
7903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	uint8_t type;
8003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} Lex_state;
8103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define ls_base		u.base
8203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define ls_start	u.start
8303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define ls_bool		u.abool
8403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define ls_adelim	u.adelim
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutypedef struct {
875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *base;
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *end;
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} State_info;
905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void readhere(struct ioword *);
9203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void ungetsc(int);
93c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void ungetsc_i(int);
9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int getsc_uu(void);
955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void getsc_line(Source *);
965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getsc_bn(void);
975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int s_get(void);
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void s_put(int);
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *get_brace_var(XString *, char *);
10003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic bool arraysub(char **);
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void gethere(bool);
102c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic Lex_state *push_state_i(State_info *, Lex_state *);
103c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic Lex_state *pop_state_i(State_info *, Lex_state *);
1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int backslash_skip;
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int ignore_backslash_newline;
1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* optimised getsc_bn() */
10903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define o_getsc()	(*source->str != '\0' && *source->str != '\\' && \
11003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    !backslash_skip ? *source->str++ : getsc_bn())
11103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* optimised getsc_uu() */
11203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define	o_getsc_u()	((*source->str != '\0') ? *source->str++ : getsc_uu())
11303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
11403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* retrace helper */
11503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define o_getsc_r(carg)	{				\
11603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int cev = (carg);				\
11703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct sretrace_info *rp = retrace_info;	\
11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							\
11903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (rp) {					\
12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(rp->xs, rp->xp);			\
12103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		*rp->xp++ = cev;			\
12203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rp = rp->next;				\
12303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}						\
12403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							\
12503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (cev);					\
12603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
128c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getsc(void);
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc(void)
1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	o_getsc_r(o_getsc());
1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
13703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int getsc_r(int);
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
14003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condragetsc_r(int c)
1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	o_getsc_r(c);
1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
14503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define getsc()		getsc_r(o_getsc())
1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define STATE_BSIZE	8
1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PUSH_STATE(s)	do {					\
1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (++statep == state_info.end)				\
152c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		statep = push_state_i(&state_info, statep);	\
15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	state = statep->type = (s);				\
15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} while (/* CONSTCOND */ 0)
1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define POP_STATE()	do {					\
1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (--statep == state_info.base)			\
158c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		statep = pop_state_i(&state_info, statep);	\
15903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	state = statep->type;					\
16003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} while (/* CONSTCOND */ 0)
16103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
162427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#define PUSH_SRETRACE(s) do {					\
16303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct sretrace_info *ri;				\
16403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra								\
165427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	PUSH_STATE(s);						\
16603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	statep->ls_start = Xsavepos(ws, wp);			\
16703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ri = alloc(sizeof(struct sretrace_info), ATEMP);	\
16803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xinit(ri->xs, ri->xp, 64, ATEMP);			\
16903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ri->next = retrace_info;				\
17003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	retrace_info = ri;					\
17103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} while (/* CONSTCOND */ 0)
17203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
17303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define POP_SRETRACE()	do {					\
17403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	wp = Xrestpos(ws, wp, statep->ls_start);		\
17503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	*retrace_info->xp = '\0';				\
17603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	sp = Xstring(retrace_info->xs, retrace_info->xp);	\
17703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	dp = (void *)retrace_info;				\
17803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	retrace_info = retrace_info->next;			\
17903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(dp, ATEMP);					\
180427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	POP_STATE();						\
18103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} while (/* CONSTCOND */ 0)
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/**
1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Lexical analyser
1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * tokens are not regular expressions, they are LL(1).
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * for example, "${var:-${PWD}}", and "$(size $(whence ksh))".
18803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * hence the state stack. Note "$(...)" are now parsed recursively.
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruyylex(int cf)
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state states[STATE_BSIZE], *statep, *s2, *base;
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	State_info state_info;
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c, c2, state;
19703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t cz;
1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString ws;		/* expandable output word */
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *wp;		/* output word pointer */
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *sp, *dp;
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Again:
20303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	states[0].type = SINVALID;
20403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	states[0].ls_base = NULL;
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	statep = &states[1];
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state_info.base = states;
2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state_info.end = &state_info.base[STATE_BSIZE];
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(ws, wp, 64, ATEMP);
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	backslash_skip = 0;
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ignore_backslash_newline = 0;
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (cf & ONEWORD)
2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SWORD;
21603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (cf & LETEXPR) {
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* enclose arguments in (double) quotes */
2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*wp++ = OQUOTE;
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SLETPAREN;
22003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		statep->nparen = 0;
22103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else {
22203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* normal lexing */
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((c = getsc()) == ' ' || c == '\t')
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '#') {
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ignore_backslash_newline++;
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((c = getsc()) != '\0' && c != '\n')
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ignore_backslash_newline--;
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ungetsc(c);
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (source->flags & SF_ALIAS) {
23503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* trailing ' ' in alias definition */
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source->flags &= ~SF_ALIAS;
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cf |= ALIAS;
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */
24103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	statep->type = state;
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* check for here string */
2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (state == SHEREDELIM) {
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc();
2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '<') {
247c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			state = SHEREDELIM;
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((c = getsc()) == ' ' || c == '\t')
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ungetsc(c);
2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c = '<';
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto accept_nonword;
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ungetsc(c);
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* collect non-special or quoted characters to form word */
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (!((c = getsc()) == 0 ||
259c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    ((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
260c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (state == SBASE &&
261c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    subshell_nesting_type == /*{*/ '}' &&
262c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    c == /*{*/ '}')
263c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* possibly end ${ :;} */
264c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			break;
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru accept_nonword:
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(ws, wp);
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (state) {
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SADELIM:
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '(')
27003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				statep->nparen++;
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == ')')
27203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				statep->nparen--;
273c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			else if (statep->nparen == 0 && (c == /*{*/ '}' ||
274c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			    c == (int)statep->ls_adelim.delimiter)) {
2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = ADELIM;
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
27703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (c == /*{*/ '}' || --statep->ls_adelim.num == 0)
2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					POP_STATE();
2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == /*{*/ '}')
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					POP_STATE();
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SBASE:
2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
28603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* temporary */
28703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				*wp = EOS;
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (is_wdvarname(Xstring(ws, wp), false)) {
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char *p, *tmp;
2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (arraysub(&tmp)) {
2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						for (p = tmp; *p; ) {
2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							Xcheck(ws, wp);
2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = CHAR;
2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = *p++;
2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						afree(tmp, ATEMP);
3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Source *s;
3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s = pushs(SREREAD,
3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    source->areap);
3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s->start = s->str =
3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    s->u.freeme = tmp;
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s->next = source;
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						source = s;
3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sbase1:		/* includes *(...|...) pattern (*+?@!) */
3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '*' || c == '@' || c == '+' || c == '?' ||
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    c == '!') {
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c2 = getsc();
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c2 == '(' /*)*/ ) {
3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OPAT;
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					PUSH_STATE(SPATTERN);
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sbase2:		/* doesn't include *(...|...) pattern (*+?@!) */
3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (c) {
3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '\\':
3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru getsc_qchar:
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c = getsc())) {
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* trailing \ is lost */
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '\'':
341811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser open_ssquote_unless_heredoc:
342811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser				if ((cf & HEREDOC))
343811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser					goto store_char;
3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline++;
3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SSQUOTE);
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '"':
3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru open_sdquote:
3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SDQUOTE);
3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
353c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			case '$':
354c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				/*
355c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				 * processing of dollar sign belongs into
356c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				 * Subst, except for those which can open
357c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				 * a string: $'…' and $"…"
358c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				 */
359c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subst_dollar_ex:
360c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				c = getsc();
361c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				switch (c) {
362c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				case '"':
363c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					goto open_sdquote;
364c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				case '\'':
365c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					goto open_sequote;
366c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				default:
367c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					goto SubstS;
368c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				}
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			default:
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Subst;
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Subst:
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (c) {
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '\\':
3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc();
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (c) {
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '"':
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if ((cf & HEREDOC))
3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						goto heredocquote;
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* FALLTHROUGH */
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '\\':
3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '$': case '`':
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru store_qchar:
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				default:
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru heredocquote:
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					Xcheck(ws, wp);
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c) {
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* trailing \ is lost */
3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = '\\';
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '$':
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc();
404c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser SubstS:
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '(') /*)*/ {
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = getsc();
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c == '(') /*)*/ {
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = EXPRSUB;
409427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes						PUSH_SRETRACE(SASPAREN);
41003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						statep->nparen = 2;
41103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						*retrace_info->xp++ = '(';
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c);
41403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra subst_command:
415c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						c = COMSUB;
416c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subst_command2:
417c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						sp = yyrecursive(c);
41803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						cz = strlen(sp) + 1;
41903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						XcheckN(ws, wp, cz);
420c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						*wp++ = c;
42103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						memcpy(wp, sp, cz);
42203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						wp += cz;
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (c == '{') /*}*/ {
425811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser					if ((c = getsc()) == '|') {
426811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						/*
427811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						 * non-subenvironment
428811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						 * value substitution
429811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						 */
430811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						c = VALSUB;
431811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						goto subst_command2;
432811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser					} else if (ctype(c, C_IFSWS)) {
433c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						/*
434c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						 * non-subenvironment
435c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						 * "command" substitution
436c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						 */
437c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						c = FUNSUB;
438c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser						goto subst_command2;
439c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					}
440c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					ungetsc(c);
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OSUBST;
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '{'; /*}*/
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					wp = get_brace_var(&ws, wp);
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = getsc();
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* allow :# and :% (ksh88 compat) */
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c == ':') {
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = getsc();
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (c == ':') {
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = CHAR;
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = '0';
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ADELIM;
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ':';
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SBRACE);
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SADELIM);
45703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->ls_adelim.delimiter = ':';
45803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->ls_adelim.num = 1;
45903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->nparen = 0;
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						} else if (ksh_isdigit(c) ||
4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    c == '('/*)*/ || c == ' ' ||
46303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    /*XXX what else? */
46403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    c == '$') {
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							/* substring subst. */
4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							if (c != ' ') {
4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								*wp++ = CHAR;
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								*wp++ = ' ';
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							}
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							ungetsc(c);
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SBRACE);
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SADELIM);
47303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->ls_adelim.delimiter = ':';
47403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->ls_adelim.num = 2;
47503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->nparen = 0;
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else if (c == '/') {
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((c = getsc()) == '/') {
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ADELIM;
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = c;
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						} else
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							ungetsc(c);
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(SBRACE);
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(SADELIM);
48803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						statep->ls_adelim.delimiter = '/';
48903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						statep->ls_adelim.num = 1;
49003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						statep->nparen = 0;
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
49303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
49403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * If this is a trim operation,
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * treat (,|,) specially in STBRACE.
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (ctype(c, C_SUBOP2)) {
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c);
49903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						if (Flag(FSH))
50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							PUSH_STATE(STBRACEBOURNE);
50103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						else
50203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							PUSH_STATE(STBRACEKORN);
5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c);
505811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						if (state == SDQUOTE ||
506811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser						    state == SQBRACE)
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SQBRACE);
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						else
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SBRACE);
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (ksh_isalphx(c)) {
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OSUBST;
5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					do {
5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xcheck(ws, wp);
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = getsc();
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} while (ksh_isalnux(c));
5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '\0';
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CSUBST;
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c);
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (ctype(c, C_VAR1 | C_DIGIT)) {
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					Xcheck(ws, wp);
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OSUBST;
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '\0';
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CSUBST;
5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CHAR;
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '$';
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c);
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '`':
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_gravis:
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SBQUOTE);
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = COMSUB;
54103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
54203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * Need to know if we are inside double quotes
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * since sh/AT&T-ksh translate the \" to " in
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * "`...\"...`".
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * This is not done in POSIX mode (section
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * 3.2.3, Double Quotes: "The backquote shall
5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * retain its special meaning introducing the
5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * other form of command substitution (see
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * 3.6.3). The portion of the quoted string
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * from the initial backquote and the
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * characters up to the next backquote that
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * is not preceded by a backslash (having
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * escape characters removed) defines that
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * command whose output replaces `...` when
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * the word is expanded."
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * Section 3.6.3, Command Substitution:
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * "Within the backquoted style of command
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * substitution, backslash shall retain its
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * literal meaning, except when followed by
5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * $ ` \.").
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				statep->ls_bool = false;
5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s2 = statep;
5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				base = state_info.base;
56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				while (/* CONSTCOND */ 1) {
5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					for (; s2 != base; s2--) {
56703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						if (s2->type == SDQUOTE) {
56803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							statep->ls_bool = true;
5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (s2 != base)
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
57403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (!(s2 = s2->ls_base))
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					base = s2-- - STATE_BSIZE;
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case QCHAR:
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (cf & LQCHAR) {
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = getsc();
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* FALLTHROUGH */
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			default:
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru store_char:
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SEQUOTE:
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\'') {
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline--;
5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '\\') {
5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c2 = unbksl(true, s_get, s_put)) == -1)
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c2 = s_get();
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c2 == 0)
60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					statep->ls_bool = true;
60303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (!statep->ls_bool) {
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char ts[4];
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if ((unsigned int)c2 < 0x100) {
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = QCHAR;
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c2;
6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
61003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						cz = utf_wctomb(ts, c2 - 0x100);
61103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						ts[cz] = 0;
61203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						for (cz = 0; ts[cz]; ++cz) {
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = QCHAR;
61403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							*wp++ = ts[cz];
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
61803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else if (!statep->ls_bool) {
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = QCHAR;
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SSQUOTE:
6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\'') {
6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
627811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser				if ((cf & HEREDOC) || state == SQBRACE)
628811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser					goto store_char;
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline--;
6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = QCHAR;
6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SDQUOTE:
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '"') {
6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Subst;
6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
64503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* $(( ... )) */
64603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SASPAREN:
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '(')
64803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				statep->nparen++;
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == ')') {
65003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				statep->nparen--;
65103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (statep->nparen == 1) {
65203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* end of EXPRSUB */
65303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					POP_SRETRACE();
65403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
65503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if ((c2 = getsc()) == /*(*/ ')') {
65603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						cz = strlen(sp) - 2;
65703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						XcheckN(ws, wp, cz);
65803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						memcpy(wp, sp + 1, cz);
65903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						wp += cz;
66003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						afree(sp, ATEMP);
66103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						*wp++ = '\0';
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
66403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						Source *s;
6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c2);
66703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						/*
66803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						 * mismatched parenthesis -
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * assume we were really
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * parsing a $(...) expression
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 */
67203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						--wp;
67303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						s = pushs(SREREAD,
67403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    source->areap);
67503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						s->start = s->str =
67603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    s->u.freeme = sp;
67703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						s->next = source;
67803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						source = s;
67903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						goto subst_command;
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
68303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* reuse existing state machine */
68403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto Sbase2;
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SQBRACE:
6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\\') {
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * perform POSIX "quote removal" if the back-
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * slash is "special", i.e. same cases as the
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * {case '\\':} in Subst: plus closing brace;
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * in mksh code "quote removal" on '\c' means
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * write QCHAR+c, otherwise CHAR+\+CHAR+c are
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * emitted (in heredocquote:)
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c = getsc()) == '"' || c == '\\' ||
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    c == '$' || c == '`' || c == /*{*/'}')
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto store_qchar;
6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto heredocquote;
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto common_SQBRACE;
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SBRACE:
7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\'')
705811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser				goto open_ssquote_unless_heredoc;
7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '\\')
7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto getsc_qchar;
7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru common_SQBRACE:
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '"')
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto open_sdquote;
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '$')
712c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				goto subst_dollar_ex;
7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '`')
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto subst_gravis;
7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c != /*{*/ '}')
7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto store_char;
7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			POP_STATE();
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = CSUBST;
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = /*{*/ '}';
7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
72203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* Same as SBASE, except (,|,) treated specially */
72303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case STBRACEKORN:
72403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (c == '|')
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = SPAT;
72603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else if (c == '(') {
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OPAT;
72803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* simile for @ */
72903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				*wp++ = ' ';
7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SPATTERN);
73103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else /* FALLTHROUGH */
73203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case STBRACEBOURNE:
73303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			  if (c == /*{*/ '}') {
73403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				POP_STATE();
73503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				*wp++ = CSUBST;
73603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				*wp++ = /*{*/ '}';
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Sbase1;
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SBQUOTE:
7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '`') {
7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = 0;
7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '\\') {
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (c = getsc()) {
74703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				case 0:
74803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* trailing \ is lost */
74903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					break;
7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '\\':
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '$': case '`':
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '"':
75503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (statep->ls_bool) {
7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* FALLTHROUGH */
7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				default:
76103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					*wp++ = '\\';
76203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					*wp++ = c;
7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
76903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* ONEWORD */
77003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SWORD:
7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto Subst;
7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
77303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* LETEXPR: (( ... )) */
77403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SLETPAREN:
77503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (c == /*(*/ ')') {
77603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (statep->nparen > 0)
77703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					--statep->nparen;
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if ((c2 = getsc()) == /*(*/ ')') {
7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = 0;
7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CQUOTE;
7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto Done;
7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					Source *s;
7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c2);
78603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
78703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * mismatched parenthesis -
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * assume we were really
78903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * parsing a (...) expression
7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp = EOS;
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					sp = Xstring(ws, wp);
79303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					dp = wdstrip(sp, WDS_KEEPQ);
7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s = pushs(SREREAD, source->areap);
7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->start = s->str = s->u.freeme = dp;
7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->next = source;
7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source = s;
7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return ('('/*)*/);
7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '(')
80103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * parentheses inside quotes and
80303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * backslashes are lost, but AT&T ksh
80403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * doesn't count them either
8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
80603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				++statep->nparen;
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto Sbase2;
8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
809c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* <<, <<-, <<< delimiter */
81003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SHEREDELIM:
81103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
81203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * here delimiters need a special case since
8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * $ and `...` are not to be treated specially
8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			switch (c) {
816c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			case '\\':
817c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				if ((c = getsc())) {
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* trailing \ is lost */
8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
822c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				break;
823c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			case '\'':
824811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser				goto open_ssquote_unless_heredoc;
825c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			case '$':
8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c2 = getsc()) == '\'') {
827c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser open_sequote:
828c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					*wp++ = OQUOTE;
829c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					ignore_backslash_newline++;
8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					PUSH_STATE(SEQUOTE);
83103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					statep->ls_bool = false;
832c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					break;
833c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				} else if (c2 == '"') {
834c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					/* FALLTHROUGH */
835c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			case '"':
836427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes					PUSH_SRETRACE(SHEREDQUOTE);
837c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					break;
838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				}
8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
840c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				/* FALLTHROUGH */
841c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			default:
8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
847c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* " in <<, <<-, <<< delimiter */
84803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SHEREDQUOTE:
849c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (c != '"')
850c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				goto Subst;
851c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			POP_SRETRACE();
852c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			dp = strnul(sp) - 1;
853c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* remove the trailing double quote */
854c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			*dp = '\0';
855c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* store the quoted string */
856c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			*wp++ = OQUOTE;
857c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			XcheckN(ws, wp, (dp - sp));
858c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			dp = sp;
859c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			while ((c = *dp++)) {
8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '\\') {
861c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					switch ((c = *dp++)) {
86203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					case '\\':
86303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					case '"':
86403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					case '$':
86503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					case '`':
8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					default:
86803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						*wp++ = CHAR;
86903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						*wp++ = '\\';
8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
876c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			afree(sp, ATEMP);
877c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			*wp++ = CQUOTE;
878c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			state = statep->type = SHEREDELIM;
8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
88103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* in *(...|...) pattern (*+?@!) */
88203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SPATTERN:
88303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (c == /*(*/ ')') {
8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CPAT;
8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '|') {
8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = SPAT;
8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '(') {
8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OPAT;
89003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* simile for @ */
89103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				*wp++ = ' ';
8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SPATTERN);
8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Sbase1;
8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Done:
8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xcheck(ws, wp);
9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (statep != &states[1])
9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* XXX figure out what is missing */
9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		yyerror("no closing quote\n");
9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
905c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (state == SHEREDELIM)
9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SBASE;
9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dp = Xstring(ws, wp);
909811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	if (state == SBASE && (
910811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE
911811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	    (c == '&' && !Flag(FSH) && !Flag(FPOSIX)) ||
912811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif
913811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	    c == '<' || c == '>')) {
9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct ioword *iop = alloc(sizeof(struct ioword), ATEMP);
9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (Xlength(ws, wp) == 0)
9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->unit = c == '<' ? 0 : 1;
9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else for (iop->unit = 0, c2 = 0; c2 < Xlength(ws, wp); c2 += 2) {
9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (dp[c2] != CHAR)
9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto no_iop;
9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!ksh_isdigit(dp[c2 + 1]))
9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto no_iop;
9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (iop->unit >= FDBASE)
9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto no_iop;
9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '&') {
9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c2 = getsc()) != '>') {
9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto no_iop;
9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c = c2;
9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag = IOBASH;
9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag = 0;
9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c2 = getsc();
9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* <<, >>, <> are ok, >< is not */
9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == c2 || (c == '<' && c2 == '>')) {
9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag |= c == c2 ?
9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (c == '>' ? IOCAT : IOHERE) : IORDWR;
9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (iop->flag == IOHERE) {
94503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if ((c2 = getsc()) == '-') {
9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					iop->flag |= IOSKIP;
94703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					c2 = getsc();
94803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				} else if (c2 == '<')
94903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					iop->flag |= IOHERESTR;
95003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				ungetsc(c2);
95103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (c2 == '\n')
95203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					iop->flag |= IONDELIM;
9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c2 == '&')
9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag |= IODUP | (c == '<' ? IORDUP : 0);
9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else {
9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag |= c == '>' ? IOWRITE : IOREAD;
9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '>' && c2 == '|')
9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				iop->flag |= IOCLOB;
9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iop->name = NULL;
9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iop->delim = NULL;
9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iop->heredoc = NULL;
96703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* free word */
96803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xfree(ws, wp);
9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		yylval.iop = iop;
9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (REDIR);
9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru no_iop:
97203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		afree(iop, ATEMP);
9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp == dp && state == SBASE) {
97603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* free word */
97703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xfree(ws, wp);
9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* no word, process LEX1 character */
9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((c == '|') || (c == '&') || (c == ';') || (c == '('/*)*/)) {
9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c2 = getsc()) == c)
9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = (c == ';') ? BREAK :
9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (c == '|') ? LOGOR :
9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (c == '&') ? LOGAND :
9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    /* c == '(' ) */ MDPAREN;
9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '|' && c2 == '&')
9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = COPROC;
98703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else if (c == ';' && c2 == '|')
98803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				c = BRKEV;
98903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else if (c == ';' && c2 == '&')
99003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				c = BRKFT;
9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_SMALL
99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (c == BREAK) {
99503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if ((c2 = getsc()) == '&')
99603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					c = BRKEV;
99703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				else
99803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					ungetsc(c2);
99903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
100003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c == '\n') {
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gethere(false);
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (cf & CONTIN)
10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Again;
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c == '\0')
10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* need here strings at EOF */
10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gethere(true);
10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c);
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
101103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* terminate word */
101203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	*wp++ = EOS;
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	yylval.cp = Xclose(ws, wp);
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (state == SWORD || state == SLETPAREN
101503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    /* XXX ONEWORD? */)
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (LWORD);
10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* unget terminator */
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ungetsc(c);
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * note: the alias-vs-function code below depends on several
10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * interna: starting from here, source->str is not modified;
10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * the way getsc() and ungetsc() operate; etc.
10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* copy word to unprefixed string ident */
10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sp = yylval.cp;
10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dp = ident;
10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((cf & HEREDELIM) && (sp[1] == '<'))
1031c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		while ((dp - ident) < IDENT) {
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c = *sp++) == CHAR)
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*dp++ = *sp++;
10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if ((c != OQUOTE) && (c != CQUOTE))
10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
1038c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*dp++ = *sp++;
10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Make sure the ident array stays '\0' padded */
1041c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	memset(dp, 0, (ident + IDENT) - dp + 1);
10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (c != EOS)
104303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* word is not unquoted */
104403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		*ident = '\0';
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
104603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (*ident != '\0' && (cf & (KEYWORD | ALIAS))) {
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *p;
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		uint32_t h = hash(ident);
10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
105103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    (!(cf & ESACONLY) || p->val.i == ESAC ||
105203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    p->val.i == /*{*/ '}')) {
10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(yylval.cp, ATEMP);
10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (p->val.i);
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h)) &&
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (p->flag & ISSET)) {
10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * this still points to the same character as the
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * ungetsc'd terminator from above
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const char *cp = source->str;
10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* prefer POSIX but not Korn functions over aliases */
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*cp == ' ' || *cp == '\t')
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * this is like getsc() without skipping
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * over Source boundaries (including not
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * parsing ungetsc'd characters that got
10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * pushed into an SREREAD) which is what
10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * we want here anyway: find out whether
10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * the alias name is followed by a POSIX
10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * function definition (only the opening
10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * parenthesis is checked though)
10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				++cp;
10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* prefer functions over aliases */
107803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (cp[0] != '(' || cp[1] != ')') {
10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				Source *s = source;
10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (s && (s->flags & SF_HASALIAS))
10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (s->u.tblp == p)
10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						return (LWORD);
10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else
10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s = s->next;
10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* push alias expansion */
10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = pushs(SALIAS, source->areap);
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->start = s->str = p->val.s;
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->u.tblp = p;
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->flags |= SF_HASALIAS;
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->next = source;
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (source->type == SEOF) {
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* prevent infinite recursion at EOS */
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source->u.tblp = p;
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source->flags |= SF_HASALIAS;
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source = s;
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(yylval.cp, ATEMP);
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Again;
11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (LWORD);
11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugethere(bool iseof)
11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **p;
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = heres; p < herep; p++)
111303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (iseof && !((*p)->flag & IOHERESTR))
11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* only here strings at EOF */
11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return;
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			readhere(*p);
11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	herep = heres;
11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * read "<<word" text into temp file
11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querureadhere(struct ioword *iop)
11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
112903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *eof, *eofp;
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString xs;
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp;
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int xpos;
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
113403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (iop->flag & IOHERESTR) {
11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* process the here string */
113603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		iop->heredoc = xp = evalstr(iop->delim, DOBLANK);
113703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xpos = strlen(xp) - 1;
113803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		memmove(xp, xp + 1, xpos);
113903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp[xpos] = '\n';
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
114303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	eof = iop->flag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(iop->flag & IOEVAL))
11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ignore_backslash_newline++;
11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(xs, xp, 256, ATEMP);
11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
115003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra heredoc_read_line:
115103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* beginning of line */
115203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	eofp = eof;
115303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	xpos = Xsavepos(xs, xp);
115403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (iop->flag & IOSKIP) {
115503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip over leading tabs */
115603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while ((c = getsc()) == '\t')
115703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* nothing */;
115803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto heredoc_parse_char;
115903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
116003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra heredoc_read_char:
116103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	c = getsc();
116203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra heredoc_parse_char:
116303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* compare with here document marker */
116403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!*eofp) {
116503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* end of here document marker, what to do? */
116603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (c) {
116703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case /*(*/ ')':
1168c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (!subshell_nesting_type)
116903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*-
117003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * not allowed outside $(...) or (...)
117103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * => mismatch
117203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 */
11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
117403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* allow $(...) or (...) to close here */
117503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ungetsc(/*(*/ ')');
117603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* FALLTHROUGH */
117703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 0:
117803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
117903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * Allow EOF here to commands without trailing
118003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * newlines (mksh -c '...') will work as well.
118103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 */
118203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case '\n':
118303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* Newline terminates here document marker */
118403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto heredoc_found_terminator;
11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
118603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else if (c == *eofp++)
118703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* store; then read and compare next character */
118803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto heredoc_store_and_loop;
118903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* nope, mismatch; read until end of line */
119003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (c != '\n') {
119103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!c)
119203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* oops, reached EOF */
119303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			yyerror("%s '%s' unclosed\n", "here document", eof);
119403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* store character */
11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(xs, xp);
11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xput(xs, xp, c);
119703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* read next character */
119803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		c = getsc();
11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
120003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* we read a newline as last character */
120103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra heredoc_store_and_loop:
120203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* store character */
120303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xcheck(xs, xp);
120403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xput(xs, xp, c);
120503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (c == '\n')
120603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto heredoc_read_line;
120703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	goto heredoc_read_char;
120803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
120903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra heredoc_found_terminator:
121003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* jump back to saved beginning of line */
121103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	xp = Xrestpos(xs, xp, xpos);
121203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* terminate, close and store */
12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xput(xs, xp, '\0');
12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	iop->heredoc = Xclose(xs, xp);
12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(iop->flag & IOEVAL))
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ignore_backslash_newline--;
12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruyyerror(const char *fmt, ...)
12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* pop aliases and re-reads */
12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (source->type == SALIAS || source->type == SREREAD)
12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source = source->next;
122803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* zap pending input */
122903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	source->str = null;
12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	error_prefix(true);
12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_vfprintf(shl_out, fmt, va);
12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	errorfz();
12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * input for yylex with alias expansion
12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruSource *
12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupushs(int type, Area *areap)
12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *s;
12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = alloc(sizeof(Source), areap);
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	memset(s, 0, sizeof(Source));
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->type = type;
12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->str = null;
12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->areap = areap;
12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (type == SFILE || type == SSTDIN)
12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		XinitN(s->xs, 256, s->areap);
12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (s);
12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
125803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condragetsc_uu(void)
12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *s = source;
12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((c = *s->str++) == 0) {
126403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* return 0 for EOF by default */
126503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		s->str = NULL;
12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (s->type) {
12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SEOF:
12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->str = null;
12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SSTDIN:
12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SFILE:
12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			getsc_line(s);
12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWSTR:
12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SSTRING:
1280c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		case SSTRINGCMDLINE:
12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWORDS:
12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->start = s->str = *s->u.strv++;
12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->type = SWORDSEP;
12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWORDSEP:
12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*s->u.strv == NULL) {
12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->start = s->str = "\n";
12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->type = SEOF;
12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->start = s->str = " ";
12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->type = SWORDS;
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SALIAS:
12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (s->flags & SF_ALIASEND) {
13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* pass on an unused SF_ALIAS flag */
13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source = s->next;
13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source->flags |= s->flags & SF_ALIAS;
13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = source;
13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (*s->u.tblp->val.s &&
13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (c = strnul(s->u.tblp->val.s)[-1], ksh_isspace(c))) {
130603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* pop source stack */
130703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				source = s = s->next;
130803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
130903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * Note that this alias ended with a
131003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * space, enabling alias expansion on
131103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * the following word.
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->flags |= SF_ALIAS;
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
131503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
131603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * At this point, we need to keep the current
13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * alias in the source list so recursive
131803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * aliases can be detected and we also need to
131903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * return the next character. Do this by
132003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * temporarily popping the alias to get the
132103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * next character and then put it back in the
132203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * source list with the SF_ALIASEND flag set.
13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
132403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* pop source stack */
132503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				source = s->next;
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source->flags |= s->flags & SF_ALIAS;
132703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				c = getsc_uu();
13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c) {
13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->flags |= SF_ALIASEND;
13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->ugbuf[0] = c; s->ugbuf[1] = '\0';
13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->start = s->str = s->ugbuf;
13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->next = source;
13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source = s;
13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s = source;
133603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* avoid reading EOF twice */
13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->str = NULL;
13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SREREAD:
134403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (s->start != s->ugbuf)
134503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* yuck */
13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(s->u.freeme, ATEMP);
13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			source = s = s->next;
13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->str == NULL) {
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->type = SEOF;
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->start = s->str = null;
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return ('\0');
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->flags & SF_ECHO) {
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts(s->str, shl_out);
13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_flush(shl_out);
13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (c);
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc_line(Source *s)
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp = Xstring(s->xs, xp), *cp;
13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool interactive = Flag(FTALKING) && s->type == SSTDIN;
1368c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	bool have_tty = tobool(interactive && (s->flags & SF_TTY));
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Done here to ensure nothing odd happens when a timeout occurs */
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XcheckN(s->xs, xp, LINE);
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*xp = '\0';
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->start = s->str = xp;
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (have_tty && ksh_tmout) {
13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_tmout_state = TMOUT_READING;
13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		alarm(ksh_tmout);
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (interactive)
13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		change_winsz();
1381c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING
13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (have_tty && (
13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    Flag(FVI) ||
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    Flag(FEMACS) || Flag(FGMACS))) {
13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int nread;
13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1389811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		nread = x_read(xp);
139003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (nread < 0)
139103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* read error */
13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nread = 0;
13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp[nread] = '\0';
13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp += nread;
1395c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} else
1396c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1397c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	  {
13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (interactive)
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pprompt(prompt, 0);
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->line++;
14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
140303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (/* CONSTCOND */ 1) {
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!p && shf_error(s->u.shf) &&
14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    shf_errno(s->u.shf) == EINTR) {
14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_clearerr(s->u.shf);
14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (trap)
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					runtraps(0);
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				continue;
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!p || (xp = p, xp[-1] == '\n'))
14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* double buffer size */
141603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* move past NUL so doubling works... */
141703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp++;
14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			XcheckN(s->xs, xp, Xlength(s->xs, xp));
141903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* ...and move back again */
142003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp--;
14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
142203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
142303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * flush any unwanted input so other programs/builtins
14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * can read it. Not very optimal, but less error prone
14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * than flushing else where, dealing with redirections,
14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * etc.
142703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * TODO: reduce size of shf buffer (~128?) if SSTDIN
14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->type == SSTDIN)
14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_flush(s->u.shf);
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
143203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
143303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * XXX: temporary kludge to restore source after a
14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * trap may have been executed.
14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source = s;
14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (have_tty && ksh_tmout) {
14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_tmout_state = TMOUT_EXECUTING;
14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		alarm(0);
14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cp = Xstring(s->xs, xp);
1442427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	rndpush(cp);
14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->start = s->str = cp;
14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Note: if input is all nulls, this is not eof */
14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Xlength(s->xs, xp) == 0) {
14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* EOF */
14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->type == SFILE)
14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_fdclose(s->u.shf);
14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->str = NULL;
14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (interactive && *s->str &&
14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) {
14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsave(&s->line, s->str, true, true);
14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (interactive && cur_prompt == PS1) {
14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cp = Xstring(s->xs, xp);
14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*cp && ctype(*cp, C_IFSWS))
14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			++cp;
14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!*cp)
14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			histsync();
14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (interactive)
14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		set_prompt(PS2, NULL);
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruset_prompt(int to, Source *s)
14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cur_prompt = to;
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (to) {
147303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* command */
147403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case PS1:
147503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
147603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Substitute ! and !! here, before substitutions are done
14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * so ! in expanded variables are not expanded.
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * NOTE: this is not what AT&T ksh does (it does it after
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * substitutions, POSIX doesn't say which is to be done.
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{
14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct shf *shf;
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char * volatile ps1;
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Area *saved_atemp;
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ps1 = str_val(global("PS1"));
14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf = shf_sopen(NULL, strlen(ps1) * 2,
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    SHF_WR | SHF_DYNAMIC, NULL);
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*ps1)
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*ps1 != '!' || *++ps1 == '!')
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_putchar(*ps1++, shf);
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_fprintf(shf, "%d",
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s ? s->line + 1 : 0);
14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ps1 = shf_sclose(shf);
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			saved_atemp = ATEMP;
14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			newenv(E_ERRH);
1498c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (kshsetjmp(e->jbuf)) {
14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				prompt = safe_prompt;
150003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
150103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * Don't print an error - assume it has already
15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * been printed. Reason is we may have forked
15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * to run a command and the child may be
15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * unwinding its stack through this code as it
15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * exits.
15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				char *cp = substitute(ps1, 0);
15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strdupx(prompt, cp, saved_atemp);
15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			quitenv(NULL);
15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
151403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* command continuation */
151503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case PS2:
15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prompt = str_val(global("PS2"));
15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1521811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserint
1522811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserpprompt(const char *cp, int ntruncate)
15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char delimiter = 0;
1525427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	bool doprint = (ntruncate != -1);
1526427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	bool indelimit = false;
1527427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	int columns = 0, lines = 0;
15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
152903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
153003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Undocumented AT&T ksh feature:
153103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * If the second char in the prompt string is \r then the first
153203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * char is taken to be a non-printing delimiter and any chars
153303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * between two instances of the delimiter are not considered to
153403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * be part of the prompt length
15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*cp && cp[1] == '\r') {
15375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		delimiter = *cp;
15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cp += 2;
15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *cp; cp++) {
15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (indelimit && *cp != delimiter)
15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (*cp == '\n' || *cp == '\r') {
15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lines += columns / x_cols + ((*cp == '\n') ? 1 : 0);
15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns = 0;
15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (*cp == '\t') {
15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns = (columns | 7) + 1;
15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (*cp == '\b') {
15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (columns > 0)
15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				columns--;
15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (*cp == delimiter)
15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			indelimit = !indelimit;
15535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (UTFMODE && ((unsigned char)*cp > 0x7F)) {
15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const char *cp2;
15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns += utf_widthadj(cp, &cp2);
1556427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes			if (doprint && (indelimit ||
1557427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes			    (ntruncate < (x_cols * lines + columns))))
15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_write(cp, cp2 - cp, shl_out);
15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			cp = cp2 - /* loop increment */ 1;
15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns++;
1563427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes		if (doprint && (*cp != delimiter) &&
15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (indelimit || (ntruncate < (x_cols * lines + columns))))
15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_putc(*cp, shl_out);
15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1567427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes	if (doprint)
1568427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes		shf_flush(shl_out);
15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (x_cols * lines + columns);
15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
157203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
157303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Read the variable part of a ${...} expression (i.e. up to but not
157403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * including the :[-+?=#%] or close-brace).
15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *
15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruget_brace_var(XString *wsp, char *wp)
15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
157903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char c;
15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	enum parse_state {
15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		PS_INITIAL, PS_SAW_HASH, PS_IDENT,
15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		PS_NUMBER, PS_VAR1
158303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} state = PS_INITIAL;
15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
158503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1) {
15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc();
15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* State machine to figure out where the variable part ends. */
15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (state) {
15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_INITIAL:
15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '#' || c == '!' || c == '%') {
15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_SAW_HASH;
15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_SAW_HASH:
15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ksh_isalphx(c))
15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_IDENT;
15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (ksh_isdigit(c))
15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_NUMBER;
160003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else if (c == '#') {
160103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (state == PS_SAW_HASH) {
160203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					char c2;
160303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
160403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					c2 = getsc();
160503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					ungetsc(c2);
1606c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					if (c2 != /*{*/ '}') {
160703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						ungetsc(c);
160803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						goto out;
160903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					}
161003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
161103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				state = PS_VAR1;
161203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else if (ctype(c, C_VAR1))
16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_VAR1;
16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto out;
16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_IDENT:
16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!ksh_isalnux(c)) {
16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '[') {
16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char *tmp, *p;
16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (!arraysub(&tmp))
16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						yyerror("missing ]\n");
16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					for (p = tmp; *p; ) {
16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xcheck(*wsp, wp);
16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = *p++;
16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					afree(tmp, ATEMP);
163003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* the ] */
163103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					c = getsc();
16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto out;
16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_NUMBER:
16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!ksh_isdigit(c))
16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto out;
16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_VAR1:
16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto out;
16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(*wsp, wp);
16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*wp++ = c;
16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru out:
164703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* end of variable part */
164803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	*wp++ = '\0';
16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ungetsc(c);
16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (wp);
16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Save an array subscript - returns true if matching bracket found, false
16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if eof or newline was found.
16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (Returned string double null terminated)
16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
165803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic bool
16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruarraysub(char **strp)
16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString ws;
166203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *wp, c;
166303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* we are just past the initial [ */
1664c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	unsigned int depth = 1;
16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(ws, wp, 32, ATEMP);
16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	do {
16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc();
16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(ws, wp);
16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*wp++ = c;
16725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '[')
16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			depth++;
16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (c == ']')
16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			depth--;
16765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} while (depth > 0 && c && c != '\n');
16775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*wp++ = '\0';
16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*strp = Xclose(ws, wp);
16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
168103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (tobool(depth == 0));
16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Unget a char: handles case when we are already at the start of the buffer */
168503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void
16865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruungetsc(int c)
16875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
168803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct sretrace_info *rp = retrace_info;
168903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (backslash_skip)
16915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		backslash_skip--;
169203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* Don't unget EOF... */
16935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (source->str == null && c == '\0')
169403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return;
169503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (rp) {
169603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (Xlength(rp->xs, rp->xp))
169703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rp->xp--;
169803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rp = rp->next;
169903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
1700c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	ungetsc_i(c);
170103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
170203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void
1703c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserungetsc_i(int c)
170403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
17055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (source->str > source->start)
17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source->str--;
17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Source *s;
17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = pushs(SREREAD, source->areap);
17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->ugbuf[0] = c; s->ugbuf[1] = '\0';
17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->start = s->str = s->ugbuf;
17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->next = source;
17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source = s;
17155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called to get a char that isn't a \newline sequence. */
17205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
17215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc_bn(void)
17225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c, c2;
17245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ignore_backslash_newline)
172603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (o_getsc_u());
17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (backslash_skip == 1) {
17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		backslash_skip = 2;
173003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (o_getsc_u());
17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	backslash_skip = 0;
17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
173503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1) {
173603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		c = o_getsc_u();
17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '\\') {
173803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if ((c2 = o_getsc_u()) == '\n')
17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* ignore the \newline; get the next char... */
17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				continue;
1741c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			ungetsc_i(c2);
17425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			backslash_skip = 1;
17435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c);
17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
174803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
174903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrayyskiputf8bom(void)
175003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
175103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c;
175203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
175303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((unsigned char)(c = o_getsc_u()) != 0xEF) {
1754c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ungetsc_i(c);
175503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return;
175603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
175703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((unsigned char)(c = o_getsc_u()) != 0xBB) {
1758c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ungetsc_i(c);
1759c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ungetsc_i(0xEF);
176003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return;
176103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
176203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((unsigned char)(c = o_getsc_u()) != 0xBF) {
1763c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ungetsc_i(c);
1764c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ungetsc_i(0xBB);
1765c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ungetsc_i(0xEF);
176603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return;
176703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
176803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	UTFMODE |= 8;
176903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
177003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
17715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Lex_state *
1772c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserpush_state_i(State_info *si, Lex_state *old_end)
17735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
177403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Lex_state *news = alloc2(STATE_BSIZE, sizeof(Lex_state), ATEMP);
17755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
177603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	news[0].ls_base = old_end;
17775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	si->base = &news[0];
17785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	si->end = &news[STATE_BSIZE];
17795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (&news[1]);
17805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Lex_state *
1783c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserpop_state_i(State_info *si, Lex_state *old_end)
17845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *old_base = si->base;
17865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
178703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	si->base = old_end->ls_base - STATE_BSIZE;
178803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	si->end = old_end->ls_base;
17895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(old_base, ATEMP);
17915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (si->base + STATE_BSIZE - 1);
17935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
17965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_get(void)
17975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (getsc());
17995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
18025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_put(int c)
18035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
18045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ungetsc(c);
18055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1806