lex.c revision 5155f1c7438ef540d7b25eb70aa1639579795b07
15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: lex.c,v 1.44 2008/07/03 17:52:08 otto Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
45155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
55155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Thorsten Glaser <tg@mirbsd.org>
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.118 2010/07/25 11:35:41 tg Exp $");
265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * states while lexing word
295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SBASE		0	/* outside any lexical constructs */
315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SWORD		1	/* implicit quoting for substitute() */
325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SLETPAREN	2	/* inside (( )), implicit quoting */
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SSQUOTE		3	/* inside '' */
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SDQUOTE		4	/* inside "" */
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SEQUOTE		5	/* inside $'' */
365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SBRACE		6	/* inside ${} */
375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SQBRACE		7	/* inside "${}" */
385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SCSPAREN	8	/* inside $() */
395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SBQUOTE		9	/* inside `` */
405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SASPAREN	10	/* inside $(( )) */
415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHEREDELIM	11	/* parsing <<,<<- delimiter */
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHEREDQUOTE	12	/* parsing " in <<,<<- delimiter */
435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SPATTERN	13	/* parsing *(...|...) pattern (*+?@!) */
445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define STBRACE		14	/* parsing ${...[#%]...} */
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SLETARRAY	15	/* inside =( ), just copy */
465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SADELIM		16	/* like SBASE, looking for delimiter */
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHERESTRING	17	/* parsing <<< string */
485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Structure to keep track of the lexing state and the various pieces of info
505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * needed for each particular state. */
515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutypedef struct lex_state Lex_state;
525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct lex_state {
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int ls_state;
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	union {
555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* $(...) */
565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct scsparen_info {
575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int nparen;	/* count open parenthesis */
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int csstate;	/* XXX remove */
595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_scsparen ls_info.u_scsparen
605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_scsparen;
615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* $((...)) */
635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct sasparen_info {
645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int nparen;	/* count open parenthesis */
655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int start;	/* marks start of $(( in output str */
665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_sasparen ls_info.u_sasparen
675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_sasparen;
685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* ((...)) */
705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct sletparen_info {
715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int nparen;	/* count open parenthesis */
725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_sletparen ls_info.u_sletparen
735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_sletparen;
745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* `...` */
765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct sbquote_info {
775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int indquotes;	/* true if in double quotes: "`...`" */
785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_sbquote ls_info.u_sbquote
795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_sbquote;
805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* =(...) */
835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct sletarray_info {
845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int nparen;	/* count open parentheses */
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_sletarray ls_info.u_sletarray
865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_sletarray;
875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* ADELIM */
905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct sadelim_info {
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char nparen;	/* count open parentheses */
925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SADELIM_BASH	0
935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SADELIM_MAKE	1
945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char style;
955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char delimiter;
965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char num;
975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unsigned char flags;	/* ofs. into sadelim_flags[] */
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_sadelim ls_info.u_sadelim
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_sadelim;
1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* $'...' */
1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct sequote_info {
1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bool got_NUL;	/* ignore rest of string */
1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ls_sequote ls_info.u_sequote
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} u_sequote;
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Lex_state *base;	/* used to point to next state block */
1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} ls_info;
1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutypedef struct {
1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *base;
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *end;
1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} State_info;
1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void readhere(struct ioword *);
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getsc__(void);
1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void getsc_line(Source *);
1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getsc_bn(void);
1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int s_get(void);
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void s_put(int);
1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *get_brace_var(XString *, char *);
1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int arraysub(char **);
1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *ungetsc(int);
1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void gethere(bool);
1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Lex_state *push_state_(State_info *, Lex_state *);
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Lex_state *pop_state_(State_info *, Lex_state *);
1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int dopprompt(const char *, int, bool);
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int backslash_skip;
1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int ignore_backslash_newline;
1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* optimised getsc_bn() */
1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define _getsc()	(*source->str != '\0' && *source->str != '\\' \
1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 && !backslash_skip && !(source->flags & SF_FIRST) \
1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 ? *source->str++ : getsc_bn())
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* optimised getsc__() */
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define	_getsc_()	((*source->str != '\0') && !(source->flags & SF_FIRST) \
1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 ? *source->str++ : getsc__())
1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_SMALL
1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getsc(void);
1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getsc_(void);
1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc(void)
1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (_getsc());
1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc_(void)
1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (_getsc_());
1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* !MKSH_SMALL: use them inline */
1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define getsc()		_getsc()
1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define getsc_()	_getsc_()
1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define STATE_BSIZE	32
1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PUSH_STATE(s)	do {					\
1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (++statep == state_info.end)				\
1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		statep = push_state_(&state_info, statep);	\
1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state = statep->ls_state = (s);				\
1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} while (0)
1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define POP_STATE()	do {					\
1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (--statep == state_info.base)			\
1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		statep = pop_state_(&state_info, statep);	\
1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state = statep->ls_state;				\
1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} while (0)
1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/**
1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Lexical analyser
1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * tokens are not regular expressions, they are LL(1).
1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * for example, "${var:-${PWD}}", and "$(size $(whence ksh))".
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * hence the state stack.
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruyylex(int cf)
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state states[STATE_BSIZE], *statep, *s2, *base;
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	State_info state_info;
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c, c2, state;
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString ws;		/* expandable output word */
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *wp;		/* output word pointer */
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *sp, *dp;
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Again:
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	states[0].ls_state = -1;
1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	states[0].ls_info.base = NULL;
1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	statep = &states[1];
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state_info.base = states;
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state_info.end = &state_info.base[STATE_BSIZE];
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(ws, wp, 64, ATEMP);
2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	backslash_skip = 0;
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ignore_backslash_newline = 0;
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (cf&ONEWORD)
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SWORD;
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (cf&LETEXPR) {
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* enclose arguments in (double) quotes */
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*wp++ = OQUOTE;
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SLETPAREN;
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		statep->ls_sletparen.nparen = 0;
2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (cf&LETARRAY) {
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SLETARRAY;
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		statep->ls_sletarray.nparen = 0;
2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {		/* normal lexing */
2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((c = getsc()) == ' ' || c == '\t')
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '#') {
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ignore_backslash_newline++;
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((c = getsc()) != '\0' && c != '\n')
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ignore_backslash_newline--;
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ungetsc(c);
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (source->flags & SF_ALIAS) {	/* trailing ' ' in alias definition */
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source->flags &= ~SF_ALIAS;
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cf |= ALIAS;
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Initial state: one of SBASE SHEREDELIM SWORD SASPAREN */
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	statep->ls_state = state;
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* check for here string */
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (state == SHEREDELIM) {
2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc();
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '<') {
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = SHERESTRING;
2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((c = getsc()) == ' ' || c == '\t')
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ungetsc(c);
2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c = '<';
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto accept_nonword;
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ungetsc(c);
2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* collect non-special or quoted characters to form word */
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (!((c = getsc()) == 0 ||
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ((state == SBASE || state == SHEREDELIM || state == SHERESTRING) &&
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ctype(c, C_LEX1)))) {
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru accept_nonword:
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(ws, wp);
2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (state) {
2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SADELIM:
2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '(')
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				statep->ls_sadelim.nparen++;
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == ')')
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				statep->ls_sadelim.nparen--;
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (statep->ls_sadelim.nparen == 0 &&
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (c == /*{*/ '}' || c == statep->ls_sadelim.delimiter)) {
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = ADELIM;
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == /*{*/ '}' || --statep->ls_sadelim.num == 0)
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					POP_STATE();
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == /*{*/ '}')
2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					POP_STATE();
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SBASE:
2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp = EOS;	/* temporary */
2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (is_wdvarname(Xstring(ws, wp), false)) {
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char *p, *tmp;
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (arraysub(&tmp)) {
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						for (p = tmp; *p; ) {
2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							Xcheck(ws, wp);
2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = CHAR;
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = *p++;
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						afree(tmp, ATEMP);
2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Source *s;
2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s = pushs(SREREAD,
2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    source->areap);
2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s->start = s->str =
2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    s->u.freeme = tmp;
2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s->next = source;
3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						source = s;
3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sbase1:		/* includes *(...|...) pattern (*+?@!) */
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '*' || c == '@' || c == '+' || c == '?' ||
3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    c == '!') {
3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c2 = getsc();
3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c2 == '(' /*)*/ ) {
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OPAT;
3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					PUSH_STATE(SPATTERN);
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sbase2:		/* doesn't include *(...|...) pattern (*+?@!) */
3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (c) {
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '\\':
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru getsc_qchar:
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c = getsc())) {
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* trailing \ is lost */
3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '\'':
3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru open_ssquote:
3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline++;
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SSQUOTE);
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '"':
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru open_sdquote:
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SDQUOTE);
3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			default:
3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Subst;
3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Subst:
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (c) {
3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '\\':
3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc();
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (c) {
3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '"':
3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if ((cf & HEREDOC))
3545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						goto heredocquote;
3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* FALLTHROUGH */
3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '\\':
3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '$': case '`':
3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru store_qchar:
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				default:
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru heredocquote:
3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					Xcheck(ws, wp);
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c) {
3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* trailing \ is lost */
3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = '\\';
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '$':
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_dollar:
3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc();
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '(') /*)*/ {
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = getsc();
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c == '(') /*)*/ {
3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(SASPAREN);
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_sasparen.nparen = 2;
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_sasparen.start =
3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    Xsavepos(ws, wp);
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = EXPRSUB;
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c);
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(SCSPAREN);
3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_scsparen.nparen = 1;
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_scsparen.csstate = 0;
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = COMSUB;
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (c == '{') /*}*/ {
3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OSUBST;
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '{'; /*}*/
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					wp = get_brace_var(&ws, wp);
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = getsc();
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* allow :# and :% (ksh88 compat) */
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c == ':') {
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = getsc();
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (c == ':') {
4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = CHAR;
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = '0';
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ADELIM;
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ':';
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SBRACE);
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SADELIM);
4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.style = SADELIM_BASH;
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.delimiter = ':';
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.num = 1;
4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.nparen = 0;
4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						} else if (ksh_isdigit(c) ||
4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    c == '('/*)*/ || c == ' ' ||
4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    c == '$' /* XXX what else? */) {
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							/* substring subst. */
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							if (c != ' ') {
4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								*wp++ = CHAR;
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								*wp++ = ' ';
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							}
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							ungetsc(c);
4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SBRACE);
4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SADELIM);
4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.style = SADELIM_BASH;
4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.delimiter = ':';
4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.num = 2;
4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sadelim.nparen = 0;
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else if (c == '/') {
4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = CHAR;
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((c = getsc()) == '/') {
4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ADELIM;
4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = c;
4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						} else
4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							ungetsc(c);
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(SBRACE);
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(SADELIM);
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_sadelim.style = SADELIM_BASH;
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_sadelim.delimiter = '/';
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_sadelim.num = 1;
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_sadelim.nparen = 0;
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* If this is a trim operation,
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * treat (,|,) specially in STBRACE.
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (ctype(c, C_SUBOP2)) {
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c);
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						PUSH_STATE(STBRACE);
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c);
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (state == SDQUOTE)
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SQBRACE);
4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						else
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							PUSH_STATE(SBRACE);
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (ksh_isalphx(c)) {
4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OSUBST;
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					do {
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xcheck(ws, wp);
4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = getsc();
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} while (ksh_isalnux(c));
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '\0';
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CSUBST;
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c);
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (ctype(c, C_VAR1 | C_DIGIT)) {
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					Xcheck(ws, wp);
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OSUBST;
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '\0';
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CSUBST;
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = 'X';
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (c == '\'' && (state == SBASE)) {
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* XXX which other states are valid? */
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = OQUOTE;
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ignore_backslash_newline++;
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					PUSH_STATE(SEQUOTE);
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_sequote.got_NUL = false;
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CHAR;
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = '$';
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c);
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '`':
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_gravis:
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SBQUOTE);
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = COMSUB;
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* Need to know if we are inside double quotes
4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * since sh/AT&T-ksh translate the \" to " in
5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * "`...\"...`".
5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * This is not done in POSIX mode (section
5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * 3.2.3, Double Quotes: "The backquote shall
5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * retain its special meaning introducing the
5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * other form of command substitution (see
5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * 3.6.3). The portion of the quoted string
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * from the initial backquote and the
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * characters up to the next backquote that
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * is not preceded by a backslash (having
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * escape characters removed) defines that
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * command whose output replaces `...` when
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * the word is expanded."
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * Section 3.6.3, Command Substitution:
5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * "Within the backquoted style of command
5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * substitution, backslash shall retain its
5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * literal meaning, except when followed by
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * $ ` \.").
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				statep->ls_sbquote.indquotes = 0;
5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s2 = statep;
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				base = state_info.base;
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (1) {
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					for (; s2 != base; s2--) {
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (s2->ls_state == SDQUOTE) {
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							statep->ls_sbquote.indquotes = 1;
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (s2 != base)
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (!(s2 = s2->ls_info.base))
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					base = s2-- - STATE_BSIZE;
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case QCHAR:
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (cf & LQCHAR) {
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = getsc();
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* FALLTHROUGH */
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			default:
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru store_char:
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SEQUOTE:
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\'') {
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline--;
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '\\') {
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c2 = unbksl(true, s_get, s_put)) == -1)
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c2 = s_get();
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c2 == 0)
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_sequote.got_NUL = true;
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!statep->ls_sequote.got_NUL) {
5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char ts[4];
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if ((unsigned int)c2 < 0x100) {
5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = QCHAR;
5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c2;
5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = utf_wctomb(ts, c2 - 0x100);
5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ts[c] = 0;
5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						for (c = 0; ts[c]; ++c) {
5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = QCHAR;
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = ts[c];
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (!statep->ls_sequote.got_NUL) {
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = QCHAR;
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SSQUOTE:
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\'') {
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline--;
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = QCHAR;
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SDQUOTE:
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '"') {
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Subst;
5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SCSPAREN:	/* $( ... ) */
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* todo: deal with $(...) quoting properly
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * kludge to partly fake quoting inside $(...): doesn't
6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * really work because nested $(...) or ${...} inside
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * double quotes aren't dealt with.
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (statep->ls_scsparen.csstate) {
6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 0:	/* normal */
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (c) {
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '(':
6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.nparen++;
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case ')':
6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.nparen--;
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '\\':
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.csstate = 1;
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '"':
6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.csstate = 2;
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '\'':
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.csstate = 4;
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ignore_backslash_newline++;
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 1:	/* backslash in normal mode */
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 3:	/* backslash in double quotes */
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				--statep->ls_scsparen.csstate;
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 2:	/* double quotes */
6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '"')
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.csstate = 0;
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if (c == '\\')
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.csstate = 3;
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 4:	/* single quotes */
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '\'') {
6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_scsparen.csstate = 0;
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ignore_backslash_newline--;
6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (statep->ls_scsparen.nparen == 0) {
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = 0;	/* end of COMSUB */
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SASPAREN:	/* $(( ... )) */
6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* XXX should nest using existing state machine
6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * (embed "...", $(...), etc.) */
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '(')
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				statep->ls_sasparen.nparen++;
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == ')') {
6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				statep->ls_sasparen.nparen--;
6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (statep->ls_sasparen.nparen == 1) {
6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/*(*/
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if ((c2 = getsc()) == ')') {
6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						POP_STATE();
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* end of EXPRSUB */
6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = 0;
6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						char *s;
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						ungetsc(c2);
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* mismatched parenthesis -
6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * assume we were really
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * parsing a $(...) expression
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 */
6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s = Xrestpos(ws, wp,
6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    statep->ls_sasparen.start);
6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						memmove(s + 1, s, wp - s);
6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*s++ = COMSUB;
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*s = '('; /*)*/
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						wp++;
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_scsparen.nparen = 1;
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						statep->ls_scsparen.csstate = 0;
6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						state = statep->ls_state =
6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    SCSPAREN;
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = c;
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SQBRACE:
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\\') {
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * perform POSIX "quote removal" if the back-
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * slash is "special", i.e. same cases as the
6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * {case '\\':} in Subst: plus closing brace;
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * in mksh code "quote removal" on '\c' means
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * write QCHAR+c, otherwise CHAR+\+CHAR+c are
6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * emitted (in heredocquote:)
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c = getsc()) == '"' || c == '\\' ||
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    c == '$' || c == '`' || c == /*{*/'}')
7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto store_qchar;
7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto heredocquote;
7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto common_SQBRACE;
7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SBRACE:
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\'')
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto open_ssquote;
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '\\')
7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto getsc_qchar;
7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru common_SQBRACE:
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '"')
7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto open_sdquote;
7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '$')
7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto subst_dollar;
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '`')
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto subst_gravis;
7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c != /*{*/ '}')
7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto store_char;
7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			POP_STATE();
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = CSUBST;
7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = /*{*/ '}';
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case STBRACE:
7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* Same as SBASE, except (,|,) treated specially */
7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == /*{*/ '}') {
7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CSUBST;
7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = /*{*/ '}';
7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '|') {
7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = SPAT;
7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '(') {
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OPAT;
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = ' ';	/* simile for @ */
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SPATTERN);
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Sbase1;
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SBQUOTE:
7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '`') {
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = 0;
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '\\') {
7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (c = getsc()) {
7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '\\':
7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '$': case '`':
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '"':
7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (statep->ls_sbquote.indquotes) {
7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* FALLTHROUGH */
7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				default:
7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (c) {
7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* trailing \ is lost */
7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = '\\';
7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = c;
7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWORD:	/* ONEWORD */
7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto Subst;
7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SLETPAREN:	/* LETEXPR: (( ... )) */
7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*(*/
7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == ')') {
7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (statep->ls_sletparen.nparen > 0)
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					--statep->ls_sletparen.nparen;
7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if ((c2 = getsc()) == /*(*/ ')') {
7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = 0;
7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = CQUOTE;
7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto Done;
7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					Source *s;
7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c2);
7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* mismatched parenthesis -
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * assume we were really
7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * parsing a $(...) expression
7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp = EOS;
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					sp = Xstring(ws, wp);
7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					dp = wdstrip(sp, true, false);
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 == '(')
8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* parenthesis inside quotes and backslashes
8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * are lost, but AT&T ksh doesn't count them
8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * either
8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				++statep->ls_sletparen.nparen;
8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto Sbase2;
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SLETARRAY:	/* LETARRAY: =( ... ) */
8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '('/*)*/)
8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				++statep->ls_sletarray.nparen;
8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == /*(*/')')
8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (statep->ls_sletarray.nparen-- == 0) {
8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = 0;
8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto Done;
8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = CHAR;
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*wp++ = c;
8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SHERESTRING:	/* <<< delimiter */
8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\\') {
8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc();
8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c) {
8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* trailing \ is lost */
8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* invoke quoting mode */
8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				Xstring(ws, wp)[0] = QCHAR;
8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '$') {
8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c2 = getsc()) == '\'') {
8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					PUSH_STATE(SEQUOTE);
8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_sequote.got_NUL = false;
8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto sherestring_quoted;
8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto sherestring_regular;
8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '\'') {
8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SSQUOTE);
8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sherestring_quoted:
8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline++;
8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* invoke quoting mode */
8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				Xstring(ws, wp)[0] = QCHAR;
8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '"') {
8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = statep->ls_state = SHEREDQUOTE;
8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* just don't IFS split; no quoting mode */
8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sherestring_regular:
8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SHEREDELIM:	/* <<,<<- delimiter */
8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* XXX chuck this state (and the next) - use
8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * the existing states ($ and \`...` should be
8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * stripped of their specialness after the
8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * fact).
8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* here delimiters need a special case since
8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * $ and `...` are not to be treated specially
8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '\\') {
8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc();
8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c) {
8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* trailing \ is lost */
8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = QCHAR;
8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '$') {
8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c2 = getsc()) == '\'') {
8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					PUSH_STATE(SEQUOTE);
8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					statep->ls_sequote.got_NUL = false;
8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto sheredelim_quoted;
8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto sheredelim_regular;
8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '\'') {
8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SSQUOTE);
8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sheredelim_quoted:
8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ignore_backslash_newline++;
8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '"') {
8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = statep->ls_state = SHEREDQUOTE;
8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OQUOTE;
8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sheredelim_regular:
8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SHEREDQUOTE:	/* " in <<,<<- delimiter */
8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '"') {
8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CQUOTE;
9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = statep->ls_state =
9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    /* dp[1] == '<' means here string */
9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    Xstring(ws, wp)[1] == '<' ?
9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    SHERESTRING : SHEREDELIM;
9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '\\') {
9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch (c = getsc()) {
9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case '\\': case '"':
9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case '$': case '`':
9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					default:
9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (c) {
9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							/* trailing \ lost */
9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = CHAR;
9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							*wp++ = '\\';
9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CHAR;
9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = c;
9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SPATTERN:	/* in *(...|...) pattern (*+?@!) */
9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ( /*(*/ c == ')') {
9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = CPAT;
9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				POP_STATE();
9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '|') {
9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = SPAT;
9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (c == '(') {
9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = OPAT;
9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*wp++ = ' ';	/* simile for @ */
9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				PUSH_STATE(SPATTERN);
9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Sbase1;
9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Done:
9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xcheck(ws, wp);
9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (statep != &states[1])
9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* XXX figure out what is missing */
9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		yyerror("no closing quote\n");
9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (state == SLETARRAY && statep->ls_sletarray.nparen != -1)
9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		yyerror("%s: ')' missing\n", T_synerr);
9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (state == SHEREDELIM || state == SHERESTRING)
9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		state = SBASE;
9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dp = Xstring(ws, wp);
9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((c == '<' || c == '>' || c == '&') && state == SBASE) {
9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct ioword *iop = alloc(sizeof(struct ioword), ATEMP);
9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (Xlength(ws, wp) == 0)
9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->unit = c == '<' ? 0 : 1;
9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else for (iop->unit = 0, c2 = 0; c2 < Xlength(ws, wp); c2 += 2) {
9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (dp[c2] != CHAR)
9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto no_iop;
9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!ksh_isdigit(dp[c2 + 1]))
9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto no_iop;
9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (iop->unit >= FDBASE)
9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto no_iop;
9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '&') {
9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c2 = getsc()) != '>') {
9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto no_iop;
9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c = c2;
9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag = IOBASH;
9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag = 0;
9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c2 = getsc();
9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* <<, >>, <> are ok, >< is not */
9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == c2 || (c == '<' && c2 == '>')) {
9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag |= c == c2 ?
9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (c == '>' ? IOCAT : IOHERE) : IORDWR;
9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (iop->flag == IOHERE) {
9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((c2 = getsc()) == '-')
9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					iop->flag |= IOSKIP;
9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ungetsc(c2);
9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c2 == '&')
9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag |= IODUP | (c == '<' ? IORDUP : 0);
9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else {
9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			iop->flag |= c == '>' ? IOWRITE : IOREAD;
9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '>' && c2 == '|')
9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				iop->flag |= IOCLOB;
9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iop->name = NULL;
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iop->delim = NULL;
10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iop->heredoc = NULL;
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xfree(ws, wp);	/* free word */
10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		yylval.iop = iop;
10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (REDIR);
10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru no_iop:
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp == dp && state == SBASE) {
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xfree(ws, wp);	/* free word */
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* no word, process LEX1 character */
10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((c == '|') || (c == '&') || (c == ';') || (c == '('/*)*/)) {
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c2 = getsc()) == c)
10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = (c == ';') ? BREAK :
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (c == '|') ? LOGOR :
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (c == '&') ? LOGAND :
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    /* c == '(' ) */ MDPAREN;
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (c == '|' && c2 == '&')
10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = COPROC;
10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ungetsc(c2);
10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c == '\n') {
10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gethere(false);
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (cf & CONTIN)
10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Again;
10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c == '\0')
10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* need here strings at EOF */
10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gethere(true);
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c);
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*wp++ = EOS;		/* terminate word */
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	yylval.cp = Xclose(ws, wp);
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (state == SWORD || state == SLETPAREN
10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    /* XXX ONEWORD? */
10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    || state == SLETARRAY
10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    )
10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (LWORD);
10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* unget terminator */
10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ungetsc(c);
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * note: the alias-vs-function code below depends on several
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * interna: starting from here, source->str is not modified;
10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * the way getsc() and ungetsc() operate; etc.
10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* copy word to unprefixed string ident */
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sp = yylval.cp;
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dp = ident;
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((cf & HEREDELIM) && (sp[1] == '<'))
10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (dp < ident+IDENT) {
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c = *sp++) == CHAR)
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*dp++ = *sp++;
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if ((c != OQUOTE) && (c != CQUOTE))
10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (dp < ident+IDENT && (c = *sp++) == CHAR)
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*dp++ = *sp++;
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Make sure the ident array stays '\0' padded */
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	memset(dp, 0, (ident+IDENT) - dp + 1);
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (c != EOS)
10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*ident = '\0';	/* word is not unquoted */
10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) {
10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *p;
10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		uint32_t h = hash(ident);
10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* { */
10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}')) {
10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(yylval.cp, ATEMP);
10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (p->val.i);
10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h)) &&
10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (p->flag & ISSET)) {
10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * this still points to the same character as the
10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * ungetsc'd terminator from above
10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const char *cp = source->str;
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* prefer POSIX but not Korn functions over aliases */
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*cp == ' ' || *cp == '\t')
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * this is like getsc() without skipping
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * over Source boundaries (including not
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * parsing ungetsc'd characters that got
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * pushed into an SREREAD) which is what
10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * we want here anyway: find out whether
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * the alias name is followed by a POSIX
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * function definition (only the opening
11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * parenthesis is checked though)
11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				++cp;
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* prefer functions over aliases */
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*cp == '(' /*)*/)
11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * delete alias upon encountering function
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * definition
11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ktdelete(p);
11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else {
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				Source *s = source;
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (s && (s->flags & SF_HASALIAS))
11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (s->u.tblp == p)
11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						return (LWORD);
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s = s->next;
11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* push alias expansion */
11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = pushs(SALIAS, source->areap);
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->start = s->str = p->val.s;
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->u.tblp = p;
11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->flags |= SF_HASALIAS;
11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->next = source;
11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (source->type == SEOF) {
11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* prevent infinite recursion at EOS */
11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source->u.tblp = p;
11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source->flags |= SF_HASALIAS;
11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source = s;
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(yylval.cp, ATEMP);
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto Again;
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (LWORD);
11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugethere(bool iseof)
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **p;
11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = heres; p < herep; p++)
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (iseof && (*p)->delim[1] != '<')
11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* only here strings at EOF */
11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return;
11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			readhere(*p);
11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	herep = heres;
11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * read "<<word" text into temp file
11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querureadhere(struct ioword *iop)
11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *volatile eof;
11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *eofp;
11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int skiptabs;
11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString xs;
11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp;
11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int xpos;
11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (iop->delim[1] == '<') {
11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* process the here string */
11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp = iop->heredoc = evalstr(iop->delim, DOBLANK);
11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = strlen(xp) - 1;
11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		memmove(xp, xp + 1, c);
11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp[c] = '\n';
11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	eof = evalstr(iop->delim, 0);
11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(iop->flag & IOEVAL))
11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ignore_backslash_newline++;
11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(xs, xp, 256, ATEMP);
11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (;;) {
11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		eofp = eof;
11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		skiptabs = iop->flag & IOSKIP;
11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xpos = Xsavepos(xs, xp);
11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((c = getsc()) != 0) {
11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (skiptabs) {
11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '\t')
11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				skiptabs = 0;
11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c != *eofp)
11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xcheck(xs, xp);
11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xput(xs, xp, c);
11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			eofp++;
11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Allow EOF here so commands with out trailing newlines
12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * will work (eg, ksh -c '...', $(...), etc).
12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*eofp == '\0' && (c == 0 || c == '\n')) {
12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xp = Xrestpos(xs, xp, xpos);
12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ungetsc(c);
12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((c = getsc()) != '\n') {
12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == 0)
12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				yyerror("here document '%s' unclosed\n", eof);
12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xcheck(xs, xp);
12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xput(xs, xp, c);
12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(xs, xp);
12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xput(xs, xp, c);
12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xput(xs, xp, '\0');
12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	iop->heredoc = Xclose(xs, xp);
12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(iop->flag & IOEVAL))
12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ignore_backslash_newline--;
12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruyyerror(const char *fmt, ...)
12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* pop aliases and re-reads */
12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (source->type == SALIAS || source->type == SREREAD)
12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source = source->next;
12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source->str = null;	/* zap pending input */
12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	error_prefix(true);
12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_vfprintf(shl_out, fmt, va);
12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	errorfz();
12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * input for yylex with alias expansion
12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruSource *
12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupushs(int type, Area *areap)
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *s;
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = alloc(sizeof(Source), areap);
12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	memset(s, 0, sizeof(Source));
12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->type = type;
12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->str = null;
12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->areap = areap;
12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (type == SFILE || type == SSTDIN)
12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		XinitN(s->xs, 256, s->areap);
12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (s);
12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc__(void)
12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *s = source;
12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru getsc_again:
12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((c = *s->str++) == 0) {
12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->str = NULL;		/* return 0 for EOF by default */
12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (s->type) {
12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SEOF:
12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->str = null;
12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SSTDIN:
12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SFILE:
12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			getsc_line(s);
12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWSTR:
12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SSTRING:
12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWORDS:
12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->start = s->str = *s->u.strv++;
12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->type = SWORDSEP;
12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SWORDSEP:
12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*s->u.strv == NULL) {
12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->start = s->str = "\n";
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->type = SEOF;
12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->start = s->str = " ";
12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->type = SWORDS;
12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SALIAS:
13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (s->flags & SF_ALIASEND) {
13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* pass on an unused SF_ALIAS flag */
13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source = s->next;
13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source->flags |= s->flags & SF_ALIAS;
13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = source;
13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (*s->u.tblp->val.s &&
13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (c = strnul(s->u.tblp->val.s)[-1], ksh_isspace(c))) {
13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source = s = s->next;	/* pop source stack */
13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* Note that this alias ended with a space,
13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * enabling alias expansion on the following
13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * word.
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->flags |= SF_ALIAS;
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* At this point, we need to keep the current
13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * alias in the source list so recursive
13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * aliases can be detected and we also need
13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * to return the next character. Do this
13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * by temporarily popping the alias to get
13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * the next character and then put it back
13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * in the source list with the SF_ALIASEND
13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * flag set.
13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source = s->next;	/* pop source stack */
13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				source->flags |= s->flags & SF_ALIAS;
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = getsc__();
13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c) {
13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->flags |= SF_ALIASEND;
13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->ugbuf[0] = c; s->ugbuf[1] = '\0';
13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->start = s->str = s->ugbuf;
13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->next = source;
13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					source = s;
13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s = source;
13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* avoid reading eof twice */
13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->str = NULL;
13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SREREAD:
13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (s->start != s->ugbuf)	/* yuck */
13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(s->u.freeme, ATEMP);
13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			source = s = s->next;
13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->str == NULL) {
13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->type = SEOF;
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->start = s->str = null;
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return ('\0');
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->flags & SF_ECHO) {
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts(s->str, shl_out);
13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_flush(shl_out);
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* check for UTF-8 byte order mark */
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (s->flags & SF_FIRST) {
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->flags &= ~SF_FIRST;
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (((unsigned char)c == 0xEF) &&
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (((const unsigned char *)(s->str))[0] == 0xBB) &&
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (((const unsigned char *)(s->str))[1] == 0xBF)) {
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->str += 2;
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			UTFMODE = 1;
13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto getsc_again;
13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (c);
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetsc_line(Source *s)
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp = Xstring(s->xs, xp), *cp;
13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool interactive = Flag(FTALKING) && s->type == SSTDIN;
13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int have_tty = interactive && (s->flags & SF_TTY);
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Done here to ensure nothing odd happens when a timeout occurs */
13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XcheckN(s->xs, xp, LINE);
13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*xp = '\0';
13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->start = s->str = xp;
13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (have_tty && ksh_tmout) {
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_tmout_state = TMOUT_READING;
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		alarm(ksh_tmout);
13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (interactive)
13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		change_winsz();
13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (have_tty && (
13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI
13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    Flag(FVI) ||
13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    Flag(FEMACS) || Flag(FGMACS))) {
13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int nread;
13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		nread = x_read(xp, LINE);
13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (nread < 0)	/* read error */
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nread = 0;
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp[nread] = '\0';
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp += nread;
14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (interactive)
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pprompt(prompt, 0);
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->line++;
14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (1) {
14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!p && shf_error(s->u.shf) &&
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    shf_errno(s->u.shf) == EINTR) {
14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_clearerr(s->u.shf);
14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (trap)
14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					runtraps(0);
14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				continue;
14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!p || (xp = p, xp[-1] == '\n'))
14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* double buffer size */
14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xp++;	/* move past NUL so doubling works... */
14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			XcheckN(s->xs, xp, Xlength(s->xs, xp));
14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xp--;	/* ...and move back again */
14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* flush any unwanted input so other programs/builtins
14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * can read it. Not very optimal, but less error prone
14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * than flushing else where, dealing with redirections,
14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * etc.
14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * todo: reduce size of shf buffer (~128?) if SSTDIN
14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->type == SSTDIN)
14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_flush(s->u.shf);
14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* XXX: temporary kludge to restore source after a
14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * trap may have been executed.
14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source = s;
14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (have_tty && ksh_tmout) {
14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_tmout_state = TMOUT_EXECUTING;
14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		alarm(0);
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cp = Xstring(s->xs, xp);
14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (interactive && *cp == '!' && cur_prompt == PS1) {
14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int linelen;
14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		linelen = Xlength(s->xs, xp);
14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		XcheckN(s->xs, xp, fc_e_n + /* NUL */ 1);
14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* reload after potential realloc */
14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cp = Xstring(s->xs, xp);
14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* change initial '!' into space */
14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*cp = ' ';
14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* NUL terminate the current string */
14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*xp = '\0';
14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* move the actual string forward */
14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		memmove(cp + fc_e_n, cp, linelen + /* NUL */ 1);
14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp += fc_e_n;
14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* prepend it with "fc -e -" */
14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		memcpy(cp, fc_e_, fc_e_n);
14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->start = s->str = cp;
14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Note: if input is all nulls, this is not eof */
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Xlength(s->xs, xp) == 0) {
14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* EOF */
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->type == SFILE)
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_fdclose(s->u.shf);
14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->str = NULL;
14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (interactive && *s->str &&
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) {
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsave(&s->line, s->str, true, true);
14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (interactive && cur_prompt == PS1) {
14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cp = Xstring(s->xs, xp);
14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*cp && ctype(*cp, C_IFSWS))
14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			++cp;
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!*cp)
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			histsync();
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (interactive)
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		set_prompt(PS2, NULL);
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruset_prompt(int to, Source *s)
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cur_prompt = to;
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (to) {
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case PS1:	/* command */
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Substitute ! and !! here, before substitutions are done
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * so ! in expanded variables are not expanded.
14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * NOTE: this is not what AT&T ksh does (it does it after
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * substitutions, POSIX doesn't say which is to be done.
14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{
14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct shf *shf;
15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char * volatile ps1;
15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Area *saved_atemp;
15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ps1 = str_val(global("PS1"));
15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf = shf_sopen(NULL, strlen(ps1) * 2,
15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    SHF_WR | SHF_DYNAMIC, NULL);
15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*ps1)
15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*ps1 != '!' || *++ps1 == '!')
15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_putchar(*ps1++, shf);
15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_fprintf(shf, "%d",
15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s ? s->line + 1 : 0);
15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ps1 = shf_sclose(shf);
15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			saved_atemp = ATEMP;
15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			newenv(E_ERRH);
15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (sigsetjmp(e->jbuf, 0)) {
15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				prompt = safe_prompt;
15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* Don't print an error - assume it has already
15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * been printed. Reason is we may have forked
15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * to run a command and the child may be
15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * unwinding its stack through this code as it
15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * exits.
15225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				char *cp = substitute(ps1, 0);
15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strdupx(prompt, cp, saved_atemp);
15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			quitenv(NULL);
15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case PS2:	/* command continuation */
15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prompt = str_val(global("PS2"));
15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
15375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudopprompt(const char *cp, int ntruncate, bool doprint)
15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int columns = 0, lines = 0, indelimit = 0;
15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char delimiter = 0;
15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Undocumented AT&T ksh feature:
15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * If the second char in the prompt string is \r then the first char
15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * is taken to be a non-printing delimiter and any chars between two
15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * instances of the delimiter are not considered to be part of the
15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * prompt length
15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*cp && cp[1] == '\r') {
15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		delimiter = *cp;
15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cp += 2;
15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *cp; cp++) {
15535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (indelimit && *cp != delimiter)
15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (*cp == '\n' || *cp == '\r') {
15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lines += columns / x_cols + ((*cp == '\n') ? 1 : 0);
15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns = 0;
15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (*cp == '\t') {
15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns = (columns | 7) + 1;
15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (*cp == '\b') {
15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (columns > 0)
15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				columns--;
15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (*cp == delimiter)
15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			indelimit = !indelimit;
15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (UTFMODE && ((unsigned char)*cp > 0x7F)) {
15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const char *cp2;
15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns += utf_widthadj(cp, &cp2);
15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (doprint && (indelimit ||
15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (ntruncate < (x_cols * lines + columns))))
15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_write(cp, cp2 - cp, shl_out);
15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			cp = cp2 - /* loop increment */ 1;
15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			columns++;
15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (doprint && (*cp != delimiter) &&
15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (indelimit || (ntruncate < (x_cols * lines + columns))))
15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_putc(*cp, shl_out);
15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (doprint)
15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_flush(shl_out);
15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (x_cols * lines + columns);
15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupprompt(const char *cp, int ntruncate)
15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dopprompt(cp, ntruncate, true);
15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupromptlen(const char *cp)
15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (dopprompt(cp, 0, false));
15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Read the variable part of a ${...} expression (ie, up to but not including
15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the :[-+?=#%] or close-brace.
15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *
16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruget_brace_var(XString *wsp, char *wp)
16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	enum parse_state {
16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		PS_INITIAL, PS_SAW_HASH, PS_IDENT,
16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		PS_NUMBER, PS_VAR1
16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} state;
16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char c;
16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	state = PS_INITIAL;
16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (1) {
16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc();
16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* State machine to figure out where the variable part ends. */
16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (state) {
16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_INITIAL:
16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == '#' || c == '!' || c == '%') {
16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_SAW_HASH;
16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_SAW_HASH:
16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ksh_isalphx(c))
16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_IDENT;
16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (ksh_isdigit(c))
16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_NUMBER;
16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (ctype(c, C_VAR1))
16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = PS_VAR1;
16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto out;
16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_IDENT:
16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!ksh_isalnux(c)) {
16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '[') {
16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char *tmp, *p;
16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (!arraysub(&tmp))
16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						yyerror("missing ]\n");
16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*wp++ = c;
16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					for (p = tmp; *p; ) {
16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xcheck(*wsp, wp);
16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*wp++ = *p++;
16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					afree(tmp, ATEMP);
16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					c = getsc();	/* the ] */
16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto out;
16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_NUMBER:
16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!ksh_isdigit(c))
16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto out;
16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case PS_VAR1:
16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto out;
16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(*wsp, wp);
16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*wp++ = c;
16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru out:
16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*wp++ = '\0';	/* end of variable part */
16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ungetsc(c);
16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (wp);
16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Save an array subscript - returns true if matching bracket found, false
16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if eof or newline was found.
16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (Returned string double null terminated)
16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruarraysub(char **strp)
16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString ws;
16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char	*wp;
16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char	c;
16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int	depth = 1;	/* we are just past the initial [ */
16765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(ws, wp, 32, ATEMP);
16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	do {
16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc();
16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xcheck(ws, wp);
16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*wp++ = c;
16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '[')
16845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			depth++;
16855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (c == ']')
16865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			depth--;
16875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} while (depth > 0 && c && c != '\n');
16885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*wp++ = '\0';
16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*strp = Xclose(ws, wp);
16915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (depth == 0 ? 1 : 0);
16935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Unget a char: handles case when we are already at the start of the buffer */
16965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *
16975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruungetsc(int c)
16985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (backslash_skip)
17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		backslash_skip--;
17015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Don't unget eof... */
17025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (source->str == null && c == '\0')
17035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (source->str);
17045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (source->str > source->start)
17055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source->str--;
17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Source *s;
17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = pushs(SREREAD, source->areap);
17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->ugbuf[0] = c; s->ugbuf[1] = '\0';
17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->start = s->str = s->ugbuf;
17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->next = source;
17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source = s;
17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (source->str);
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)
17265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (getsc_());
17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (backslash_skip == 1) {
17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		backslash_skip = 2;
17305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (getsc_());
17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	backslash_skip = 0;
17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (1) {
17365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		c = getsc_();
17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '\\') {
17385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c2 = getsc_()) == '\n')
17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* ignore the \newline; get the next char... */
17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				continue;
17415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ungetsc(c2);
17425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			backslash_skip = 1;
17435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c);
17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Lex_state *
17495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupush_state_(State_info *si, Lex_state *old_end)
17505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *news = alloc(STATE_BSIZE * sizeof(Lex_state), ATEMP);
17525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	news[0].ls_info.base = old_end;
17545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	si->base = &news[0];
17555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	si->end = &news[STATE_BSIZE];
17565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (&news[1]);
17575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Lex_state *
17605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupop_state_(State_info *si, Lex_state *old_end)
17615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Lex_state *old_base = si->base;
17635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	si->base = old_end->ls_info.base - STATE_BSIZE;
17655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	si->end = old_end->ls_info.base;
17665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(old_base, ATEMP);
17685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (si->base + STATE_BSIZE - 1);
17705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
17735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_get(void)
17745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (getsc());
17765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
17795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_put(int c)
17805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ungetsc(c);
17825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1783