lex.c revision 1.9 1 1.9 agc /* $NetBSD: lex.c,v 1.9 2003/06/23 11:38:59 agc Exp $ */
2 1.2 tls
3 1.1 jtc /*
4 1.1 jtc * lexical analysis and source input
5 1.1 jtc */
6 1.9 agc #include <sys/cdefs.h>
7 1.9 agc
8 1.9 agc #ifndef lint
9 1.9 agc __RCSID("$NetBSD: lex.c,v 1.9 2003/06/23 11:38:59 agc Exp $");
10 1.9 agc #endif
11 1.9 agc
12 1.1 jtc
13 1.1 jtc #include "sh.h"
14 1.1 jtc #include <ctype.h>
15 1.1 jtc
16 1.6 hubertf
17 1.6 hubertf /* Structure to keep track of the lexing state and the various pieces of info
18 1.6 hubertf * needed for each particular state.
19 1.6 hubertf */
20 1.6 hubertf typedef struct lex_state Lex_state;
21 1.6 hubertf struct lex_state {
22 1.6 hubertf int ls_state;
23 1.6 hubertf union {
24 1.6 hubertf /* $(...) */
25 1.6 hubertf struct scsparen_info {
26 1.6 hubertf int nparen; /* count open parenthesis */
27 1.6 hubertf int csstate; /* XXX remove */
28 1.6 hubertf #define ls_scsparen ls_info.u_scsparen
29 1.6 hubertf } u_scsparen;
30 1.6 hubertf
31 1.6 hubertf /* $((...)) */
32 1.6 hubertf struct sasparen_info {
33 1.6 hubertf int nparen; /* count open parenthesis */
34 1.6 hubertf int start; /* marks start of $(( in output str */
35 1.6 hubertf #define ls_sasparen ls_info.u_sasparen
36 1.6 hubertf } u_sasparen;
37 1.6 hubertf
38 1.6 hubertf /* ((...)) */
39 1.6 hubertf struct sletparen_info {
40 1.6 hubertf int nparen; /* count open parenthesis */
41 1.6 hubertf #define ls_sletparen ls_info.u_sletparen
42 1.6 hubertf } u_sletparen;
43 1.6 hubertf
44 1.6 hubertf /* `...` */
45 1.6 hubertf struct sbquote_info {
46 1.6 hubertf int indquotes; /* true if in double quotes: "`...`" */
47 1.6 hubertf #define ls_sbquote ls_info.u_sbquote
48 1.6 hubertf } u_sbquote;
49 1.6 hubertf
50 1.6 hubertf Lex_state *base; /* used to point to next state block */
51 1.6 hubertf } ls_info;
52 1.6 hubertf };
53 1.6 hubertf
54 1.6 hubertf typedef struct State_info State_info;
55 1.6 hubertf struct State_info {
56 1.6 hubertf Lex_state *base;
57 1.6 hubertf Lex_state *end;
58 1.6 hubertf };
59 1.6 hubertf
60 1.6 hubertf
61 1.1 jtc static void readhere ARGS((struct ioword *iop));
62 1.2 tls static int getsc__ ARGS((void));
63 1.1 jtc static void getsc_line ARGS((Source *s));
64 1.6 hubertf static int getsc_bn ARGS((void));
65 1.1 jtc static char *get_brace_var ARGS((XString *wsp, char *wp));
66 1.1 jtc static int arraysub ARGS((char **strp));
67 1.2 tls static const char *ungetsc ARGS((int c));
68 1.2 tls static void gethere ARGS((void));
69 1.6 hubertf static Lex_state *push_state_ ARGS((State_info *si, Lex_state *old_end));
70 1.6 hubertf static Lex_state *pop_state_ ARGS((State_info *si, Lex_state *old_end));
71 1.2 tls
72 1.2 tls static int backslash_skip;
73 1.2 tls static int ignore_backslash_newline;
74 1.2 tls
75 1.2 tls /* optimized getsc_bn() */
76 1.2 tls #define getsc() (*source->str != '\0' && *source->str != '\\' \
77 1.2 tls && !backslash_skip ? *source->str++ : getsc_bn())
78 1.2 tls /* optimized getsc__() */
79 1.2 tls #define getsc_() ((*source->str != '\0') ? *source->str++ : getsc__())
80 1.1 jtc
81 1.6 hubertf #define STATE_BSIZE 32
82 1.6 hubertf
83 1.6 hubertf #define PUSH_STATE(s) do { \
84 1.6 hubertf if (++statep == state_info.end) \
85 1.6 hubertf statep = push_state_(&state_info, statep); \
86 1.6 hubertf state = statep->ls_state = (s); \
87 1.6 hubertf } while (0)
88 1.6 hubertf
89 1.6 hubertf #define POP_STATE() do { \
90 1.6 hubertf if (--statep == state_info.base) \
91 1.6 hubertf statep = pop_state_(&state_info, statep); \
92 1.6 hubertf state = statep->ls_state; \
93 1.6 hubertf } while (0)
94 1.6 hubertf
95 1.6 hubertf
96 1.1 jtc
97 1.1 jtc /*
98 1.1 jtc * Lexical analyzer
99 1.1 jtc *
100 1.1 jtc * tokens are not regular expressions, they are LL(1).
101 1.1 jtc * for example, "${var:-${PWD}}", and "$(size $(whence ksh))".
102 1.1 jtc * hence the state stack.
103 1.1 jtc */
104 1.1 jtc
105 1.1 jtc int
106 1.1 jtc yylex(cf)
107 1.1 jtc int cf;
108 1.1 jtc {
109 1.6 hubertf Lex_state states[STATE_BSIZE], *statep;
110 1.6 hubertf State_info state_info;
111 1.1 jtc register int c, state;
112 1.1 jtc XString ws; /* expandable output word */
113 1.1 jtc register char *wp; /* output word pointer */
114 1.6 hubertf char *sp, *dp;
115 1.6 hubertf int c2;
116 1.1 jtc
117 1.1 jtc
118 1.1 jtc Again:
119 1.6 hubertf states[0].ls_state = -1;
120 1.6 hubertf states[0].ls_info.base = (Lex_state *) 0;
121 1.6 hubertf statep = &states[1];
122 1.6 hubertf state_info.base = states;
123 1.6 hubertf state_info.end = &states[STATE_BSIZE];
124 1.6 hubertf
125 1.1 jtc Xinit(ws, wp, 64, ATEMP);
126 1.1 jtc
127 1.2 tls backslash_skip = 0;
128 1.2 tls ignore_backslash_newline = 0;
129 1.2 tls
130 1.1 jtc if (cf&ONEWORD)
131 1.6 hubertf state = SWORD;
132 1.2 tls #ifdef KSH
133 1.1 jtc else if (cf&LETEXPR) {
134 1.1 jtc *wp++ = OQUOTE; /* enclose arguments in (double) quotes */
135 1.6 hubertf state = SLETPAREN;
136 1.6 hubertf statep->ls_sletparen.nparen = 0;
137 1.2 tls }
138 1.2 tls #endif /* KSH */
139 1.2 tls else { /* normal lexing */
140 1.6 hubertf state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
141 1.1 jtc while ((c = getsc()) == ' ' || c == '\t')
142 1.1 jtc ;
143 1.2 tls if (c == '#') {
144 1.2 tls ignore_backslash_newline++;
145 1.1 jtc while ((c = getsc()) != '\0' && c != '\n')
146 1.1 jtc ;
147 1.2 tls ignore_backslash_newline--;
148 1.2 tls }
149 1.1 jtc ungetsc(c);
150 1.1 jtc }
151 1.1 jtc if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */
152 1.1 jtc source->flags &= ~SF_ALIAS;
153 1.1 jtc /* In POSIX mode, a trailing space only counts if we are
154 1.1 jtc * parsing a simple command
155 1.1 jtc */
156 1.1 jtc if (!Flag(FPOSIX) || (cf & CMDWORD))
157 1.1 jtc cf |= ALIAS;
158 1.1 jtc }
159 1.1 jtc
160 1.6 hubertf /* Initial state: one of SBASE SHEREDELIM SWORD SASPAREN */
161 1.6 hubertf statep->ls_state = state;
162 1.6 hubertf
163 1.1 jtc /* collect non-special or quoted characters to form word */
164 1.6 hubertf while (!((c = getsc()) == 0
165 1.6 hubertf || ((state == SBASE || state == SHEREDELIM)
166 1.6 hubertf && ctype(c, C_LEX1))))
167 1.1 jtc {
168 1.1 jtc Xcheck(ws, wp);
169 1.1 jtc switch (state) {
170 1.1 jtc case SBASE:
171 1.1 jtc if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
172 1.1 jtc *wp = EOS; /* temporary */
173 1.1 jtc if (is_wdvarname(Xstring(ws, wp), FALSE))
174 1.1 jtc {
175 1.1 jtc char *p, *tmp;
176 1.1 jtc
177 1.1 jtc if (arraysub(&tmp)) {
178 1.1 jtc *wp++ = CHAR;
179 1.1 jtc *wp++ = c;
180 1.1 jtc for (p = tmp; *p; ) {
181 1.1 jtc Xcheck(ws, wp);
182 1.1 jtc *wp++ = CHAR;
183 1.1 jtc *wp++ = *p++;
184 1.1 jtc }
185 1.1 jtc afree(tmp, ATEMP);
186 1.1 jtc break;
187 1.1 jtc } else {
188 1.1 jtc Source *s;
189 1.1 jtc
190 1.1 jtc s = pushs(SREREAD,
191 1.1 jtc source->areap);
192 1.1 jtc s->start = s->str
193 1.1 jtc = s->u.freeme = tmp;
194 1.1 jtc s->next = source;
195 1.1 jtc source = s;
196 1.1 jtc }
197 1.1 jtc }
198 1.1 jtc *wp++ = CHAR;
199 1.1 jtc *wp++ = c;
200 1.1 jtc break;
201 1.1 jtc }
202 1.1 jtc /* fall through.. */
203 1.1 jtc Sbase1: /* includes *(...|...) pattern (*+?@!) */
204 1.1 jtc #ifdef KSH
205 1.1 jtc if (c == '*' || c == '@' || c == '+' || c == '?'
206 1.1 jtc || c == '!')
207 1.1 jtc {
208 1.1 jtc c2 = getsc();
209 1.1 jtc if (c2 == '(' /*)*/ ) {
210 1.1 jtc *wp++ = OPAT;
211 1.1 jtc *wp++ = c;
212 1.6 hubertf PUSH_STATE(SPATTERN);
213 1.1 jtc break;
214 1.1 jtc }
215 1.1 jtc ungetsc(c2);
216 1.1 jtc }
217 1.1 jtc #endif /* KSH */
218 1.1 jtc /* fall through.. */
219 1.1 jtc Sbase2: /* doesn't include *(...|...) pattern (*+?@!) */
220 1.1 jtc switch (c) {
221 1.1 jtc case '\\':
222 1.1 jtc c = getsc();
223 1.1 jtc #ifdef OS2
224 1.2 tls if (isalnum(c)) {
225 1.2 tls *wp++ = CHAR, *wp++ = '\\';
226 1.2 tls *wp++ = CHAR, *wp++ = c;
227 1.2 tls } else
228 1.1 jtc #endif
229 1.2 tls if (c) /* trailing \ is lost */
230 1.2 tls *wp++ = QCHAR, *wp++ = c;
231 1.1 jtc break;
232 1.1 jtc case '\'':
233 1.1 jtc *wp++ = OQUOTE;
234 1.2 tls ignore_backslash_newline++;
235 1.6 hubertf PUSH_STATE(SSQUOTE);
236 1.1 jtc break;
237 1.1 jtc case '"':
238 1.1 jtc *wp++ = OQUOTE;
239 1.6 hubertf PUSH_STATE(SDQUOTE);
240 1.1 jtc break;
241 1.1 jtc default:
242 1.1 jtc goto Subst;
243 1.1 jtc }
244 1.1 jtc break;
245 1.1 jtc
246 1.1 jtc Subst:
247 1.1 jtc switch (c) {
248 1.1 jtc case '\\':
249 1.1 jtc c = getsc();
250 1.1 jtc switch (c) {
251 1.1 jtc case '"': case '\\':
252 1.1 jtc case '$': case '`':
253 1.1 jtc *wp++ = QCHAR, *wp++ = c;
254 1.1 jtc break;
255 1.1 jtc default:
256 1.1 jtc Xcheck(ws, wp);
257 1.2 tls if (c) { /* trailing \ is lost */
258 1.2 tls *wp++ = CHAR, *wp++ = '\\';
259 1.2 tls *wp++ = CHAR, *wp++ = c;
260 1.2 tls }
261 1.1 jtc break;
262 1.1 jtc }
263 1.1 jtc break;
264 1.1 jtc case '$':
265 1.1 jtc c = getsc();
266 1.1 jtc if (c == '(') /*)*/ {
267 1.1 jtc c = getsc();
268 1.1 jtc if (c == '(') /*)*/ {
269 1.6 hubertf PUSH_STATE(SASPAREN);
270 1.6 hubertf statep->ls_sasparen.nparen = 2;
271 1.6 hubertf statep->ls_sasparen.start =
272 1.6 hubertf Xsavepos(ws, wp);
273 1.1 jtc *wp++ = EXPRSUB;
274 1.1 jtc } else {
275 1.1 jtc ungetsc(c);
276 1.6 hubertf PUSH_STATE(SCSPAREN);
277 1.6 hubertf statep->ls_scsparen.nparen = 1;
278 1.6 hubertf statep->ls_scsparen.csstate = 0;
279 1.1 jtc *wp++ = COMSUB;
280 1.1 jtc }
281 1.1 jtc } else if (c == '{') /*}*/ {
282 1.1 jtc *wp++ = OSUBST;
283 1.6 hubertf *wp++ = '{'; /*}*/
284 1.1 jtc wp = get_brace_var(&ws, wp);
285 1.6 hubertf c = getsc();
286 1.6 hubertf /* allow :# and :% (ksh88 compat) */
287 1.6 hubertf if (c == ':') {
288 1.6 hubertf *wp++ = CHAR, *wp++ = c;
289 1.6 hubertf c = getsc();
290 1.6 hubertf }
291 1.1 jtc /* If this is a trim operation,
292 1.6 hubertf * treat (,|,) specially in STBRACE.
293 1.1 jtc */
294 1.1 jtc if (c == '#' || c == '%') {
295 1.6 hubertf ungetsc(c);
296 1.6 hubertf PUSH_STATE(STBRACE);
297 1.1 jtc } else {
298 1.1 jtc ungetsc(c);
299 1.6 hubertf PUSH_STATE(SBRACE);
300 1.1 jtc }
301 1.1 jtc } else if (ctype(c, C_ALPHA)) {
302 1.1 jtc *wp++ = OSUBST;
303 1.6 hubertf *wp++ = 'X';
304 1.1 jtc do {
305 1.1 jtc Xcheck(ws, wp);
306 1.1 jtc *wp++ = c;
307 1.1 jtc c = getsc();
308 1.1 jtc } while (ctype(c, C_ALPHA|C_DIGIT));
309 1.1 jtc *wp++ = '\0';
310 1.1 jtc *wp++ = CSUBST;
311 1.6 hubertf *wp++ = 'X';
312 1.1 jtc ungetsc(c);
313 1.1 jtc } else if (ctype(c, C_DIGIT|C_VAR1)) {
314 1.1 jtc Xcheck(ws, wp);
315 1.1 jtc *wp++ = OSUBST;
316 1.6 hubertf *wp++ = 'X';
317 1.1 jtc *wp++ = c;
318 1.1 jtc *wp++ = '\0';
319 1.1 jtc *wp++ = CSUBST;
320 1.6 hubertf *wp++ = 'X';
321 1.1 jtc } else {
322 1.1 jtc *wp++ = CHAR, *wp++ = '$';
323 1.1 jtc ungetsc(c);
324 1.1 jtc }
325 1.1 jtc break;
326 1.1 jtc case '`':
327 1.6 hubertf PUSH_STATE(SBQUOTE);
328 1.1 jtc *wp++ = COMSUB;
329 1.1 jtc /* Need to know if we are inside double quotes
330 1.1 jtc * since sh/at&t-ksh translate the \" to " in
331 1.1 jtc * "`..\"..`".
332 1.6 hubertf * This is not done in posix mode (section
333 1.6 hubertf * 3.2.3, Double Quotes: "The backquote shall
334 1.6 hubertf * retain its special meaning introducing the
335 1.6 hubertf * other form of command substitution (see
336 1.6 hubertf * 3.6.3). The portion of the quoted string
337 1.6 hubertf * from the initial backquote and the
338 1.6 hubertf * characters up to the next backquote that
339 1.6 hubertf * is not preceded by a backslash (having
340 1.6 hubertf * escape characters removed) defines that
341 1.6 hubertf * command whose output replaces `...` when
342 1.6 hubertf * the word is expanded."
343 1.6 hubertf * Section 3.6.3, Command Substitution:
344 1.6 hubertf * "Within the backquoted style of command
345 1.6 hubertf * substitution, backslash shall retain its
346 1.6 hubertf * literal meaning, except when followed by
347 1.6 hubertf * $ ` \.").
348 1.1 jtc */
349 1.6 hubertf statep->ls_sbquote.indquotes = 0;
350 1.6 hubertf if (!Flag(FPOSIX)) {
351 1.6 hubertf Lex_state *s = statep;
352 1.6 hubertf Lex_state *base = state_info.base;
353 1.6 hubertf while (1) {
354 1.6 hubertf for (; s != base; s--) {
355 1.6 hubertf if (s->ls_state == SDQUOTE) {
356 1.6 hubertf statep->ls_sbquote.indquotes = 1;
357 1.6 hubertf break;
358 1.6 hubertf }
359 1.6 hubertf }
360 1.6 hubertf if (s != base)
361 1.6 hubertf break;
362 1.6 hubertf if (!(s = s->ls_info.base))
363 1.6 hubertf break;
364 1.6 hubertf base = s-- - STATE_BSIZE;
365 1.6 hubertf }
366 1.6 hubertf }
367 1.1 jtc break;
368 1.1 jtc default:
369 1.1 jtc *wp++ = CHAR, *wp++ = c;
370 1.1 jtc }
371 1.1 jtc break;
372 1.1 jtc
373 1.1 jtc case SSQUOTE:
374 1.1 jtc if (c == '\'') {
375 1.6 hubertf POP_STATE();
376 1.1 jtc *wp++ = CQUOTE;
377 1.2 tls ignore_backslash_newline--;
378 1.1 jtc } else
379 1.1 jtc *wp++ = QCHAR, *wp++ = c;
380 1.1 jtc break;
381 1.1 jtc
382 1.1 jtc case SDQUOTE:
383 1.1 jtc if (c == '"') {
384 1.6 hubertf POP_STATE();
385 1.1 jtc *wp++ = CQUOTE;
386 1.1 jtc } else
387 1.1 jtc goto Subst;
388 1.1 jtc break;
389 1.1 jtc
390 1.6 hubertf case SCSPAREN: /* $( .. ) */
391 1.1 jtc /* todo: deal with $(...) quoting properly
392 1.1 jtc * kludge to partly fake quoting inside $(..): doesn't
393 1.1 jtc * really work because nested $(..) or ${..} inside
394 1.1 jtc * double quotes aren't dealt with.
395 1.1 jtc */
396 1.6 hubertf switch (statep->ls_scsparen.csstate) {
397 1.1 jtc case 0: /* normal */
398 1.1 jtc switch (c) {
399 1.1 jtc case '(':
400 1.6 hubertf statep->ls_scsparen.nparen++;
401 1.1 jtc break;
402 1.1 jtc case ')':
403 1.6 hubertf statep->ls_scsparen.nparen--;
404 1.1 jtc break;
405 1.1 jtc case '\\':
406 1.6 hubertf statep->ls_scsparen.csstate = 1;
407 1.1 jtc break;
408 1.1 jtc case '"':
409 1.6 hubertf statep->ls_scsparen.csstate = 2;
410 1.1 jtc break;
411 1.1 jtc case '\'':
412 1.6 hubertf statep->ls_scsparen.csstate = 4;
413 1.2 tls ignore_backslash_newline++;
414 1.1 jtc break;
415 1.1 jtc }
416 1.1 jtc break;
417 1.1 jtc
418 1.1 jtc case 1: /* backslash in normal mode */
419 1.1 jtc case 3: /* backslash in double quotes */
420 1.6 hubertf --statep->ls_scsparen.csstate;
421 1.1 jtc break;
422 1.1 jtc
423 1.1 jtc case 2: /* double quotes */
424 1.1 jtc if (c == '"')
425 1.6 hubertf statep->ls_scsparen.csstate = 0;
426 1.1 jtc else if (c == '\\')
427 1.6 hubertf statep->ls_scsparen.csstate = 3;
428 1.1 jtc break;
429 1.1 jtc
430 1.1 jtc case 4: /* single quotes */
431 1.2 tls if (c == '\'') {
432 1.6 hubertf statep->ls_scsparen.csstate = 0;
433 1.2 tls ignore_backslash_newline--;
434 1.2 tls }
435 1.1 jtc break;
436 1.1 jtc }
437 1.6 hubertf if (statep->ls_scsparen.nparen == 0) {
438 1.6 hubertf POP_STATE();
439 1.1 jtc *wp++ = 0; /* end of COMSUB */
440 1.1 jtc } else
441 1.1 jtc *wp++ = c;
442 1.1 jtc break;
443 1.1 jtc
444 1.6 hubertf case SASPAREN: /* $(( .. )) */
445 1.1 jtc /* todo: deal with $((...); (...)) properly */
446 1.1 jtc /* XXX should nest using existing state machine
447 1.1 jtc * (embed "..", $(...), etc.) */
448 1.1 jtc if (c == '(')
449 1.6 hubertf statep->ls_sasparen.nparen++;
450 1.1 jtc else if (c == ')') {
451 1.6 hubertf statep->ls_sasparen.nparen--;
452 1.6 hubertf if (statep->ls_sasparen.nparen == 1) {
453 1.1 jtc /*(*/
454 1.1 jtc if ((c2 = getsc()) == ')') {
455 1.6 hubertf POP_STATE();
456 1.1 jtc *wp++ = 0; /* end of EXPRSUB */
457 1.1 jtc break;
458 1.1 jtc } else {
459 1.6 hubertf char *s;
460 1.6 hubertf
461 1.1 jtc ungetsc(c2);
462 1.1 jtc /* mismatched parenthesis -
463 1.1 jtc * assume we were really
464 1.1 jtc * parsing a $(..) expression
465 1.1 jtc */
466 1.6 hubertf s = Xrestpos(ws, wp,
467 1.6 hubertf statep->ls_sasparen.start);
468 1.6 hubertf memmove(s + 1, s, wp - s);
469 1.6 hubertf *s++ = COMSUB;
470 1.6 hubertf *s = '('; /*)*/
471 1.1 jtc wp++;
472 1.6 hubertf statep->ls_scsparen.nparen = 1;
473 1.6 hubertf statep->ls_scsparen.csstate = 0;
474 1.6 hubertf state = statep->ls_state
475 1.6 hubertf = SCSPAREN;
476 1.6 hubertf
477 1.1 jtc }
478 1.1 jtc }
479 1.1 jtc }
480 1.1 jtc *wp++ = c;
481 1.1 jtc break;
482 1.1 jtc
483 1.1 jtc case SBRACE:
484 1.1 jtc /*{*/
485 1.1 jtc if (c == '}') {
486 1.6 hubertf POP_STATE();
487 1.1 jtc *wp++ = CSUBST;
488 1.6 hubertf *wp++ = /*{*/ '}';
489 1.1 jtc } else
490 1.1 jtc goto Sbase1;
491 1.1 jtc break;
492 1.1 jtc
493 1.1 jtc case STBRACE:
494 1.6 hubertf /* Same as SBRACE, except (,|,) treated specially */
495 1.1 jtc /*{*/
496 1.1 jtc if (c == '}') {
497 1.6 hubertf POP_STATE();
498 1.1 jtc *wp++ = CSUBST;
499 1.6 hubertf *wp++ = /*{*/ '}';
500 1.1 jtc } else if (c == '|') {
501 1.1 jtc *wp++ = SPAT;
502 1.6 hubertf } else if (c == '(') {
503 1.6 hubertf *wp++ = OPAT;
504 1.6 hubertf *wp++ = ' '; /* simile for @ */
505 1.6 hubertf PUSH_STATE(SPATTERN);
506 1.1 jtc } else
507 1.1 jtc goto Sbase1;
508 1.1 jtc break;
509 1.1 jtc
510 1.1 jtc case SBQUOTE:
511 1.1 jtc if (c == '`') {
512 1.1 jtc *wp++ = 0;
513 1.6 hubertf POP_STATE();
514 1.1 jtc } else if (c == '\\') {
515 1.1 jtc switch (c = getsc()) {
516 1.1 jtc case '\\':
517 1.1 jtc case '$': case '`':
518 1.1 jtc *wp++ = c;
519 1.1 jtc break;
520 1.1 jtc case '"':
521 1.6 hubertf if (statep->ls_sbquote.indquotes) {
522 1.1 jtc *wp++ = c;
523 1.1 jtc break;
524 1.1 jtc }
525 1.1 jtc /* fall through.. */
526 1.1 jtc default:
527 1.2 tls if (c) { /* trailing \ is lost */
528 1.2 tls *wp++ = '\\';
529 1.2 tls *wp++ = c;
530 1.2 tls }
531 1.1 jtc break;
532 1.1 jtc }
533 1.1 jtc } else
534 1.1 jtc *wp++ = c;
535 1.1 jtc break;
536 1.1 jtc
537 1.1 jtc case SWORD: /* ONEWORD */
538 1.1 jtc goto Subst;
539 1.1 jtc
540 1.2 tls #ifdef KSH
541 1.6 hubertf case SLETPAREN: /* LETEXPR: (( ... )) */
542 1.1 jtc /*(*/
543 1.1 jtc if (c == ')') {
544 1.6 hubertf if (statep->ls_sletparen.nparen > 0)
545 1.6 hubertf --statep->ls_sletparen.nparen;
546 1.1 jtc /*(*/
547 1.1 jtc else if ((c2 = getsc()) == ')') {
548 1.1 jtc c = 0;
549 1.1 jtc *wp++ = CQUOTE;
550 1.1 jtc goto Done;
551 1.1 jtc } else
552 1.1 jtc ungetsc(c2);
553 1.1 jtc } else if (c == '(')
554 1.1 jtc /* parenthesis inside quotes and backslashes
555 1.1 jtc * are lost, but at&t ksh doesn't count them
556 1.1 jtc * either
557 1.1 jtc */
558 1.6 hubertf ++statep->ls_sletparen.nparen;
559 1.1 jtc goto Sbase2;
560 1.2 tls #endif /* KSH */
561 1.1 jtc
562 1.1 jtc case SHEREDELIM: /* <<,<<- delimiter */
563 1.1 jtc /* XXX chuck this state (and the next) - use
564 1.1 jtc * the existing states ($ and \`..` should be
565 1.1 jtc * stripped of their specialness after the
566 1.1 jtc * fact).
567 1.1 jtc */
568 1.1 jtc /* here delimiters need a special case since
569 1.1 jtc * $ and `..` are not to be treated specially
570 1.1 jtc */
571 1.1 jtc if (c == '\\') {
572 1.1 jtc c = getsc();
573 1.2 tls if (c) { /* trailing \ is lost */
574 1.1 jtc *wp++ = QCHAR;
575 1.1 jtc *wp++ = c;
576 1.1 jtc }
577 1.1 jtc } else if (c == '\'') {
578 1.6 hubertf PUSH_STATE(SSQUOTE);
579 1.1 jtc *wp++ = OQUOTE;
580 1.2 tls ignore_backslash_newline++;
581 1.1 jtc } else if (c == '"') {
582 1.6 hubertf state = statep->ls_state = SHEREDQUOTE;
583 1.1 jtc *wp++ = OQUOTE;
584 1.1 jtc } else {
585 1.1 jtc *wp++ = CHAR;
586 1.1 jtc *wp++ = c;
587 1.1 jtc }
588 1.1 jtc break;
589 1.1 jtc
590 1.1 jtc case SHEREDQUOTE: /* " in <<,<<- delimiter */
591 1.1 jtc if (c == '"') {
592 1.1 jtc *wp++ = CQUOTE;
593 1.6 hubertf state = statep->ls_state = SHEREDELIM;
594 1.1 jtc } else {
595 1.2 tls if (c == '\\') {
596 1.2 tls switch (c = getsc()) {
597 1.2 tls case '\\': case '"':
598 1.2 tls case '$': case '`':
599 1.2 tls break;
600 1.2 tls default:
601 1.2 tls if (c) { /* trailing \ lost */
602 1.2 tls *wp++ = CHAR;
603 1.2 tls *wp++ = '\\';
604 1.2 tls }
605 1.2 tls break;
606 1.2 tls }
607 1.2 tls }
608 1.1 jtc *wp++ = CHAR;
609 1.1 jtc *wp++ = c;
610 1.1 jtc }
611 1.1 jtc break;
612 1.1 jtc
613 1.1 jtc case SPATTERN: /* in *(...|...) pattern (*+?@!) */
614 1.1 jtc if ( /*(*/ c == ')') {
615 1.1 jtc *wp++ = CPAT;
616 1.6 hubertf POP_STATE();
617 1.6 hubertf } else if (c == '|') {
618 1.1 jtc *wp++ = SPAT;
619 1.6 hubertf } else if (c == '(') {
620 1.6 hubertf *wp++ = OPAT;
621 1.6 hubertf *wp++ = ' '; /* simile for @ */
622 1.6 hubertf PUSH_STATE(SPATTERN);
623 1.6 hubertf } else
624 1.1 jtc goto Sbase1;
625 1.1 jtc break;
626 1.1 jtc }
627 1.1 jtc }
628 1.1 jtc Done:
629 1.1 jtc Xcheck(ws, wp);
630 1.6 hubertf if (statep != &states[1])
631 1.6 hubertf /* XXX figure out what is missing */
632 1.1 jtc yyerror("no closing quote\n");
633 1.1 jtc
634 1.1 jtc /* This done to avoid tests for SHEREDELIM wherever SBASE tested */
635 1.1 jtc if (state == SHEREDELIM)
636 1.1 jtc state = SBASE;
637 1.1 jtc
638 1.6 hubertf dp = Xstring(ws, wp);
639 1.6 hubertf if ((c == '<' || c == '>') && state == SBASE
640 1.6 hubertf && ((c2 = Xlength(ws, wp)) == 0
641 1.6 hubertf || (c2 == 2 && dp[0] == CHAR && digit(dp[1]))))
642 1.6 hubertf {
643 1.6 hubertf struct ioword *iop =
644 1.6 hubertf (struct ioword *) alloc(sizeof(*iop), ATEMP);
645 1.6 hubertf
646 1.6 hubertf if (c2 == 2)
647 1.6 hubertf iop->unit = dp[1] - '0';
648 1.6 hubertf else
649 1.6 hubertf iop->unit = c == '>'; /* 0 for <, 1 for > */
650 1.6 hubertf
651 1.6 hubertf c2 = getsc();
652 1.6 hubertf /* <<, >>, <> are ok, >< is not */
653 1.6 hubertf if (c == c2 || (c == '<' && c2 == '>')) {
654 1.6 hubertf iop->flag = c == c2 ?
655 1.6 hubertf (c == '>' ? IOCAT : IOHERE) : IORDWR;
656 1.7 hubertf if (iop->flag == IOHERE) {
657 1.7 hubertf if ((c2 = getsc()) == '-') {
658 1.6 hubertf iop->flag |= IOSKIP;
659 1.7 hubertf } else {
660 1.6 hubertf ungetsc(c2);
661 1.7 hubertf }
662 1.7 hubertf }
663 1.6 hubertf } else if (c2 == '&')
664 1.6 hubertf iop->flag = IODUP | (c == '<' ? IORDUP : 0);
665 1.6 hubertf else {
666 1.6 hubertf iop->flag = c == '>' ? IOWRITE : IOREAD;
667 1.6 hubertf if (c == '>' && c2 == '|')
668 1.6 hubertf iop->flag |= IOCLOB;
669 1.6 hubertf else
670 1.6 hubertf ungetsc(c2);
671 1.6 hubertf }
672 1.6 hubertf
673 1.6 hubertf iop->name = (char *) 0;
674 1.6 hubertf iop->delim = (char *) 0;
675 1.6 hubertf iop->heredoc = (char *) 0;
676 1.6 hubertf Xfree(ws, wp); /* free word */
677 1.6 hubertf yylval.iop = iop;
678 1.6 hubertf return REDIR;
679 1.1 jtc }
680 1.1 jtc
681 1.6 hubertf if (wp == dp && state == SBASE) {
682 1.1 jtc Xfree(ws, wp); /* free word */
683 1.1 jtc /* no word, process LEX1 character */
684 1.1 jtc switch (c) {
685 1.1 jtc default:
686 1.1 jtc return c;
687 1.1 jtc
688 1.1 jtc case '|':
689 1.1 jtc case '&':
690 1.1 jtc case ';':
691 1.1 jtc if ((c2 = getsc()) == c)
692 1.1 jtc c = (c == ';') ? BREAK :
693 1.1 jtc (c == '|') ? LOGOR :
694 1.1 jtc (c == '&') ? LOGAND :
695 1.1 jtc YYERRCODE;
696 1.1 jtc #ifdef KSH
697 1.1 jtc else if (c == '|' && c2 == '&')
698 1.1 jtc c = COPROC;
699 1.1 jtc #endif /* KSH */
700 1.1 jtc else
701 1.1 jtc ungetsc(c2);
702 1.1 jtc return c;
703 1.1 jtc
704 1.1 jtc case '\n':
705 1.1 jtc gethere();
706 1.1 jtc if (cf & CONTIN)
707 1.1 jtc goto Again;
708 1.1 jtc return c;
709 1.1 jtc
710 1.1 jtc case '(': /*)*/
711 1.2 tls #ifdef KSH
712 1.1 jtc if ((c2 = getsc()) == '(') /*)*/
713 1.6 hubertf /* XXX need to handle ((...); (...)) */
714 1.1 jtc c = MDPAREN;
715 1.1 jtc else
716 1.1 jtc ungetsc(c2);
717 1.2 tls #endif /* KSH */
718 1.1 jtc return c;
719 1.1 jtc /*(*/
720 1.1 jtc case ')':
721 1.1 jtc return c;
722 1.1 jtc }
723 1.1 jtc }
724 1.1 jtc
725 1.1 jtc *wp++ = EOS; /* terminate word */
726 1.1 jtc yylval.cp = Xclose(ws, wp);
727 1.2 tls if (state == SWORD
728 1.2 tls #ifdef KSH
729 1.6 hubertf || state == SLETPAREN
730 1.2 tls #endif /* KSH */
731 1.2 tls ) /* ONEWORD? */
732 1.1 jtc return LWORD;
733 1.1 jtc ungetsc(c); /* unget terminator */
734 1.1 jtc
735 1.1 jtc /* copy word to unprefixed string ident */
736 1.1 jtc for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; )
737 1.1 jtc *dp++ = *sp++;
738 1.1 jtc /* Make sure the ident array stays '\0' paded */
739 1.1 jtc memset(dp, 0, (ident+IDENT) - dp + 1);
740 1.1 jtc if (c != EOS)
741 1.1 jtc *ident = '\0'; /* word is not unquoted */
742 1.1 jtc
743 1.1 jtc if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) {
744 1.1 jtc struct tbl *p;
745 1.1 jtc int h = hash(ident);
746 1.1 jtc
747 1.1 jtc /* { */
748 1.1 jtc if ((cf & KEYWORD) && (p = tsearch(&keywords, ident, h))
749 1.1 jtc && (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}'))
750 1.1 jtc {
751 1.1 jtc afree(yylval.cp, ATEMP);
752 1.1 jtc return p->val.i;
753 1.1 jtc }
754 1.1 jtc if ((cf & ALIAS) && (p = tsearch(&aliases, ident, h))
755 1.1 jtc && (p->flag & ISSET))
756 1.1 jtc {
757 1.1 jtc register Source *s;
758 1.1 jtc
759 1.1 jtc for (s = source; s->type == SALIAS; s = s->next)
760 1.1 jtc if (s->u.tblp == p)
761 1.1 jtc return LWORD;
762 1.1 jtc /* push alias expansion */
763 1.1 jtc s = pushs(SALIAS, source->areap);
764 1.1 jtc s->start = s->str = p->val.s;
765 1.1 jtc s->u.tblp = p;
766 1.1 jtc s->next = source;
767 1.1 jtc source = s;
768 1.1 jtc afree(yylval.cp, ATEMP);
769 1.1 jtc goto Again;
770 1.1 jtc }
771 1.1 jtc }
772 1.1 jtc
773 1.1 jtc return LWORD;
774 1.1 jtc }
775 1.1 jtc
776 1.1 jtc static void
777 1.1 jtc gethere()
778 1.1 jtc {
779 1.1 jtc register struct ioword **p;
780 1.1 jtc
781 1.1 jtc for (p = heres; p < herep; p++)
782 1.1 jtc readhere(*p);
783 1.1 jtc herep = heres;
784 1.1 jtc }
785 1.1 jtc
786 1.1 jtc /*
787 1.1 jtc * read "<<word" text into temp file
788 1.1 jtc */
789 1.1 jtc
790 1.1 jtc static void
791 1.1 jtc readhere(iop)
792 1.6 hubertf struct ioword *iop;
793 1.1 jtc {
794 1.1 jtc register int c;
795 1.1 jtc char *volatile eof;
796 1.1 jtc char *eofp;
797 1.2 tls int skiptabs;
798 1.6 hubertf XString xs;
799 1.6 hubertf char *xp;
800 1.6 hubertf int xpos;
801 1.1 jtc
802 1.1 jtc eof = evalstr(iop->delim, 0);
803 1.1 jtc
804 1.2 tls if (!(iop->flag & IOEVAL))
805 1.2 tls ignore_backslash_newline++;
806 1.2 tls
807 1.6 hubertf Xinit(xs, xp, 256, ATEMP);
808 1.6 hubertf
809 1.1 jtc for (;;) {
810 1.1 jtc eofp = eof;
811 1.1 jtc skiptabs = iop->flag & IOSKIP;
812 1.6 hubertf xpos = Xsavepos(xs, xp);
813 1.2 tls while ((c = getsc()) != 0) {
814 1.1 jtc if (skiptabs) {
815 1.1 jtc if (c == '\t')
816 1.1 jtc continue;
817 1.1 jtc skiptabs = 0;
818 1.1 jtc }
819 1.1 jtc if (c != *eofp)
820 1.1 jtc break;
821 1.6 hubertf Xcheck(xs, xp);
822 1.6 hubertf Xput(xs, xp, c);
823 1.1 jtc eofp++;
824 1.1 jtc }
825 1.1 jtc /* Allow EOF here so commands with out trailing newlines
826 1.1 jtc * will work (eg, ksh -c '...', $(...), etc).
827 1.1 jtc */
828 1.6 hubertf if (*eofp == '\0' && (c == 0 || c == '\n')) {
829 1.6 hubertf xp = Xrestpos(xs, xp, xpos);
830 1.1 jtc break;
831 1.6 hubertf }
832 1.1 jtc ungetsc(c);
833 1.2 tls while ((c = getsc()) != '\n') {
834 1.1 jtc if (c == 0)
835 1.1 jtc yyerror("here document `%s' unclosed\n", eof);
836 1.6 hubertf Xcheck(xs, xp);
837 1.6 hubertf Xput(xs, xp, c);
838 1.1 jtc }
839 1.6 hubertf Xcheck(xs, xp);
840 1.6 hubertf Xput(xs, xp, c);
841 1.1 jtc }
842 1.6 hubertf Xput(xs, xp, '\0');
843 1.6 hubertf iop->heredoc = Xclose(xs, xp);
844 1.6 hubertf
845 1.2 tls if (!(iop->flag & IOEVAL))
846 1.2 tls ignore_backslash_newline--;
847 1.1 jtc }
848 1.1 jtc
849 1.1 jtc void
850 1.1 jtc #ifdef HAVE_PROTOTYPES
851 1.1 jtc yyerror(const char *fmt, ...)
852 1.1 jtc #else
853 1.1 jtc yyerror(fmt, va_alist)
854 1.1 jtc const char *fmt;
855 1.1 jtc va_dcl
856 1.1 jtc #endif
857 1.1 jtc {
858 1.1 jtc va_list va;
859 1.1 jtc
860 1.1 jtc /* pop aliases and re-reads */
861 1.1 jtc while (source->type == SALIAS || source->type == SREREAD)
862 1.1 jtc source = source->next;
863 1.1 jtc source->str = null; /* zap pending input */
864 1.1 jtc
865 1.1 jtc error_prefix(TRUE);
866 1.1 jtc SH_VA_START(va, fmt);
867 1.1 jtc shf_vfprintf(shl_out, fmt, va);
868 1.1 jtc va_end(va);
869 1.1 jtc errorf(null);
870 1.1 jtc }
871 1.1 jtc
872 1.1 jtc /*
873 1.1 jtc * input for yylex with alias expansion
874 1.1 jtc */
875 1.1 jtc
876 1.1 jtc Source *
877 1.1 jtc pushs(type, areap)
878 1.1 jtc int type;
879 1.1 jtc Area *areap;
880 1.1 jtc {
881 1.1 jtc register Source *s;
882 1.1 jtc
883 1.1 jtc s = (Source *) alloc(sizeof(Source), areap);
884 1.1 jtc s->type = type;
885 1.1 jtc s->str = null;
886 1.1 jtc s->start = NULL;
887 1.1 jtc s->line = 0;
888 1.1 jtc s->errline = 0;
889 1.1 jtc s->file = NULL;
890 1.1 jtc s->flags = 0;
891 1.1 jtc s->next = NULL;
892 1.1 jtc s->areap = areap;
893 1.1 jtc if (type == SFILE || type == SSTDIN) {
894 1.1 jtc char *dummy;
895 1.1 jtc Xinit(s->xs, dummy, 256, s->areap);
896 1.1 jtc } else
897 1.1 jtc memset(&s->xs, 0, sizeof(s->xs));
898 1.1 jtc return s;
899 1.1 jtc }
900 1.1 jtc
901 1.1 jtc static int
902 1.2 tls getsc__()
903 1.1 jtc {
904 1.1 jtc register Source *s = source;
905 1.1 jtc register int c;
906 1.1 jtc
907 1.1 jtc while ((c = *s->str++) == 0) {
908 1.1 jtc s->str = NULL; /* return 0 for EOF by default */
909 1.1 jtc switch (s->type) {
910 1.1 jtc case SEOF:
911 1.1 jtc s->str = null;
912 1.1 jtc return 0;
913 1.1 jtc
914 1.1 jtc case SSTDIN:
915 1.1 jtc case SFILE:
916 1.1 jtc getsc_line(s);
917 1.1 jtc break;
918 1.1 jtc
919 1.1 jtc case SWSTR:
920 1.1 jtc break;
921 1.1 jtc
922 1.1 jtc case SSTRING:
923 1.1 jtc break;
924 1.1 jtc
925 1.1 jtc case SWORDS:
926 1.1 jtc s->start = s->str = *s->u.strv++;
927 1.1 jtc s->type = SWORDSEP;
928 1.1 jtc break;
929 1.1 jtc
930 1.1 jtc case SWORDSEP:
931 1.1 jtc if (*s->u.strv == NULL) {
932 1.1 jtc s->start = s->str = newline;
933 1.1 jtc s->type = SEOF;
934 1.1 jtc } else {
935 1.1 jtc s->start = s->str = space;
936 1.1 jtc s->type = SWORDS;
937 1.1 jtc }
938 1.1 jtc break;
939 1.1 jtc
940 1.1 jtc case SALIAS:
941 1.1 jtc if (s->flags & SF_ALIASEND) {
942 1.1 jtc /* pass on an unused SF_ALIAS flag */
943 1.1 jtc source = s->next;
944 1.1 jtc source->flags |= s->flags & SF_ALIAS;
945 1.1 jtc s = source;
946 1.1 jtc } else if (*s->u.tblp->val.s
947 1.5 christos && isspace((unsigned char)strchr(s->u.tblp->val.s, 0)[-1]))
948 1.1 jtc {
949 1.1 jtc source = s = s->next; /* pop source stack */
950 1.2 tls /* Note that this alias ended with a space,
951 1.2 tls * enabling alias expansion on the following
952 1.2 tls * word.
953 1.2 tls */
954 1.1 jtc s->flags |= SF_ALIAS;
955 1.1 jtc } else {
956 1.2 tls /* At this point, we need to keep the current
957 1.2 tls * alias in the source list so recursive
958 1.2 tls * aliases can be detected and we also need
959 1.2 tls * to return the next character. Do this
960 1.2 tls * by temporarily popping the alias to get
961 1.2 tls * the next character and then put it back
962 1.2 tls * in the source list with the SF_ALIASEND
963 1.2 tls * flag set.
964 1.1 jtc */
965 1.2 tls source = s->next; /* pop source stack */
966 1.2 tls source->flags |= s->flags & SF_ALIAS;
967 1.2 tls c = getsc__();
968 1.2 tls if (c) {
969 1.2 tls s->flags |= SF_ALIASEND;
970 1.2 tls s->ugbuf[0] = c; s->ugbuf[1] = '\0';
971 1.2 tls s->start = s->str = s->ugbuf;
972 1.2 tls s->next = source;
973 1.2 tls source = s;
974 1.2 tls } else {
975 1.2 tls s = source;
976 1.2 tls /* avoid reading eof twice */
977 1.2 tls s->str = NULL;
978 1.2 tls break;
979 1.2 tls }
980 1.1 jtc }
981 1.1 jtc continue;
982 1.1 jtc
983 1.1 jtc case SREREAD:
984 1.2 tls if (s->start != s->ugbuf) /* yuck */
985 1.1 jtc afree(s->u.freeme, ATEMP);
986 1.1 jtc source = s = s->next;
987 1.1 jtc continue;
988 1.1 jtc }
989 1.1 jtc if (s->str == NULL) {
990 1.1 jtc s->type = SEOF;
991 1.1 jtc s->start = s->str = null;
992 1.1 jtc return '\0';
993 1.1 jtc }
994 1.1 jtc if (s->flags & SF_ECHO) {
995 1.1 jtc shf_puts(s->str, shl_out);
996 1.1 jtc shf_flush(shl_out);
997 1.1 jtc }
998 1.1 jtc }
999 1.1 jtc return c;
1000 1.1 jtc }
1001 1.1 jtc
1002 1.1 jtc static void
1003 1.1 jtc getsc_line(s)
1004 1.1 jtc Source *s;
1005 1.1 jtc {
1006 1.1 jtc char *xp = Xstring(s->xs, xp);
1007 1.1 jtc int interactive = Flag(FTALKING) && s->type == SSTDIN;
1008 1.1 jtc int have_tty = interactive && (s->flags & SF_TTY);
1009 1.1 jtc
1010 1.1 jtc /* Done here to ensure nothing odd happens when a timeout occurs */
1011 1.1 jtc XcheckN(s->xs, xp, LINE);
1012 1.1 jtc *xp = '\0';
1013 1.1 jtc s->start = s->str = xp;
1014 1.1 jtc
1015 1.1 jtc #ifdef KSH
1016 1.1 jtc if (have_tty && ksh_tmout) {
1017 1.1 jtc ksh_tmout_state = TMOUT_READING;
1018 1.1 jtc alarm(ksh_tmout);
1019 1.1 jtc }
1020 1.1 jtc #endif /* KSH */
1021 1.1 jtc #ifdef EDIT
1022 1.1 jtc if (have_tty && (0
1023 1.1 jtc # ifdef VI
1024 1.1 jtc || Flag(FVI)
1025 1.1 jtc # endif /* VI */
1026 1.1 jtc # ifdef EMACS
1027 1.1 jtc || Flag(FEMACS) || Flag(FGMACS)
1028 1.1 jtc # endif /* EMACS */
1029 1.1 jtc ))
1030 1.1 jtc {
1031 1.1 jtc int nread;
1032 1.1 jtc
1033 1.1 jtc nread = x_read(xp, LINE);
1034 1.1 jtc if (nread < 0) /* read error */
1035 1.1 jtc nread = 0;
1036 1.1 jtc xp[nread] = '\0';
1037 1.1 jtc xp += nread;
1038 1.1 jtc }
1039 1.1 jtc else
1040 1.1 jtc #endif /* EDIT */
1041 1.1 jtc {
1042 1.1 jtc if (interactive) {
1043 1.1 jtc pprompt(prompt, 0);
1044 1.1 jtc } else
1045 1.1 jtc s->line++;
1046 1.1 jtc
1047 1.1 jtc while (1) {
1048 1.1 jtc char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);
1049 1.1 jtc
1050 1.1 jtc if (!p && shf_error(s->u.shf)
1051 1.1 jtc && shf_errno(s->u.shf) == EINTR)
1052 1.1 jtc {
1053 1.1 jtc shf_clearerr(s->u.shf);
1054 1.1 jtc if (trap)
1055 1.1 jtc runtraps(0);
1056 1.1 jtc continue;
1057 1.1 jtc }
1058 1.1 jtc if (!p || (xp = p, xp[-1] == '\n'))
1059 1.1 jtc break;
1060 1.1 jtc /* double buffer size */
1061 1.1 jtc xp++; /* move past null so doubling works... */
1062 1.1 jtc XcheckN(s->xs, xp, Xlength(s->xs, xp));
1063 1.1 jtc xp--; /* ...and move back again */
1064 1.1 jtc }
1065 1.1 jtc /* flush any unwanted input so other programs/builtins
1066 1.1 jtc * can read it. Not very optimal, but less error prone
1067 1.1 jtc * than flushing else where, dealing with redirections,
1068 1.1 jtc * etc..
1069 1.1 jtc * todo: reduce size of shf buffer (~128?) if SSTDIN
1070 1.1 jtc */
1071 1.1 jtc if (s->type == SSTDIN)
1072 1.1 jtc shf_flush(s->u.shf);
1073 1.1 jtc }
1074 1.1 jtc /* XXX: temporary kludge to restore source after a
1075 1.1 jtc * trap may have been executed.
1076 1.1 jtc */
1077 1.1 jtc source = s;
1078 1.1 jtc #ifdef KSH
1079 1.1 jtc if (have_tty && ksh_tmout)
1080 1.1 jtc {
1081 1.1 jtc ksh_tmout_state = TMOUT_EXECUTING;
1082 1.1 jtc alarm(0);
1083 1.1 jtc }
1084 1.1 jtc #endif /* KSH */
1085 1.1 jtc s->start = s->str = Xstring(s->xs, xp);
1086 1.1 jtc strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
1087 1.1 jtc /* Note: if input is all nulls, this is not eof */
1088 1.1 jtc if (Xlength(s->xs, xp) == 0) { /* EOF */
1089 1.1 jtc if (s->type == SFILE)
1090 1.1 jtc shf_fdclose(s->u.shf);
1091 1.1 jtc s->str = NULL;
1092 1.1 jtc } else if (interactive) {
1093 1.1 jtc #ifdef HISTORY
1094 1.1 jtc char *p = Xstring(s->xs, xp);
1095 1.1 jtc if (cur_prompt == PS1)
1096 1.1 jtc while (*p && ctype(*p, C_IFS) && ctype(*p, C_IFSWS))
1097 1.1 jtc p++;
1098 1.1 jtc if (*p) {
1099 1.1 jtc # ifdef EASY_HISTORY
1100 1.1 jtc if (cur_prompt == PS2)
1101 1.1 jtc histappend(Xstring(s->xs, xp), 1);
1102 1.1 jtc else
1103 1.1 jtc # endif /* EASY_HISTORY */
1104 1.1 jtc {
1105 1.1 jtc s->line++;
1106 1.1 jtc histsave(s->line, s->str, 1);
1107 1.1 jtc }
1108 1.1 jtc }
1109 1.1 jtc #endif /* HISTORY */
1110 1.1 jtc }
1111 1.1 jtc if (interactive)
1112 1.1 jtc set_prompt(PS2, (Source *) 0);
1113 1.1 jtc }
1114 1.1 jtc
1115 1.1 jtc void
1116 1.1 jtc set_prompt(to, s)
1117 1.1 jtc int to;
1118 1.1 jtc Source *s;
1119 1.1 jtc {
1120 1.1 jtc cur_prompt = to;
1121 1.1 jtc
1122 1.1 jtc switch (to) {
1123 1.1 jtc case PS1: /* command */
1124 1.1 jtc #ifdef KSH
1125 1.1 jtc /* Substitute ! and !! here, before substitutions are done
1126 1.1 jtc * so ! in expanded variables are not expanded.
1127 1.1 jtc * NOTE: this is not what at&t ksh does (it does it after
1128 1.1 jtc * substitutions, POSIX doesn't say which is to be done.
1129 1.1 jtc */
1130 1.1 jtc {
1131 1.1 jtc struct shf *shf;
1132 1.1 jtc char *ps1;
1133 1.1 jtc Area *saved_atemp;
1134 1.3 christos #ifdef __GNUC__
1135 1.3 christos (void) &ps1;
1136 1.3 christos #endif
1137 1.1 jtc
1138 1.1 jtc ps1 = str_val(global("PS1"));
1139 1.1 jtc shf = shf_sopen((char *) 0, strlen(ps1) * 2,
1140 1.1 jtc SHF_WR | SHF_DYNAMIC, (struct shf *) 0);
1141 1.1 jtc while (*ps1) {
1142 1.1 jtc if (*ps1 != '!' || *++ps1 == '!')
1143 1.1 jtc shf_putchar(*ps1++, shf);
1144 1.1 jtc else
1145 1.1 jtc shf_fprintf(shf, "%d",
1146 1.1 jtc s ? s->line + 1 : 0);
1147 1.1 jtc }
1148 1.1 jtc ps1 = shf_sclose(shf);
1149 1.1 jtc saved_atemp = ATEMP;
1150 1.1 jtc newenv(E_ERRH);
1151 1.1 jtc if (ksh_sigsetjmp(e->jbuf, 0)) {
1152 1.1 jtc prompt = safe_prompt;
1153 1.1 jtc /* Don't print an error - assume it has already
1154 1.1 jtc * been printed. Reason is we may have forked
1155 1.1 jtc * to run a command and the child may be
1156 1.1 jtc * unwinding its stack through this code as it
1157 1.1 jtc * exits.
1158 1.1 jtc */
1159 1.1 jtc } else
1160 1.1 jtc prompt = str_save(substitute(ps1, 0),
1161 1.1 jtc saved_atemp);
1162 1.1 jtc quitenv();
1163 1.1 jtc }
1164 1.1 jtc #else /* KSH */
1165 1.1 jtc prompt = str_val(global("PS1"));
1166 1.1 jtc #endif /* KSH */
1167 1.1 jtc break;
1168 1.1 jtc
1169 1.1 jtc case PS2: /* command continuation */
1170 1.1 jtc prompt = str_val(global("PS2"));
1171 1.1 jtc break;
1172 1.1 jtc }
1173 1.1 jtc }
1174 1.1 jtc
1175 1.1 jtc /* See also related routine, promptlen() in edit.c */
1176 1.1 jtc void
1177 1.1 jtc pprompt(cp, ntruncate)
1178 1.1 jtc const char *cp;
1179 1.1 jtc int ntruncate;
1180 1.1 jtc {
1181 1.1 jtc #if 0
1182 1.1 jtc char nbuf[32];
1183 1.1 jtc int c;
1184 1.1 jtc
1185 1.1 jtc while (*cp != 0) {
1186 1.1 jtc if (*cp != '!')
1187 1.1 jtc c = *cp++;
1188 1.1 jtc else if (*++cp == '!')
1189 1.1 jtc c = *cp++;
1190 1.1 jtc else {
1191 1.1 jtc int len;
1192 1.1 jtc char *p;
1193 1.1 jtc
1194 1.1 jtc shf_snprintf(p = nbuf, sizeof(nbuf), "%d",
1195 1.1 jtc source->line + 1);
1196 1.1 jtc len = strlen(nbuf);
1197 1.1 jtc if (ntruncate) {
1198 1.1 jtc if (ntruncate >= len) {
1199 1.1 jtc ntruncate -= len;
1200 1.1 jtc continue;
1201 1.1 jtc }
1202 1.1 jtc p += ntruncate;
1203 1.1 jtc len -= ntruncate;
1204 1.1 jtc ntruncate = 0;
1205 1.1 jtc }
1206 1.1 jtc shf_write(p, len, shl_out);
1207 1.1 jtc continue;
1208 1.1 jtc }
1209 1.1 jtc if (ntruncate)
1210 1.1 jtc --ntruncate;
1211 1.1 jtc else
1212 1.1 jtc shf_putc(c, shl_out);
1213 1.1 jtc }
1214 1.1 jtc #endif /* 0 */
1215 1.2 tls shf_puts(cp + ntruncate, shl_out);
1216 1.2 tls shf_flush(shl_out);
1217 1.1 jtc }
1218 1.1 jtc
1219 1.1 jtc /* Read the variable part of a ${...} expression (ie, up to but not including
1220 1.1 jtc * the :[-+?=#%] or close-brace.
1221 1.1 jtc */
1222 1.1 jtc static char *
1223 1.1 jtc get_brace_var(wsp, wp)
1224 1.1 jtc XString *wsp;
1225 1.1 jtc char *wp;
1226 1.1 jtc {
1227 1.1 jtc enum parse_state {
1228 1.1 jtc PS_INITIAL, PS_SAW_HASH, PS_IDENT,
1229 1.1 jtc PS_NUMBER, PS_VAR1, PS_END
1230 1.1 jtc }
1231 1.1 jtc state;
1232 1.1 jtc char c;
1233 1.1 jtc
1234 1.1 jtc state = PS_INITIAL;
1235 1.1 jtc while (1) {
1236 1.2 tls c = getsc();
1237 1.1 jtc /* State machine to figure out where the variable part ends. */
1238 1.1 jtc switch (state) {
1239 1.1 jtc case PS_INITIAL:
1240 1.1 jtc if (c == '#') {
1241 1.1 jtc state = PS_SAW_HASH;
1242 1.1 jtc break;
1243 1.1 jtc }
1244 1.1 jtc /* fall through.. */
1245 1.1 jtc case PS_SAW_HASH:
1246 1.1 jtc if (letter(c))
1247 1.1 jtc state = PS_IDENT;
1248 1.1 jtc else if (digit(c))
1249 1.1 jtc state = PS_NUMBER;
1250 1.1 jtc else if (ctype(c, C_VAR1))
1251 1.1 jtc state = PS_VAR1;
1252 1.1 jtc else
1253 1.1 jtc state = PS_END;
1254 1.1 jtc break;
1255 1.1 jtc case PS_IDENT:
1256 1.1 jtc if (!letnum(c)) {
1257 1.1 jtc state = PS_END;
1258 1.1 jtc if (c == '[') {
1259 1.1 jtc char *tmp, *p;
1260 1.1 jtc
1261 1.1 jtc if (!arraysub(&tmp))
1262 1.1 jtc yyerror("missing ]\n");
1263 1.1 jtc *wp++ = c;
1264 1.1 jtc for (p = tmp; *p; ) {
1265 1.1 jtc Xcheck(*wsp, wp);
1266 1.1 jtc *wp++ = *p++;
1267 1.1 jtc }
1268 1.1 jtc afree(tmp, ATEMP);
1269 1.2 tls c = getsc(); /* the ] */
1270 1.1 jtc }
1271 1.1 jtc }
1272 1.1 jtc break;
1273 1.1 jtc case PS_NUMBER:
1274 1.1 jtc if (!digit(c))
1275 1.1 jtc state = PS_END;
1276 1.1 jtc break;
1277 1.1 jtc case PS_VAR1:
1278 1.1 jtc state = PS_END;
1279 1.1 jtc break;
1280 1.1 jtc case PS_END: /* keep gcc happy */
1281 1.1 jtc break;
1282 1.1 jtc }
1283 1.1 jtc if (state == PS_END) {
1284 1.1 jtc *wp++ = '\0'; /* end of variable part */
1285 1.1 jtc ungetsc(c);
1286 1.1 jtc break;
1287 1.1 jtc }
1288 1.1 jtc Xcheck(*wsp, wp);
1289 1.1 jtc *wp++ = c;
1290 1.1 jtc }
1291 1.1 jtc return wp;
1292 1.1 jtc }
1293 1.1 jtc
1294 1.1 jtc /*
1295 1.1 jtc * Save an array subscript - returns true if matching bracket found, false
1296 1.1 jtc * if eof or newline was found.
1297 1.1 jtc * (Returned string double null terminated)
1298 1.1 jtc */
1299 1.1 jtc static int
1300 1.1 jtc arraysub(strp)
1301 1.1 jtc char **strp;
1302 1.1 jtc {
1303 1.1 jtc XString ws;
1304 1.1 jtc char *wp;
1305 1.1 jtc char c;
1306 1.1 jtc int depth = 1; /* we are just past the initial [ */
1307 1.1 jtc
1308 1.1 jtc Xinit(ws, wp, 32, ATEMP);
1309 1.1 jtc
1310 1.1 jtc do {
1311 1.2 tls c = getsc();
1312 1.1 jtc Xcheck(ws, wp);
1313 1.1 jtc *wp++ = c;
1314 1.1 jtc if (c == '[')
1315 1.1 jtc depth++;
1316 1.1 jtc else if (c == ']')
1317 1.1 jtc depth--;
1318 1.1 jtc } while (depth > 0 && c && c != '\n');
1319 1.1 jtc
1320 1.1 jtc *wp++ = '\0';
1321 1.1 jtc *strp = Xclose(ws, wp);
1322 1.1 jtc
1323 1.1 jtc return depth == 0 ? 1 : 0;
1324 1.1 jtc }
1325 1.1 jtc
1326 1.1 jtc /* Unget a char: handles case when we are already at the start of the buffer */
1327 1.1 jtc static const char *
1328 1.2 tls ungetsc(c)
1329 1.1 jtc int c;
1330 1.1 jtc {
1331 1.2 tls if (backslash_skip)
1332 1.2 tls backslash_skip--;
1333 1.1 jtc /* Don't unget eof... */
1334 1.1 jtc if (source->str == null && c == '\0')
1335 1.1 jtc return source->str;
1336 1.1 jtc if (source->str > source->start)
1337 1.1 jtc source->str--;
1338 1.1 jtc else {
1339 1.1 jtc Source *s;
1340 1.1 jtc
1341 1.1 jtc s = pushs(SREREAD, source->areap);
1342 1.2 tls s->ugbuf[0] = c; s->ugbuf[1] = '\0';
1343 1.2 tls s->start = s->str = s->ugbuf;
1344 1.1 jtc s->next = source;
1345 1.1 jtc source = s;
1346 1.1 jtc }
1347 1.1 jtc return source->str;
1348 1.1 jtc }
1349 1.1 jtc
1350 1.2 tls
1351 1.1 jtc /* Called to get a char that isn't a \newline sequence. */
1352 1.1 jtc static int
1353 1.2 tls getsc_bn ARGS((void))
1354 1.1 jtc {
1355 1.2 tls int c, c2;
1356 1.2 tls
1357 1.2 tls if (ignore_backslash_newline)
1358 1.2 tls return getsc_();
1359 1.2 tls
1360 1.2 tls if (backslash_skip == 1) {
1361 1.2 tls backslash_skip = 2;
1362 1.2 tls return getsc_();
1363 1.2 tls }
1364 1.2 tls
1365 1.2 tls backslash_skip = 0;
1366 1.1 jtc
1367 1.1 jtc while (1) {
1368 1.1 jtc c = getsc_();
1369 1.2 tls if (c == '\\') {
1370 1.2 tls if ((c2 = getsc_()) == '\n')
1371 1.2 tls /* ignore the \newline; get the next char... */
1372 1.2 tls continue;
1373 1.2 tls ungetsc(c2);
1374 1.2 tls backslash_skip = 1;
1375 1.1 jtc }
1376 1.2 tls return c;
1377 1.1 jtc }
1378 1.6 hubertf }
1379 1.6 hubertf
1380 1.6 hubertf static Lex_state *
1381 1.6 hubertf push_state_(si, old_end)
1382 1.6 hubertf State_info *si;
1383 1.6 hubertf Lex_state *old_end;
1384 1.6 hubertf {
1385 1.6 hubertf Lex_state *new = alloc(sizeof(Lex_state) * STATE_BSIZE, ATEMP);
1386 1.6 hubertf
1387 1.6 hubertf new[0].ls_info.base = old_end;
1388 1.6 hubertf si->base = &new[0];
1389 1.6 hubertf si->end = &new[STATE_BSIZE];
1390 1.6 hubertf return &new[1];
1391 1.6 hubertf }
1392 1.6 hubertf
1393 1.6 hubertf static Lex_state *
1394 1.6 hubertf pop_state_(si, old_end)
1395 1.6 hubertf State_info *si;
1396 1.6 hubertf Lex_state *old_end;
1397 1.6 hubertf {
1398 1.6 hubertf Lex_state *old_base = si->base;
1399 1.6 hubertf
1400 1.6 hubertf si->base = old_end->ls_info.base - STATE_BSIZE;
1401 1.6 hubertf si->end = old_end->ls_info.base;
1402 1.6 hubertf
1403 1.6 hubertf afree(old_base, ATEMP);
1404 1.6 hubertf
1405 1.8 simonb return si->base + STATE_BSIZE - 1;
1406 1.1 jtc }
1407