]> git.ipfire.org Git - thirdparty/bash.git/blame - parse.y
Bash-5.0 patch 17: better fix for reaping process substitution file descriptors
[thirdparty/bash.git] / parse.y
CommitLineData
3185942a 1/* parse.y - Yacc grammar for bash. */
726f6388 2
d233b485 3/* Copyright (C) 1989-2017 Free Software Foundation, Inc.
726f6388
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
726f6388 11
3185942a
JA
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
726f6388 16
3185942a
JA
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
726f6388
JA
20
21%{
ccc6cda3
JA
22#include "config.h"
23
726f6388 24#include "bashtypes.h"
726f6388 25#include "bashansi.h"
ccc6cda3 26
28ef6c31
JA
27#include "filecntl.h"
28
ccc6cda3
JA
29#if defined (HAVE_UNISTD_H)
30# include <unistd.h>
31#endif
32
33#if defined (HAVE_LOCALE_H)
34# include <locale.h>
35#endif
36
37#include <stdio.h>
f73dda09 38#include "chartypes.h"
ccc6cda3
JA
39#include <signal.h>
40
41#include "memalloc.h"
42
b80f6443
JA
43#include "bashintl.h"
44
7117c2d2
JA
45#define NEED_STRFTIME_DECL /* used in externs.h */
46
726f6388 47#include "shell.h"
d233b485 48#include "execute_cmd.h"
ac50fbac 49#include "typemax.h" /* SIZE_MAX if needed */
ccc6cda3 50#include "trap.h"
726f6388 51#include "flags.h"
ccc6cda3
JA
52#include "parser.h"
53#include "mailcheck.h"
f73dda09 54#include "test.h"
95732b49 55#include "builtins.h"
ccc6cda3
JA
56#include "builtins/common.h"
57#include "builtins/builtext.h"
726f6388 58
7117c2d2
JA
59#include "shmbutil.h"
60
726f6388 61#if defined (READLINE)
ccc6cda3 62# include "bashline.h"
726f6388
JA
63# include <readline/readline.h>
64#endif /* READLINE */
65
66#if defined (HISTORY)
67# include "bashhist.h"
68# include <readline/history.h>
69#endif /* HISTORY */
70
71#if defined (JOB_CONTROL)
72# include "jobs.h"
a0c0a00f
CR
73#else
74extern int cleanup_dead_jobs __P((void));
726f6388
JA
75#endif /* JOB_CONTROL */
76
77#if defined (ALIAS)
78# include "alias.h"
b80f6443
JA
79#else
80typedef void *alias_t;
726f6388
JA
81#endif /* ALIAS */
82
83#if defined (PROMPT_STRING_DECODE)
cce855bc
JA
84# ifndef _MINIX
85# include <sys/param.h>
86# endif
87# include <time.h>
7117c2d2
JA
88# if defined (TM_IN_SYS_TIME)
89# include <sys/types.h>
90# include <sys/time.h>
91# endif /* TM_IN_SYS_TIME */
cce855bc 92# include "maxpath.h"
726f6388
JA
93#endif /* PROMPT_STRING_DECODE */
94
ccc6cda3
JA
95#define RE_READ_TOKEN -99
96#define NO_EXPANSION -100
97
d233b485
CR
98#define END_ALIAS -2
99
7117c2d2
JA
100#ifdef DEBUG
101# define YYDEBUG 1
102#else
103# define YYDEBUG 0
104#endif
105
106#if defined (HANDLE_MULTIBYTE)
107# define last_shell_getc_is_singlebyte \
108 ((shell_input_line_index > 1) \
109 ? shell_input_line_property[shell_input_line_index - 1] \
110 : 1)
111# define MBTEST(x) ((x) && last_shell_getc_is_singlebyte)
112#else
113# define last_shell_getc_is_singlebyte 1
114# define MBTEST(x) ((x))
115#endif
ccc6cda3 116
cce855bc 117#if defined (EXTENDED_GLOB)
cce855bc
JA
118extern int extended_glob;
119#endif
120
cce855bc 121extern int dump_translatable_strings, dump_po_strings;
726f6388 122
d233b485 123#if !defined (errno)
bb70624e 124extern int errno;
d233b485
CR
125#endif
126
726f6388
JA
127/* **************************************************************** */
128/* */
129/* "Forward" declarations */
130/* */
131/* **************************************************************** */
132
f73dda09
JA
133#ifdef DEBUG
134static void debug_parser __P((int));
135#endif
136
137static int yy_getc __P((void));
138static int yy_ungetc __P((int));
139
140#if defined (READLINE)
141static int yy_readline_get __P((void));
142static int yy_readline_unget __P((int));
143#endif
144
145static int yy_string_get __P((void));
146static int yy_string_unget __P((int));
3185942a 147static void rewind_input_string __P((void));
f73dda09
JA
148static int yy_stream_get __P((void));
149static int yy_stream_unget __P((int));
150
151static int shell_getc __P((int));
152static void shell_ungetc __P((int));
153static void discard_until __P((int));
154
155#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
156static void push_string __P((char *, int, alias_t *));
157static void pop_string __P((void));
158static void free_string_list __P((void));
159#endif
160
161static char *read_a_line __P((int));
162
f73dda09
JA
163static int reserved_word_acceptable __P((int));
164static int yylex __P((void));
90a39f32
CR
165
166static void push_heredoc __P((REDIRECT *));
167static char *mk_alexpansion __P((char *));
f73dda09
JA
168static int alias_expand_token __P((char *));
169static int time_command_acceptable __P((void));
170static int special_case_tokens __P((char *));
171static int read_token __P((int));
172static char *parse_matched_pair __P((int, int, int, int *, int));
3185942a 173static char *parse_comsub __P((int, int, int, int *, int));
7117c2d2
JA
174#if defined (ARRAY_VARS)
175static char *parse_compound_assignment __P((int *));
176#endif
f73dda09 177#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
7117c2d2 178static int parse_dparen __P((int));
b80f6443 179static int parse_arith_cmd __P((char **, int));
f73dda09 180#endif
cce855bc 181#if defined (COND_COMMAND)
7117c2d2 182static void cond_error __P((void));
f73dda09
JA
183static COND_COM *cond_expr __P((void));
184static COND_COM *cond_or __P((void));
185static COND_COM *cond_and __P((void));
186static COND_COM *cond_term __P((void));
187static int cond_skip_newlines __P((void));
188static COMMAND *parse_cond_command __P((void));
cce855bc 189#endif
7117c2d2
JA
190#if defined (ARRAY_VARS)
191static int token_is_assignment __P((char *, int));
192static int token_is_ident __P((char *, int));
193#endif
f73dda09
JA
194static int read_token_word __P((int));
195static void discard_parser_constructs __P((int));
726f6388 196
7117c2d2
JA
197static char *error_token_from_token __P((int));
198static char *error_token_from_text __P((void));
199static void print_offending_line __P((void));
f73dda09 200static void report_syntax_error __P((char *));
7117c2d2 201
f73dda09
JA
202static void handle_eof_input_unit __P((void));
203static void prompt_again __P((void));
d166f048 204#if 0
f73dda09 205static void reset_readline_prompt __P((void));
d166f048 206#endif
f73dda09 207static void print_prompt __P((void));
726f6388 208
7117c2d2
JA
209#if defined (HANDLE_MULTIBYTE)
210static void set_line_mbstate __P((void));
211static char *shell_input_line_property = NULL;
d233b485 212static size_t shell_input_line_propsize = 0;
7117c2d2
JA
213#else
214# define set_line_mbstate()
215#endif
216
f73dda09 217extern int yyerror __P((const char *));
d166f048 218
7117c2d2
JA
219#ifdef DEBUG
220extern int yydebug;
221#endif
222
ccc6cda3
JA
223/* Default prompt strings */
224char *primary_prompt = PPROMPT;
225char *secondary_prompt = SPROMPT;
226
726f6388
JA
227/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
228char *ps1_prompt, *ps2_prompt;
229
a0c0a00f
CR
230/* Displayed after reading a command but before executing it in an interactive shell */
231char *ps0_prompt;
232
726f6388
JA
233/* Handle on the current prompt string. Indirectly points through
234 ps1_ or ps2_prompt. */
235char **prompt_string_pointer = (char **)NULL;
236char *current_prompt_string;
237
ccc6cda3
JA
238/* Non-zero means we expand aliases in commands. */
239int expand_aliases = 0;
240
241/* If non-zero, the decoded prompt string undergoes parameter and
242 variable substitution, command substitution, arithmetic substitution,
243 string expansion, process substitution, and quote removal in
244 decode_prompt_string. */
245int promptvars = 1;
246
b80f6443
JA
247/* If non-zero, $'...' and $"..." are expanded when they appear within
248 a ${...} expansion, even when the expansion appears within double
249 quotes. */
250int extended_quote = 1;
251
726f6388 252/* The number of lines read from input while creating the current command. */
ccc6cda3 253int current_command_line_count;
726f6388 254
495aee44
CR
255/* The number of lines in a command saved while we run parse_and_execute */
256int saved_command_line_count;
257
3185942a
JA
258/* The token that currently denotes the end of parse. */
259int shell_eof_token;
260
261/* The token currently being read. */
262int current_token;
263
0001803f
CR
264/* The current parser state. */
265int parser_state;
266
726f6388
JA
267/* Variables to manage the task of reading here documents, because we need to
268 defer the reading until after a complete command has been collected. */
90a39f32 269static REDIRECT *redir_stack[HEREDOC_MAX];
ccc6cda3 270int need_here_doc;
726f6388
JA
271
272/* Where shell input comes from. History expansion is performed on each
273 line when the shell is interactive. */
274static char *shell_input_line = (char *)NULL;
ac50fbac
CR
275static size_t shell_input_line_index;
276static size_t shell_input_line_size; /* Amount allocated for shell_input_line. */
277static size_t shell_input_line_len; /* strlen (shell_input_line) */
726f6388
JA
278
279/* Either zero or EOF. */
ccc6cda3
JA
280static int shell_input_line_terminator;
281
282/* The line number in a script on which a function definition starts. */
283static int function_dstart;
284
285/* The line number in a script on which a function body starts. */
286static int function_bstart;
726f6388 287
bb70624e
JA
288/* The line number in a script at which an arithmetic for command starts. */
289static int arith_for_lineno;
290
0001803f
CR
291/* The decoded prompt string. Used if READLINE is not defined or if
292 editing is turned off. Analogous to current_readline_prompt. */
293static char *current_decoded_prompt;
3185942a
JA
294
295/* The last read token, or NULL. read_token () uses this for context
296 checking. */
297static int last_read_token;
298
299/* The token read prior to last_read_token. */
300static int token_before_that;
301
302/* The token read prior to token_before_that. */
303static int two_tokens_ago;
304
0001803f
CR
305static int global_extglob;
306
b80f6443
JA
307/* The line number in a script where the word in a `case WORD', `select WORD'
308 or `for WORD' begins. This is a nested command maximum, since the array
309 index is decremented after a case, select, or for command is parsed. */
310#define MAX_CASE_NEST 128
90a39f32 311static int word_lineno[MAX_CASE_NEST+1];
b80f6443
JA
312static int word_top = -1;
313
314/* If non-zero, it is the token that we want read_token to return
315 regardless of what text is (or isn't) present to be read. This
316 is reset by read_token. If token_to_read == WORD or
317 ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */
318static int token_to_read;
319static WORD_DESC *word_desc_to_read;
320
0001803f 321static REDIRECTEE source;
726f6388 322static REDIRECTEE redir;
d233b485
CR
323
324static FILE *yyoutstream;
325static FILE *yyerrstream;
726f6388
JA
326%}
327
328%union {
329 WORD_DESC *word; /* the word that we read. */
330 int number; /* the number that we read. */
331 WORD_LIST *word_list;
332 COMMAND *command;
333 REDIRECT *redirect;
334 ELEMENT element;
335 PATTERN_LIST *pattern;
336}
337
338/* Reserved words. Members of the first group are only recognized
339 in the case that they are preceded by a list_terminator. Members
cce855bc
JA
340 of the second group are for [[...]] commands. Members of the
341 third group are recognized only under special circumstances. */
3185942a 342%token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION COPROC
cce855bc 343%token COND_START COND_END COND_ERROR
495aee44 344%token IN BANG TIME TIMEOPT TIMEIGN
726f6388
JA
345
346/* More general tokens. yylex () knows how to make these. */
0001803f 347%token <word> WORD ASSIGNMENT_WORD REDIR_WORD
726f6388 348%token <number> NUMBER
bb70624e 349%token <word_list> ARITH_CMD ARITH_FOR_EXPRS
cce855bc 350%token <command> COND_CMD
7117c2d2 351%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
3185942a
JA
352%token GREATER_AND SEMI_SEMI SEMI_AND SEMI_SEMI_AND
353%token LESS_LESS_MINUS AND_GREATER AND_GREATER_GREATER LESS_GREATER
354%token GREATER_BAR BAR_AND
726f6388
JA
355
356/* The types that the various syntactical units return. */
357
ccc6cda3
JA
358%type <command> inputunit command pipeline pipeline_command
359%type <command> list list0 list1 compound_list simple_list simple_list1
360%type <command> simple_command shell_command
361%type <command> for_command select_command case_command group_command
cce855bc
JA
362%type <command> arith_command
363%type <command> cond_command
bb70624e 364%type <command> arith_for_command
3185942a 365%type <command> coproc
28ef6c31 366%type <command> function_def function_body if_command elif_clause subshell
ccc6cda3 367%type <redirect> redirection redirection_list
726f6388 368%type <element> simple_command_element
ccc6cda3
JA
369%type <word_list> word_list pattern
370%type <pattern> pattern_list case_clause_sequence case_clause
371%type <number> timespec
b80f6443 372%type <number> list_terminator
726f6388
JA
373
374%start inputunit
375
376%left '&' ';' '\n' yacc_EOF
377%left AND_AND OR_OR
3185942a 378%right '|' BAR_AND
726f6388
JA
379%%
380
7117c2d2 381inputunit: simple_list simple_list_terminator
726f6388
JA
382 {
383 /* Case of regular command. Discard the error
384 safety net,and return the command just parsed. */
385 global_command = $1;
386 eof_encountered = 0;
7117c2d2 387 /* discard_parser_constructs (0); */
3185942a
JA
388 if (parser_state & PST_CMDSUBST)
389 parser_state |= PST_EOFTOKEN;
726f6388
JA
390 YYACCEPT;
391 }
392 | '\n'
393 {
394 /* Case of regular command, but not a very
395 interesting one. Return a NULL command. */
396 global_command = (COMMAND *)NULL;
3185942a
JA
397 if (parser_state & PST_CMDSUBST)
398 parser_state |= PST_EOFTOKEN;
726f6388
JA
399 YYACCEPT;
400 }
ccc6cda3 401 | error '\n'
726f6388
JA
402 {
403 /* Error during parsing. Return NULL command. */
404 global_command = (COMMAND *)NULL;
405 eof_encountered = 0;
7117c2d2 406 /* discard_parser_constructs (1); */
3185942a 407 if (interactive && parse_and_execute_level == 0)
726f6388
JA
408 {
409 YYACCEPT;
410 }
411 else
412 {
413 YYABORT;
414 }
415 }
d233b485
CR
416 | error yacc_EOF
417 {
418 /* EOF after an error. Do ignoreeof or not. Really
419 only interesting in non-interactive shells */
420 global_command = (COMMAND *)NULL;
421 if (last_command_exit_value == 0)
422 last_command_exit_value = EX_BADUSAGE; /* force error return */
423 handle_eof_input_unit ();
424 if (interactive && parse_and_execute_level == 0)
425 {
426 YYACCEPT;
427 }
428 else
429 {
430 YYABORT;
431 }
432 }
726f6388
JA
433 | yacc_EOF
434 {
ccc6cda3 435 /* Case of EOF seen by itself. Do ignoreeof or
726f6388
JA
436 not. */
437 global_command = (COMMAND *)NULL;
438 handle_eof_input_unit ();
439 YYACCEPT;
440 }
441 ;
442
ccc6cda3
JA
443word_list: WORD
444 { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
445 | word_list WORD
726f6388
JA
446 { $$ = make_word_list ($2, $1); }
447 ;
448
449redirection: '>' WORD
450 {
0001803f 451 source.dest = 1;
726f6388 452 redir.filename = $2;
0001803f 453 $$ = make_redirection (source, r_output_direction, redir, 0);
726f6388
JA
454 }
455 | '<' WORD
456 {
0001803f 457 source.dest = 0;
726f6388 458 redir.filename = $2;
0001803f 459 $$ = make_redirection (source, r_input_direction, redir, 0);
726f6388
JA
460 }
461 | NUMBER '>' WORD
462 {
0001803f 463 source.dest = $1;
726f6388 464 redir.filename = $3;
0001803f 465 $$ = make_redirection (source, r_output_direction, redir, 0);
726f6388
JA
466 }
467 | NUMBER '<' WORD
468 {
0001803f
CR
469 source.dest = $1;
470 redir.filename = $3;
471 $$ = make_redirection (source, r_input_direction, redir, 0);
472 }
473 | REDIR_WORD '>' WORD
474 {
475 source.filename = $1;
726f6388 476 redir.filename = $3;
0001803f
CR
477 $$ = make_redirection (source, r_output_direction, redir, REDIR_VARASSIGN);
478 }
479 | REDIR_WORD '<' WORD
480 {
481 source.filename = $1;
482 redir.filename = $3;
483 $$ = make_redirection (source, r_input_direction, redir, REDIR_VARASSIGN);
726f6388
JA
484 }
485 | GREATER_GREATER WORD
486 {
0001803f 487 source.dest = 1;
726f6388 488 redir.filename = $2;
0001803f 489 $$ = make_redirection (source, r_appending_to, redir, 0);
726f6388
JA
490 }
491 | NUMBER GREATER_GREATER WORD
492 {
0001803f
CR
493 source.dest = $1;
494 redir.filename = $3;
495 $$ = make_redirection (source, r_appending_to, redir, 0);
496 }
497 | REDIR_WORD GREATER_GREATER WORD
498 {
499 source.filename = $1;
500 redir.filename = $3;
501 $$ = make_redirection (source, r_appending_to, redir, REDIR_VARASSIGN);
502 }
503 | GREATER_BAR WORD
504 {
505 source.dest = 1;
506 redir.filename = $2;
507 $$ = make_redirection (source, r_output_force, redir, 0);
508 }
509 | NUMBER GREATER_BAR WORD
510 {
511 source.dest = $1;
512 redir.filename = $3;
513 $$ = make_redirection (source, r_output_force, redir, 0);
514 }
515 | REDIR_WORD GREATER_BAR WORD
516 {
517 source.filename = $1;
518 redir.filename = $3;
519 $$ = make_redirection (source, r_output_force, redir, REDIR_VARASSIGN);
520 }
521 | LESS_GREATER WORD
522 {
523 source.dest = 0;
524 redir.filename = $2;
525 $$ = make_redirection (source, r_input_output, redir, 0);
526 }
527 | NUMBER LESS_GREATER WORD
528 {
529 source.dest = $1;
726f6388 530 redir.filename = $3;
0001803f
CR
531 $$ = make_redirection (source, r_input_output, redir, 0);
532 }
533 | REDIR_WORD LESS_GREATER WORD
534 {
535 source.filename = $1;
536 redir.filename = $3;
537 $$ = make_redirection (source, r_input_output, redir, REDIR_VARASSIGN);
726f6388
JA
538 }
539 | LESS_LESS WORD
540 {
0001803f 541 source.dest = 0;
726f6388 542 redir.filename = $2;
0001803f 543 $$ = make_redirection (source, r_reading_until, redir, 0);
90a39f32 544 push_heredoc ($$);
726f6388
JA
545 }
546 | NUMBER LESS_LESS WORD
547 {
0001803f
CR
548 source.dest = $1;
549 redir.filename = $3;
550 $$ = make_redirection (source, r_reading_until, redir, 0);
90a39f32 551 push_heredoc ($$);
0001803f
CR
552 }
553 | REDIR_WORD LESS_LESS WORD
554 {
555 source.filename = $1;
726f6388 556 redir.filename = $3;
0001803f 557 $$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN);
90a39f32 558 push_heredoc ($$);
0001803f
CR
559 }
560 | LESS_LESS_MINUS WORD
561 {
562 source.dest = 0;
563 redir.filename = $2;
564 $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
90a39f32 565 push_heredoc ($$);
0001803f
CR
566 }
567 | NUMBER LESS_LESS_MINUS WORD
568 {
569 source.dest = $1;
570 redir.filename = $3;
571 $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
90a39f32 572 push_heredoc ($$);
0001803f
CR
573 }
574 | REDIR_WORD LESS_LESS_MINUS WORD
575 {
576 source.filename = $1;
577 redir.filename = $3;
578 $$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN);
90a39f32 579 push_heredoc ($$);
726f6388 580 }
7117c2d2
JA
581 | LESS_LESS_LESS WORD
582 {
0001803f 583 source.dest = 0;
7117c2d2 584 redir.filename = $2;
0001803f 585 $$ = make_redirection (source, r_reading_string, redir, 0);
7117c2d2
JA
586 }
587 | NUMBER LESS_LESS_LESS WORD
588 {
0001803f 589 source.dest = $1;
7117c2d2 590 redir.filename = $3;
0001803f
CR
591 $$ = make_redirection (source, r_reading_string, redir, 0);
592 }
593 | REDIR_WORD LESS_LESS_LESS WORD
594 {
595 source.filename = $1;
596 redir.filename = $3;
597 $$ = make_redirection (source, r_reading_string, redir, REDIR_VARASSIGN);
7117c2d2 598 }
726f6388
JA
599 | LESS_AND NUMBER
600 {
0001803f 601 source.dest = 0;
726f6388 602 redir.dest = $2;
0001803f 603 $$ = make_redirection (source, r_duplicating_input, redir, 0);
726f6388
JA
604 }
605 | NUMBER LESS_AND NUMBER
606 {
0001803f
CR
607 source.dest = $1;
608 redir.dest = $3;
609 $$ = make_redirection (source, r_duplicating_input, redir, 0);
610 }
611 | REDIR_WORD LESS_AND NUMBER
612 {
613 source.filename = $1;
726f6388 614 redir.dest = $3;
0001803f 615 $$ = make_redirection (source, r_duplicating_input, redir, REDIR_VARASSIGN);
726f6388
JA
616 }
617 | GREATER_AND NUMBER
618 {
0001803f 619 source.dest = 1;
726f6388 620 redir.dest = $2;
0001803f 621 $$ = make_redirection (source, r_duplicating_output, redir, 0);
726f6388
JA
622 }
623 | NUMBER GREATER_AND NUMBER
624 {
0001803f 625 source.dest = $1;
726f6388 626 redir.dest = $3;
0001803f
CR
627 $$ = make_redirection (source, r_duplicating_output, redir, 0);
628 }
629 | REDIR_WORD GREATER_AND NUMBER
630 {
631 source.filename = $1;
632 redir.dest = $3;
633 $$ = make_redirection (source, r_duplicating_output, redir, REDIR_VARASSIGN);
726f6388
JA
634 }
635 | LESS_AND WORD
636 {
0001803f 637 source.dest = 0;
726f6388 638 redir.filename = $2;
0001803f 639 $$ = make_redirection (source, r_duplicating_input_word, redir, 0);
726f6388
JA
640 }
641 | NUMBER LESS_AND WORD
642 {
0001803f
CR
643 source.dest = $1;
644 redir.filename = $3;
645 $$ = make_redirection (source, r_duplicating_input_word, redir, 0);
646 }
647 | REDIR_WORD LESS_AND WORD
648 {
649 source.filename = $1;
726f6388 650 redir.filename = $3;
0001803f 651 $$ = make_redirection (source, r_duplicating_input_word, redir, REDIR_VARASSIGN);
726f6388
JA
652 }
653 | GREATER_AND WORD
654 {
0001803f 655 source.dest = 1;
726f6388 656 redir.filename = $2;
0001803f 657 $$ = make_redirection (source, r_duplicating_output_word, redir, 0);
726f6388
JA
658 }
659 | NUMBER GREATER_AND WORD
660 {
0001803f 661 source.dest = $1;
726f6388 662 redir.filename = $3;
0001803f 663 $$ = make_redirection (source, r_duplicating_output_word, redir, 0);
726f6388 664 }
0001803f 665 | REDIR_WORD GREATER_AND WORD
726f6388 666 {
0001803f 667 source.filename = $1;
726f6388 668 redir.filename = $3;
0001803f 669 $$ = make_redirection (source, r_duplicating_output_word, redir, REDIR_VARASSIGN);
726f6388
JA
670 }
671 | GREATER_AND '-'
672 {
0001803f 673 source.dest = 1;
f73dda09 674 redir.dest = 0;
0001803f 675 $$ = make_redirection (source, r_close_this, redir, 0);
726f6388
JA
676 }
677 | NUMBER GREATER_AND '-'
678 {
0001803f 679 source.dest = $1;
f73dda09 680 redir.dest = 0;
0001803f 681 $$ = make_redirection (source, r_close_this, redir, 0);
726f6388 682 }
0001803f 683 | REDIR_WORD GREATER_AND '-'
726f6388 684 {
0001803f 685 source.filename = $1;
f73dda09 686 redir.dest = 0;
0001803f 687 $$ = make_redirection (source, r_close_this, redir, REDIR_VARASSIGN);
726f6388 688 }
0001803f 689 | LESS_AND '-'
726f6388 690 {
0001803f 691 source.dest = 0;
f73dda09 692 redir.dest = 0;
0001803f 693 $$ = make_redirection (source, r_close_this, redir, 0);
726f6388 694 }
0001803f 695 | NUMBER LESS_AND '-'
3185942a 696 {
0001803f
CR
697 source.dest = $1;
698 redir.dest = 0;
699 $$ = make_redirection (source, r_close_this, redir, 0);
3185942a 700 }
0001803f 701 | REDIR_WORD LESS_AND '-'
726f6388 702 {
0001803f
CR
703 source.filename = $1;
704 redir.dest = 0;
705 $$ = make_redirection (source, r_close_this, redir, REDIR_VARASSIGN);
726f6388 706 }
0001803f 707 | AND_GREATER WORD
726f6388 708 {
0001803f 709 source.dest = 1;
726f6388 710 redir.filename = $2;
0001803f 711 $$ = make_redirection (source, r_err_and_out, redir, 0);
ccc6cda3 712 }
0001803f 713 | AND_GREATER_GREATER WORD
726f6388 714 {
0001803f 715 source.dest = 1;
726f6388 716 redir.filename = $2;
0001803f 717 $$ = make_redirection (source, r_append_err_and_out, redir, 0);
726f6388
JA
718 }
719 ;
720
721simple_command_element: WORD
722 { $$.word = $1; $$.redirect = 0; }
723 | ASSIGNMENT_WORD
724 { $$.word = $1; $$.redirect = 0; }
725 | redirection
726 { $$.redirect = $1; $$.word = 0; }
727 ;
728
ccc6cda3 729redirection_list: redirection
726f6388
JA
730 {
731 $$ = $1;
732 }
ccc6cda3
JA
733 | redirection_list redirection
734 {
735 register REDIRECT *t;
726f6388 736
ccc6cda3
JA
737 for (t = $1; t->next; t = t->next)
738 ;
739 t->next = $2;
726f6388
JA
740 $$ = $1;
741 }
742 ;
743
744simple_command: simple_command_element
745 { $$ = make_simple_command ($1, (COMMAND *)NULL); }
746 | simple_command simple_command_element
747 { $$ = make_simple_command ($2, $1); }
748 ;
749
750command: simple_command
751 { $$ = clean_simple_command ($1); }
752 | shell_command
753 { $$ = $1; }
ccc6cda3 754 | shell_command redirection_list
726f6388 755 {
ccc6cda3
JA
756 COMMAND *tc;
757
758 tc = $1;
d233b485 759 if (tc && tc->redirects)
726f6388
JA
760 {
761 register REDIRECT *t;
ccc6cda3 762 for (t = tc->redirects; t->next; t = t->next)
726f6388
JA
763 ;
764 t->next = $2;
765 }
d233b485 766 else if (tc)
ccc6cda3 767 tc->redirects = $2;
726f6388
JA
768 $$ = $1;
769 }
28ef6c31
JA
770 | function_def
771 { $$ = $1; }
3185942a
JA
772 | coproc
773 { $$ = $1; }
726f6388
JA
774 ;
775
ccc6cda3
JA
776shell_command: for_command
777 { $$ = $1; }
778 | case_command
779 { $$ = $1; }
780 | WHILE compound_list DO compound_list DONE
726f6388 781 { $$ = make_while_command ($2, $4); }
ccc6cda3 782 | UNTIL compound_list DO compound_list DONE
726f6388
JA
783 { $$ = make_until_command ($2, $4); }
784 | select_command
785 { $$ = $1; }
786 | if_command
787 { $$ = $1; }
788 | subshell
789 { $$ = $1; }
790 | group_command
791 { $$ = $1; }
cce855bc
JA
792 | arith_command
793 { $$ = $1; }
794 | cond_command
795 { $$ = $1; }
bb70624e
JA
796 | arith_for_command
797 { $$ = $1; }
726f6388
JA
798 ;
799
d166f048 800for_command: FOR WORD newline_list DO compound_list DONE
b80f6443
JA
801 {
802 $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
803 if (word_top > 0) word_top--;
804 }
d166f048 805 | FOR WORD newline_list '{' compound_list '}'
b80f6443
JA
806 {
807 $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
808 if (word_top > 0) word_top--;
809 }
d166f048 810 | FOR WORD ';' newline_list DO compound_list DONE
b80f6443
JA
811 {
812 $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
813 if (word_top > 0) word_top--;
814 }
d166f048 815 | FOR WORD ';' newline_list '{' compound_list '}'
b80f6443
JA
816 {
817 $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
818 if (word_top > 0) word_top--;
819 }
d166f048 820 | FOR WORD newline_list IN word_list list_terminator newline_list DO compound_list DONE
b80f6443
JA
821 {
822 $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
823 if (word_top > 0) word_top--;
824 }
d166f048 825 | FOR WORD newline_list IN word_list list_terminator newline_list '{' compound_list '}'
b80f6443
JA
826 {
827 $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
828 if (word_top > 0) word_top--;
829 }
f73dda09 830 | FOR WORD newline_list IN list_terminator newline_list DO compound_list DONE
b80f6443
JA
831 {
832 $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
833 if (word_top > 0) word_top--;
834 }
f73dda09 835 | FOR WORD newline_list IN list_terminator newline_list '{' compound_list '}'
b80f6443
JA
836 {
837 $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
838 if (word_top > 0) word_top--;
839 }
ccc6cda3
JA
840 ;
841
bb70624e 842arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE
b80f6443
JA
843 {
844 $$ = make_arith_for_command ($2, $6, arith_for_lineno);
d233b485 845 if ($$ == 0) YYERROR;
b80f6443
JA
846 if (word_top > 0) word_top--;
847 }
bb70624e 848 | FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
b80f6443
JA
849 {
850 $$ = make_arith_for_command ($2, $6, arith_for_lineno);
d233b485 851 if ($$ == 0) YYERROR;
b80f6443
JA
852 if (word_top > 0) word_top--;
853 }
28ef6c31 854 | FOR ARITH_FOR_EXPRS DO compound_list DONE
b80f6443
JA
855 {
856 $$ = make_arith_for_command ($2, $4, arith_for_lineno);
d233b485 857 if ($$ == 0) YYERROR;
b80f6443
JA
858 if (word_top > 0) word_top--;
859 }
28ef6c31 860 | FOR ARITH_FOR_EXPRS '{' compound_list '}'
b80f6443
JA
861 {
862 $$ = make_arith_for_command ($2, $4, arith_for_lineno);
d233b485 863 if ($$ == 0) YYERROR;
b80f6443
JA
864 if (word_top > 0) word_top--;
865 }
bb70624e 866 ;
28ef6c31 867
ccc6cda3 868select_command: SELECT WORD newline_list DO list DONE
726f6388 869 {
b80f6443
JA
870 $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
871 if (word_top > 0) word_top--;
726f6388 872 }
ccc6cda3 873 | SELECT WORD newline_list '{' list '}'
726f6388 874 {
b80f6443
JA
875 $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
876 if (word_top > 0) word_top--;
726f6388 877 }
ccc6cda3 878 | SELECT WORD ';' newline_list DO list DONE
726f6388 879 {
b80f6443
JA
880 $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
881 if (word_top > 0) word_top--;
726f6388 882 }
ccc6cda3 883 | SELECT WORD ';' newline_list '{' list '}'
726f6388 884 {
b80f6443
JA
885 $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
886 if (word_top > 0) word_top--;
726f6388 887 }
ccc6cda3 888 | SELECT WORD newline_list IN word_list list_terminator newline_list DO list DONE
726f6388 889 {
b80f6443
JA
890 $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
891 if (word_top > 0) word_top--;
726f6388 892 }
ccc6cda3 893 | SELECT WORD newline_list IN word_list list_terminator newline_list '{' list '}'
726f6388 894 {
b80f6443
JA
895 $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
896 if (word_top > 0) word_top--;
726f6388 897 }
d233b485
CR
898 | SELECT WORD newline_list IN list_terminator newline_list DO compound_list DONE
899 {
900 $$ = make_select_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
901 if (word_top > 0) word_top--;
902 }
903 | SELECT WORD newline_list IN list_terminator newline_list '{' compound_list '}'
904 {
905 $$ = make_select_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
906 if (word_top > 0) word_top--;
907 }
726f6388
JA
908 ;
909
ccc6cda3 910case_command: CASE WORD newline_list IN newline_list ESAC
b80f6443
JA
911 {
912 $$ = make_case_command ($2, (PATTERN_LIST *)NULL, word_lineno[word_top]);
913 if (word_top > 0) word_top--;
914 }
ccc6cda3 915 | CASE WORD newline_list IN case_clause_sequence newline_list ESAC
b80f6443
JA
916 {
917 $$ = make_case_command ($2, $5, word_lineno[word_top]);
918 if (word_top > 0) word_top--;
919 }
ccc6cda3 920 | CASE WORD newline_list IN case_clause ESAC
b80f6443
JA
921 {
922 $$ = make_case_command ($2, $5, word_lineno[word_top]);
923 if (word_top > 0) word_top--;
924 }
ccc6cda3 925 ;
726f6388 926
28ef6c31 927function_def: WORD '(' ')' newline_list function_body
ccc6cda3 928 { $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
726f6388 929
28ef6c31 930 | FUNCTION WORD '(' ')' newline_list function_body
ccc6cda3 931 { $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
726f6388 932
28ef6c31 933 | FUNCTION WORD newline_list function_body
ccc6cda3 934 { $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
726f6388
JA
935 ;
936
28ef6c31
JA
937function_body: shell_command
938 { $$ = $1; }
939 | shell_command redirection_list
940 {
941 COMMAND *tc;
942
943 tc = $1;
944 /* According to Posix.2 3.9.5, redirections
945 specified after the body of a function should
946 be attached to the function and performed when
947 the function is executed, not as part of the
948 function definition command. */
949 /* XXX - I don't think it matters, but we might
950 want to change this in the future to avoid
951 problems differentiating between a function
952 definition with a redirection and a function
953 definition containing a single command with a
954 redirection. The two are semantically equivalent,
955 though -- the only difference is in how the
956 command printing code displays the redirections. */
d233b485 957 if (tc && tc->redirects)
28ef6c31
JA
958 {
959 register REDIRECT *t;
960 for (t = tc->redirects; t->next; t = t->next)
961 ;
962 t->next = $2;
963 }
d233b485 964 else if (tc)
28ef6c31
JA
965 tc->redirects = $2;
966 $$ = $1;
967 }
968 ;
969
ccc6cda3 970subshell: '(' compound_list ')'
bb70624e
JA
971 {
972 $$ = make_subshell_command ($2);
973 $$->flags |= CMD_WANT_SUBSHELL;
974 }
726f6388 975 ;
ccc6cda3 976
3185942a
JA
977coproc: COPROC shell_command
978 {
979 $$ = make_coproc_command ("COPROC", $2);
980 $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
981 }
982 | COPROC shell_command redirection_list
983 {
984 COMMAND *tc;
985
986 tc = $2;
d233b485 987 if (tc && tc->redirects)
3185942a
JA
988 {
989 register REDIRECT *t;
990 for (t = tc->redirects; t->next; t = t->next)
991 ;
992 t->next = $3;
993 }
d233b485 994 else if (tc)
3185942a
JA
995 tc->redirects = $3;
996 $$ = make_coproc_command ("COPROC", $2);
997 $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
998 }
999 | COPROC WORD shell_command
1000 {
1001 $$ = make_coproc_command ($2->word, $3);
1002 $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
1003 }
1004 | COPROC WORD shell_command redirection_list
1005 {
1006 COMMAND *tc;
1007
1008 tc = $3;
d233b485 1009 if (tc && tc->redirects)
3185942a
JA
1010 {
1011 register REDIRECT *t;
1012 for (t = tc->redirects; t->next; t = t->next)
1013 ;
1014 t->next = $4;
1015 }
d233b485 1016 else if (tc)
3185942a
JA
1017 tc->redirects = $4;
1018 $$ = make_coproc_command ($2->word, $3);
1019 $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
1020 }
1021 | COPROC simple_command
1022 {
1023 $$ = make_coproc_command ("COPROC", clean_simple_command ($2));
1024 $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
1025 }
1026 ;
1027
ccc6cda3 1028if_command: IF compound_list THEN compound_list FI
726f6388 1029 { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
ccc6cda3 1030 | IF compound_list THEN compound_list ELSE compound_list FI
726f6388 1031 { $$ = make_if_command ($2, $4, $6); }
ccc6cda3 1032 | IF compound_list THEN compound_list elif_clause FI
726f6388
JA
1033 { $$ = make_if_command ($2, $4, $5); }
1034 ;
1035
1036
28ef6c31 1037group_command: '{' compound_list '}'
726f6388
JA
1038 { $$ = make_group_command ($2); }
1039 ;
1040
cce855bc
JA
1041arith_command: ARITH_CMD
1042 { $$ = make_arith_command ($1); }
1043 ;
1044
1045cond_command: COND_START COND_CMD COND_END
1046 { $$ = $2; }
1047 ;
1048
ccc6cda3 1049elif_clause: ELIF compound_list THEN compound_list
726f6388 1050 { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
ccc6cda3 1051 | ELIF compound_list THEN compound_list ELSE compound_list
726f6388 1052 { $$ = make_if_command ($2, $4, $6); }
ccc6cda3 1053 | ELIF compound_list THEN compound_list elif_clause
726f6388
JA
1054 { $$ = make_if_command ($2, $4, $5); }
1055 ;
1056
ccc6cda3
JA
1057case_clause: pattern_list
1058 | case_clause_sequence pattern_list
726f6388
JA
1059 { $2->next = $1; $$ = $2; }
1060 ;
1061
ccc6cda3 1062pattern_list: newline_list pattern ')' compound_list
726f6388 1063 { $$ = make_pattern_list ($2, $4); }
ccc6cda3 1064 | newline_list pattern ')' newline_list
726f6388 1065 { $$ = make_pattern_list ($2, (COMMAND *)NULL); }
ccc6cda3 1066 | newline_list '(' pattern ')' compound_list
726f6388 1067 { $$ = make_pattern_list ($3, $5); }
ccc6cda3 1068 | newline_list '(' pattern ')' newline_list
726f6388
JA
1069 { $$ = make_pattern_list ($3, (COMMAND *)NULL); }
1070 ;
1071
ccc6cda3 1072case_clause_sequence: pattern_list SEMI_SEMI
3185942a 1073 { $$ = $1; }
ccc6cda3 1074 | case_clause_sequence pattern_list SEMI_SEMI
726f6388 1075 { $2->next = $1; $$ = $2; }
3185942a
JA
1076 | pattern_list SEMI_AND
1077 { $1->flags |= CASEPAT_FALLTHROUGH; $$ = $1; }
1078 | case_clause_sequence pattern_list SEMI_AND
1079 { $2->flags |= CASEPAT_FALLTHROUGH; $2->next = $1; $$ = $2; }
1080 | pattern_list SEMI_SEMI_AND
1081 { $1->flags |= CASEPAT_TESTNEXT; $$ = $1; }
1082 | case_clause_sequence pattern_list SEMI_SEMI_AND
1083 { $2->flags |= CASEPAT_TESTNEXT; $2->next = $1; $$ = $2; }
726f6388
JA
1084 ;
1085
726f6388
JA
1086pattern: WORD
1087 { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
1088 | pattern '|' WORD
1089 { $$ = make_word_list ($3, $1); }
1090 ;
1091
1092/* A list allows leading or trailing newlines and
1093 newlines as operators (equivalent to semicolons).
1094 It must end with a newline or semicolon.
1095 Lists are used within commands such as if, for, while. */
1096
ccc6cda3 1097list: newline_list list0
726f6388
JA
1098 {
1099 $$ = $2;
1100 if (need_here_doc)
1101 gather_here_documents ();
1102 }
1103 ;
1104
ccc6cda3
JA
1105compound_list: list
1106 | newline_list list1
1107 {
1108 $$ = $2;
1109 }
1110 ;
1111
1112list0: list1 '\n' newline_list
1113 | list1 '&' newline_list
726f6388
JA
1114 {
1115 if ($1->type == cm_connection)
1116 $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
1117 else
1118 $$ = command_connect ($1, (COMMAND *)NULL, '&');
1119 }
ccc6cda3 1120 | list1 ';' newline_list
726f6388
JA
1121
1122 ;
1123
ccc6cda3 1124list1: list1 AND_AND newline_list list1
726f6388 1125 { $$ = command_connect ($1, $4, AND_AND); }
ccc6cda3 1126 | list1 OR_OR newline_list list1
726f6388 1127 { $$ = command_connect ($1, $4, OR_OR); }
ccc6cda3 1128 | list1 '&' newline_list list1
726f6388
JA
1129 {
1130 if ($1->type == cm_connection)
1131 $$ = connect_async_list ($1, $4, '&');
1132 else
1133 $$ = command_connect ($1, $4, '&');
1134 }
ccc6cda3 1135 | list1 ';' newline_list list1
726f6388 1136 { $$ = command_connect ($1, $4, ';'); }
ccc6cda3 1137 | list1 '\n' newline_list list1
726f6388 1138 { $$ = command_connect ($1, $4, ';'); }
ccc6cda3 1139 | pipeline_command
726f6388 1140 { $$ = $1; }
726f6388
JA
1141 ;
1142
7117c2d2
JA
1143simple_list_terminator: '\n'
1144 | yacc_EOF
1145 ;
1146
726f6388 1147list_terminator:'\n'
b80f6443 1148 { $$ = '\n'; }
726f6388 1149 | ';'
b80f6443 1150 { $$ = ';'; }
726f6388 1151 | yacc_EOF
b80f6443 1152 { $$ = yacc_EOF; }
726f6388
JA
1153 ;
1154
ccc6cda3
JA
1155newline_list:
1156 | newline_list '\n'
726f6388
JA
1157 ;
1158
1159/* A simple_list is a list that contains no significant newlines
1160 and no leading or trailing newlines. Newlines are allowed
1161 only following operators, where they are not significant.
1162
1163 This is what an inputunit consists of. */
1164
1165simple_list: simple_list1
1166 {
1167 $$ = $1;
1168 if (need_here_doc)
1169 gather_here_documents ();
3185942a
JA
1170 if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
1171 {
1172 global_command = $1;
1173 eof_encountered = 0;
1174 rewind_input_string ();
1175 YYACCEPT;
1176 }
726f6388
JA
1177 }
1178 | simple_list1 '&'
1179 {
1180 if ($1->type == cm_connection)
1181 $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
1182 else
1183 $$ = command_connect ($1, (COMMAND *)NULL, '&');
1184 if (need_here_doc)
1185 gather_here_documents ();
3185942a
JA
1186 if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
1187 {
1188 global_command = $1;
1189 eof_encountered = 0;
1190 rewind_input_string ();
1191 YYACCEPT;
1192 }
726f6388
JA
1193 }
1194 | simple_list1 ';'
1195 {
1196 $$ = $1;
1197 if (need_here_doc)
1198 gather_here_documents ();
3185942a
JA
1199 if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
1200 {
1201 global_command = $1;
1202 eof_encountered = 0;
1203 rewind_input_string ();
1204 YYACCEPT;
1205 }
726f6388
JA
1206 }
1207 ;
1208
ccc6cda3 1209simple_list1: simple_list1 AND_AND newline_list simple_list1
726f6388 1210 { $$ = command_connect ($1, $4, AND_AND); }
ccc6cda3 1211 | simple_list1 OR_OR newline_list simple_list1
726f6388
JA
1212 { $$ = command_connect ($1, $4, OR_OR); }
1213 | simple_list1 '&' simple_list1
1214 {
1215 if ($1->type == cm_connection)
1216 $$ = connect_async_list ($1, $3, '&');
1217 else
1218 $$ = command_connect ($1, $3, '&');
1219 }
1220 | simple_list1 ';' simple_list1
1221 { $$ = command_connect ($1, $3, ';'); }
ccc6cda3
JA
1222
1223 | pipeline_command
1224 { $$ = $1; }
1225 ;
1226
1227pipeline_command: pipeline
495aee44
CR
1228 { $$ = $1; }
1229 | BANG pipeline_command
726f6388 1230 {
95732b49 1231 if ($2)
495aee44 1232 $2->flags ^= CMD_INVERT_RETURN; /* toggle */
726f6388
JA
1233 $$ = $2;
1234 }
495aee44 1235 | timespec pipeline_command
ccc6cda3 1236 {
95732b49
JA
1237 if ($2)
1238 $2->flags |= $1;
ccc6cda3
JA
1239 $$ = $2;
1240 }
b80f6443
JA
1241 | timespec list_terminator
1242 {
1243 ELEMENT x;
1244
1245 /* Boy, this is unclean. `time' by itself can
1246 time a null command. We cheat and push a
1247 newline back if the list_terminator was a newline
1248 to avoid the double-newline problem (one to
1249 terminate this, one to terminate the command) */
1250 x.word = 0;
1251 x.redirect = 0;
1252 $$ = make_simple_command (x, (COMMAND *)NULL);
1253 $$->flags |= $1;
1254 /* XXX - let's cheat and push a newline back */
1255 if ($2 == '\n')
1256 token_to_read = '\n';
a0c0a00f
CR
1257 else if ($2 == ';')
1258 token_to_read = ';';
d233b485 1259 parser_state &= ~PST_REDIRLIST; /* make_simple_command sets this */
b80f6443 1260 }
495aee44
CR
1261 | BANG list_terminator
1262 {
1263 ELEMENT x;
1264
1265 /* This is just as unclean. Posix says that `!'
1266 by itself should be equivalent to `false'.
1267 We cheat and push a
1268 newline back if the list_terminator was a newline
1269 to avoid the double-newline problem (one to
1270 terminate this, one to terminate the command) */
1271 x.word = 0;
1272 x.redirect = 0;
1273 $$ = make_simple_command (x, (COMMAND *)NULL);
1274 $$->flags |= CMD_INVERT_RETURN;
1275 /* XXX - let's cheat and push a newline back */
1276 if ($2 == '\n')
1277 token_to_read = '\n';
a0c0a00f
CR
1278 if ($2 == ';')
1279 token_to_read = ';';
d233b485 1280 parser_state &= ~PST_REDIRLIST; /* make_simple_command sets this */
495aee44 1281 }
726f6388
JA
1282 ;
1283
3185942a 1284pipeline: pipeline '|' newline_list pipeline
726f6388 1285 { $$ = command_connect ($1, $4, '|'); }
3185942a
JA
1286 | pipeline BAR_AND newline_list pipeline
1287 {
1288 /* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */
1289 COMMAND *tc;
0001803f 1290 REDIRECTEE rd, sd;
3185942a
JA
1291 REDIRECT *r;
1292
89a92869 1293 tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
0001803f 1294 sd.dest = 2;
3185942a 1295 rd.dest = 1;
0001803f 1296 r = make_redirection (sd, r_duplicating_output, rd, 0);
3185942a
JA
1297 if (tc->redirects)
1298 {
1299 register REDIRECT *t;
1300 for (t = tc->redirects; t->next; t = t->next)
1301 ;
1302 t->next = r;
1303 }
1304 else
1305 tc->redirects = r;
1306
1307 $$ = command_connect ($1, $4, '|');
1308 }
726f6388
JA
1309 | command
1310 { $$ = $1; }
1311 ;
ccc6cda3
JA
1312
1313timespec: TIME
1314 { $$ = CMD_TIME_PIPELINE; }
1315 | TIME TIMEOPT
1316 { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
495aee44
CR
1317 | TIME TIMEOPT TIMEIGN
1318 { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
ccc6cda3 1319 ;
726f6388
JA
1320%%
1321
1322/* Initial size to allocate for tokens, and the
1323 amount to grow them by. */
d166f048 1324#define TOKEN_DEFAULT_INITIAL_SIZE 496
726f6388
JA
1325#define TOKEN_DEFAULT_GROW_SIZE 512
1326
b80f6443
JA
1327/* Should we call prompt_again? */
1328#define SHOULD_PROMPT() \
1329 (interactive && (bash_input.type == st_stdin || bash_input.type == st_stream))
1330
1331#if defined (ALIAS)
1332# define expanding_alias() (pushed_string_list && pushed_string_list->expander)
1333#else
1334# define expanding_alias() 0
1335#endif
1336
726f6388
JA
1337/* Global var is non-zero when end of file has been reached. */
1338int EOF_Reached = 0;
1339
f73dda09
JA
1340#ifdef DEBUG
1341static void
ccc6cda3
JA
1342debug_parser (i)
1343 int i;
1344{
1345#if YYDEBUG != 0
1346 yydebug = i;
d233b485
CR
1347 yyoutstream = stdout;
1348 yyerrstream = stderr;
ccc6cda3
JA
1349#endif
1350}
f73dda09 1351#endif
ccc6cda3 1352
726f6388
JA
1353/* yy_getc () returns the next available character from input or EOF.
1354 yy_ungetc (c) makes `c' the next character to read.
1355 init_yy_io (get, unget, type, location) makes the function GET the
1356 installed function for getting the next character, makes UNGET the
1357 installed function for un-getting a character, sets the type of stream
1358 (either string or file) from TYPE, and makes LOCATION point to where
1359 the input is coming from. */
1360
1361/* Unconditionally returns end-of-file. */
ccc6cda3 1362int
726f6388
JA
1363return_EOF ()
1364{
1365 return (EOF);
1366}
1367
1368/* Variable containing the current get and unget functions.
1369 See ./input.h for a clearer description. */
1370BASH_INPUT bash_input;
1371
ccc6cda3
JA
1372/* Set all of the fields in BASH_INPUT to NULL. Free bash_input.name if it
1373 is non-null, avoiding a memory leak. */
726f6388
JA
1374void
1375initialize_bash_input ()
1376{
ccc6cda3
JA
1377 bash_input.type = st_none;
1378 FREE (bash_input.name);
726f6388
JA
1379 bash_input.name = (char *)NULL;
1380 bash_input.location.file = (FILE *)NULL;
1381 bash_input.location.string = (char *)NULL;
f73dda09
JA
1382 bash_input.getter = (sh_cget_func_t *)NULL;
1383 bash_input.ungetter = (sh_cunget_func_t *)NULL;
726f6388
JA
1384}
1385
1386/* Set the contents of the current bash input stream from
1387 GET, UNGET, TYPE, NAME, and LOCATION. */
1388void
1389init_yy_io (get, unget, type, name, location)
f73dda09
JA
1390 sh_cget_func_t *get;
1391 sh_cunget_func_t *unget;
d166f048 1392 enum stream_type type;
f73dda09 1393 const char *name;
726f6388
JA
1394 INPUT_STREAM location;
1395{
1396 bash_input.type = type;
1397 FREE (bash_input.name);
ccc6cda3 1398 bash_input.name = name ? savestring (name) : (char *)NULL;
726f6388 1399
ccc6cda3 1400 /* XXX */
726f6388
JA
1401#if defined (CRAY)
1402 memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
1403#else
1404 bash_input.location = location;
1405#endif
1406 bash_input.getter = get;
1407 bash_input.ungetter = unget;
1408}
1409
7117c2d2
JA
1410char *
1411yy_input_name ()
1412{
1413 return (bash_input.name ? bash_input.name : "stdin");
1414}
1415
726f6388 1416/* Call this to get the next character of input. */
f73dda09 1417static int
726f6388
JA
1418yy_getc ()
1419{
1420 return (*(bash_input.getter)) ();
1421}
1422
1423/* Call this to unget C. That is, to make C the next character
1424 to be read. */
f73dda09 1425static int
726f6388
JA
1426yy_ungetc (c)
1427 int c;
1428{
1429 return (*(bash_input.ungetter)) (c);
1430}
1431
1432#if defined (BUFFERED_INPUT)
f73dda09 1433#ifdef INCLUDE_UNUSED
726f6388
JA
1434int
1435input_file_descriptor ()
1436{
1437 switch (bash_input.type)
1438 {
1439 case st_stream:
1440 return (fileno (bash_input.location.file));
1441 case st_bstream:
1442 return (bash_input.location.buffered_fd);
ccc6cda3 1443 case st_stdin:
726f6388
JA
1444 default:
1445 return (fileno (stdin));
1446 }
1447}
f73dda09 1448#endif
726f6388
JA
1449#endif /* BUFFERED_INPUT */
1450
1451/* **************************************************************** */
1452/* */
1453/* Let input be read from readline (). */
1454/* */
1455/* **************************************************************** */
1456
1457#if defined (READLINE)
1458char *current_readline_prompt = (char *)NULL;
1459char *current_readline_line = (char *)NULL;
1460int current_readline_line_index = 0;
1461
1462static int
1463yy_readline_get ()
1464{
ccc6cda3 1465 SigHandler *old_sigint;
f73dda09
JA
1466 int line_len;
1467 unsigned char c;
ccc6cda3 1468
a0c0a00f 1469 if (current_readline_line == 0)
726f6388 1470 {
a0c0a00f 1471 if (bash_readline_initialized == 0)
726f6388
JA
1472 initialize_readline ();
1473
1474#if defined (JOB_CONTROL)
1475 if (job_control)
28ef6c31 1476 give_terminal_to (shell_pgrp, 0);
726f6388
JA
1477#endif /* JOB_CONTROL */
1478
a0c0a00f 1479 old_sigint = IMPOSSIBLE_TRAP_HANDLER;
726f6388
JA
1480 if (signal_is_ignored (SIGINT) == 0)
1481 {
ac50fbac 1482 /* interrupt_immediately++; */
495aee44 1483 old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
726f6388
JA
1484 }
1485
d233b485 1486 sh_unset_nodelay_mode (fileno (rl_instream)); /* just in case */
ccc6cda3
JA
1487 current_readline_line = readline (current_readline_prompt ?
1488 current_readline_prompt : "");
726f6388 1489
ac50fbac 1490 CHECK_TERMSIG;
495aee44 1491 if (signal_is_ignored (SIGINT) == 0)
726f6388 1492 {
ac50fbac 1493 /* interrupt_immediately--; */
495aee44
CR
1494 if (old_sigint != IMPOSSIBLE_TRAP_HANDLER)
1495 set_signal_handler (SIGINT, old_sigint);
726f6388
JA
1496 }
1497
ccc6cda3
JA
1498#if 0
1499 /* Reset the prompt to the decoded value of prompt_string_pointer. */
726f6388 1500 reset_readline_prompt ();
ccc6cda3 1501#endif
726f6388 1502
ccc6cda3 1503 if (current_readline_line == 0)
726f6388
JA
1504 return (EOF);
1505
ccc6cda3 1506 current_readline_line_index = 0;
726f6388 1507 line_len = strlen (current_readline_line);
ccc6cda3 1508
f73dda09 1509 current_readline_line = (char *)xrealloc (current_readline_line, 2 + line_len);
726f6388
JA
1510 current_readline_line[line_len++] = '\n';
1511 current_readline_line[line_len] = '\0';
1512 }
1513
ccc6cda3 1514 if (current_readline_line[current_readline_line_index] == 0)
726f6388
JA
1515 {
1516 free (current_readline_line);
1517 current_readline_line = (char *)NULL;
1518 return (yy_readline_get ());
1519 }
1520 else
1521 {
f73dda09 1522 c = current_readline_line[current_readline_line_index++];
726f6388
JA
1523 return (c);
1524 }
1525}
1526
1527static int
1528yy_readline_unget (c)
ccc6cda3 1529 int c;
726f6388
JA
1530{
1531 if (current_readline_line_index && current_readline_line)
1532 current_readline_line[--current_readline_line_index] = c;
1533 return (c);
1534}
1535
ccc6cda3 1536void
726f6388
JA
1537with_input_from_stdin ()
1538{
1539 INPUT_STREAM location;
1540
1541 if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
1542 {
1543 location.string = current_readline_line;
1544 init_yy_io (yy_readline_get, yy_readline_unget,
1545 st_stdin, "readline stdin", location);
1546 }
1547}
1548
1549#else /* !READLINE */
1550
1551void
1552with_input_from_stdin ()
1553{
1554 with_input_from_stream (stdin, "stdin");
1555}
1556#endif /* !READLINE */
1557
1558/* **************************************************************** */
1559/* */
1560/* Let input come from STRING. STRING is zero terminated. */
1561/* */
1562/* **************************************************************** */
1563
1564static int
1565yy_string_get ()
1566{
ccc6cda3 1567 register char *string;
f73dda09 1568 register unsigned char c;
726f6388
JA
1569
1570 string = bash_input.location.string;
726f6388
JA
1571
1572 /* If the string doesn't exist, or is empty, EOF found. */
1573 if (string && *string)
1574 {
f73dda09 1575 c = *string++;
726f6388 1576 bash_input.location.string = string;
f73dda09 1577 return (c);
726f6388 1578 }
f73dda09
JA
1579 else
1580 return (EOF);
726f6388
JA
1581}
1582
1583static int
1584yy_string_unget (c)
1585 int c;
1586{
1587 *(--bash_input.location.string) = c;
1588 return (c);
1589}
1590
1591void
1592with_input_from_string (string, name)
f73dda09
JA
1593 char *string;
1594 const char *name;
726f6388
JA
1595{
1596 INPUT_STREAM location;
1597
1598 location.string = string;
726f6388
JA
1599 init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
1600}
1601
3185942a
JA
1602/* Count the number of characters we've consumed from bash_input.location.string
1603 and read into shell_input_line, but have not returned from shell_getc.
1604 That is the true input location. Rewind bash_input.location.string by
1605 that number of characters, so it points to the last character actually
1606 consumed by the parser. */
1607static void
1608rewind_input_string ()
1609{
1610 int xchars;
1611
1612 /* number of unconsumed characters in the input -- XXX need to take newlines
1613 into account, e.g., $(...\n) */
1614 xchars = shell_input_line_len - shell_input_line_index;
1615 if (bash_input.location.string[-1] == '\n')
1616 xchars++;
1617
1618 /* XXX - how to reflect bash_input.location.string back to string passed to
1619 parse_and_execute or xparse_dolparen? xparse_dolparen needs to know how
1620 far into the string we parsed. parse_and_execute knows where bash_input.
1621 location.string is, and how far from orig_string that is -- that's the
1622 number of characters the command consumed. */
1623
1624 /* bash_input.location.string - xchars should be where we parsed to */
1625 /* need to do more validation on xchars value for sanity -- test cases. */
1626 bash_input.location.string -= xchars;
1627}
1628
726f6388
JA
1629/* **************************************************************** */
1630/* */
1631/* Let input come from STREAM. */
1632/* */
1633/* **************************************************************** */
1634
bb70624e
JA
1635/* These two functions used to test the value of the HAVE_RESTARTABLE_SYSCALLS
1636 define, and just use getc/ungetc if it was defined, but since bash
1637 installs its signal handlers without the SA_RESTART flag, some signals
1638 (like SIGCHLD, SIGWINCH, etc.) received during a read(2) will not cause
1639 the read to be restarted. We need to restart it ourselves. */
1640
726f6388
JA
1641static int
1642yy_stream_get ()
1643{
bb70624e 1644 int result;
726f6388 1645
bb70624e 1646 result = EOF;
726f6388 1647 if (bash_input.location.file)
95732b49 1648 {
ac50fbac
CR
1649 /* XXX - don't need terminate_immediately; getc_with_restart checks
1650 for terminating signals itself if read returns < 0 */
95732b49 1651 result = getc_with_restart (bash_input.location.file);
95732b49 1652 }
726f6388
JA
1653 return (result);
1654}
1655
1656static int
1657yy_stream_unget (c)
1658 int c;
1659{
726f6388 1660 return (ungetc_with_restart (c, bash_input.location.file));
726f6388
JA
1661}
1662
1663void
1664with_input_from_stream (stream, name)
1665 FILE *stream;
f73dda09 1666 const char *name;
726f6388
JA
1667{
1668 INPUT_STREAM location;
1669
1670 location.file = stream;
1671 init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
1672}
1673
1674typedef struct stream_saver {
1675 struct stream_saver *next;
1676 BASH_INPUT bash_input;
1677 int line;
1678#if defined (BUFFERED_INPUT)
1679 BUFFERED_STREAM *bstream;
1680#endif /* BUFFERED_INPUT */
1681} STREAM_SAVER;
1682
1683/* The globally known line number. */
1684int line_number = 0;
1685
495aee44
CR
1686/* The line number offset set by assigning to LINENO. Not currently used. */
1687int line_number_base = 0;
1688
cce855bc
JA
1689#if defined (COND_COMMAND)
1690static int cond_lineno;
1691static int cond_token;
1692#endif
1693
726f6388
JA
1694STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
1695
ccc6cda3
JA
1696void
1697push_stream (reset_lineno)
1698 int reset_lineno;
726f6388
JA
1699{
1700 STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
1701
1702 xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
1703
1704#if defined (BUFFERED_INPUT)
1705 saver->bstream = (BUFFERED_STREAM *)NULL;
1706 /* If we have a buffered stream, clear out buffers[fd]. */
1707 if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
cce855bc
JA
1708 saver->bstream = set_buffered_stream (bash_input.location.buffered_fd,
1709 (BUFFERED_STREAM *)NULL);
726f6388
JA
1710#endif /* BUFFERED_INPUT */
1711
1712 saver->line = line_number;
1713 bash_input.name = (char *)NULL;
1714 saver->next = stream_list;
1715 stream_list = saver;
ccc6cda3
JA
1716 EOF_Reached = 0;
1717 if (reset_lineno)
1718 line_number = 0;
726f6388
JA
1719}
1720
ccc6cda3 1721void
726f6388
JA
1722pop_stream ()
1723{
726f6388
JA
1724 if (!stream_list)
1725 EOF_Reached = 1;
1726 else
1727 {
1728 STREAM_SAVER *saver = stream_list;
1729
1730 EOF_Reached = 0;
1731 stream_list = stream_list->next;
1732
1733 init_yy_io (saver->bash_input.getter,
1734 saver->bash_input.ungetter,
1735 saver->bash_input.type,
1736 saver->bash_input.name,
1737 saver->bash_input.location);
1738
1739#if defined (BUFFERED_INPUT)
1740 /* If we have a buffered stream, restore buffers[fd]. */
1741 /* If the input file descriptor was changed while this was on the
1742 save stack, update the buffered fd to the new file descriptor and
1743 re-establish the buffer <-> bash_input fd correspondence. */
1744 if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
28ef6c31
JA
1745 {
1746 if (bash_input_fd_changed)
726f6388
JA
1747 {
1748 bash_input_fd_changed = 0;
1749 if (default_buffered_input >= 0)
1750 {
1751 bash_input.location.buffered_fd = default_buffered_input;
1752 saver->bstream->b_fd = default_buffered_input;
28ef6c31 1753 SET_CLOSE_ON_EXEC (default_buffered_input);
726f6388
JA
1754 }
1755 }
28ef6c31 1756 /* XXX could free buffered stream returned as result here. */
cce855bc 1757 set_buffered_stream (bash_input.location.buffered_fd, saver->bstream);
28ef6c31 1758 }
726f6388
JA
1759#endif /* BUFFERED_INPUT */
1760
1761 line_number = saver->line;
1762
1763 FREE (saver->bash_input.name);
1764 free (saver);
1765 }
1766}
1767
1768/* Return 1 if a stream of type TYPE is saved on the stack. */
1769int
1770stream_on_stack (type)
ccc6cda3 1771 enum stream_type type;
726f6388
JA
1772{
1773 register STREAM_SAVER *s;
ccc6cda3 1774
726f6388
JA
1775 for (s = stream_list; s; s = s->next)
1776 if (s->bash_input.type == type)
1777 return 1;
1778 return 0;
1779}
1780
bb70624e
JA
1781/* Save the current token state and return it in a malloced array. */
1782int *
1783save_token_state ()
1784{
1785 int *ret;
1786
89a92869 1787 ret = (int *)xmalloc (4 * sizeof (int));
bb70624e
JA
1788 ret[0] = last_read_token;
1789 ret[1] = token_before_that;
1790 ret[2] = two_tokens_ago;
89a92869 1791 ret[3] = current_token;
bb70624e
JA
1792 return ret;
1793}
1794
1795void
1796restore_token_state (ts)
1797 int *ts;
1798{
1799 if (ts == 0)
1800 return;
1801 last_read_token = ts[0];
1802 token_before_that = ts[1];
1803 two_tokens_ago = ts[2];
89a92869 1804 current_token = ts[3];
bb70624e
JA
1805}
1806
726f6388
JA
1807/*
1808 * This is used to inhibit alias expansion and reserved word recognition
ccc6cda3
JA
1809 * inside case statement pattern lists. A `case statement pattern list' is:
1810 *
726f6388
JA
1811 * everything between the `in' in a `case word in' and the next ')'
1812 * or `esac'
1813 * everything between a `;;' and the next `)' or `esac'
1814 */
726f6388 1815
cce855bc
JA
1816#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
1817
ccc6cda3
JA
1818#define END_OF_ALIAS 0
1819
726f6388
JA
1820/*
1821 * Pseudo-global variables used in implementing token-wise alias expansion.
1822 */
1823
726f6388 1824/*
ccc6cda3 1825 * Pushing and popping strings. This works together with shell_getc to
726f6388
JA
1826 * implement alias expansion on a per-token basis.
1827 */
1828
ac50fbac
CR
1829#define PSH_ALIAS 0x01
1830#define PSH_DPAREN 0x02
1831#define PSH_SOURCE 0x04
1832
726f6388
JA
1833typedef struct string_saver {
1834 struct string_saver *next;
1835 int expand_alias; /* Value to set expand_alias to when string is popped. */
1836 char *saved_line;
cce855bc 1837#if defined (ALIAS)
ccc6cda3 1838 alias_t *expander; /* alias that caused this line to be pushed. */
cce855bc 1839#endif
ac50fbac
CR
1840 size_t saved_line_size, saved_line_index;
1841 int saved_line_terminator;
1842 int flags;
726f6388
JA
1843} STRING_SAVER;
1844
1845STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
1846
726f6388
JA
1847/*
1848 * Push the current shell_input_line onto a stack of such lines and make S
1849 * the current input. Used when expanding aliases. EXPAND is used to set
1850 * the value of expand_next_token when the string is popped, so that the
1851 * word after the alias in the original line is handled correctly when the
1852 * alias expands to multiple words. TOKEN is the token that was expanded
1853 * into S; it is saved and used to prevent infinite recursive expansion.
1854 */
1855static void
ccc6cda3 1856push_string (s, expand, ap)
726f6388
JA
1857 char *s;
1858 int expand;
ccc6cda3 1859 alias_t *ap;
726f6388 1860{
f73dda09 1861 STRING_SAVER *temp = (STRING_SAVER *)xmalloc (sizeof (STRING_SAVER));
726f6388
JA
1862
1863 temp->expand_alias = expand;
1864 temp->saved_line = shell_input_line;
1865 temp->saved_line_size = shell_input_line_size;
1866 temp->saved_line_index = shell_input_line_index;
1867 temp->saved_line_terminator = shell_input_line_terminator;
ac50fbac 1868 temp->flags = 0;
cce855bc 1869#if defined (ALIAS)
ccc6cda3 1870 temp->expander = ap;
ac50fbac
CR
1871 if (ap)
1872 temp->flags = PSH_ALIAS;
cce855bc 1873#endif
726f6388
JA
1874 temp->next = pushed_string_list;
1875 pushed_string_list = temp;
1876
cce855bc 1877#if defined (ALIAS)
d166f048
JA
1878 if (ap)
1879 ap->flags |= AL_BEINGEXPANDED;
cce855bc 1880#endif
726f6388
JA
1881
1882 shell_input_line = s;
ac50fbac 1883 shell_input_line_size = STRLEN (s);
726f6388
JA
1884 shell_input_line_index = 0;
1885 shell_input_line_terminator = '\0';
b80f6443
JA
1886#if 0
1887 parser_state &= ~PST_ALEXPNEXT; /* XXX */
1888#endif
7117c2d2
JA
1889
1890 set_line_mbstate ();
726f6388
JA
1891}
1892
1893/*
1894 * Make the top of the pushed_string stack be the current shell input.
1895 * Only called when there is something on the stack. Called from shell_getc
1896 * when it thinks it has consumed the string generated by an alias expansion
1897 * and needs to return to the original input line.
1898 */
1899static void
1900pop_string ()
1901{
1902 STRING_SAVER *t;
1903
1904 FREE (shell_input_line);
1905 shell_input_line = pushed_string_list->saved_line;
1906 shell_input_line_index = pushed_string_list->saved_line_index;
1907 shell_input_line_size = pushed_string_list->saved_line_size;
1908 shell_input_line_terminator = pushed_string_list->saved_line_terminator;
ccc6cda3
JA
1909
1910 if (pushed_string_list->expand_alias)
1911 parser_state |= PST_ALEXPNEXT;
1912 else
1913 parser_state &= ~PST_ALEXPNEXT;
726f6388
JA
1914
1915 t = pushed_string_list;
1916 pushed_string_list = pushed_string_list->next;
ccc6cda3 1917
cce855bc 1918#if defined (ALIAS)
d166f048
JA
1919 if (t->expander)
1920 t->expander->flags &= ~AL_BEINGEXPANDED;
cce855bc 1921#endif
ccc6cda3
JA
1922
1923 free ((char *)t);
7117c2d2
JA
1924
1925 set_line_mbstate ();
726f6388
JA
1926}
1927
1928static void
1929free_string_list ()
1930{
ccc6cda3 1931 register STRING_SAVER *t, *t1;
726f6388 1932
ccc6cda3 1933 for (t = pushed_string_list; t; )
726f6388
JA
1934 {
1935 t1 = t->next;
1936 FREE (t->saved_line);
cce855bc
JA
1937#if defined (ALIAS)
1938 if (t->expander)
1939 t->expander->flags &= ~AL_BEINGEXPANDED;
1940#endif
726f6388
JA
1941 free ((char *)t);
1942 t = t1;
1943 }
1944 pushed_string_list = (STRING_SAVER *)NULL;
1945}
1946
cce855bc 1947#endif /* ALIAS || DPAREN_ARITHMETIC */
ccc6cda3 1948
b80f6443
JA
1949void
1950free_pushed_string_input ()
1951{
1952#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
1953 free_string_list ();
1954#endif
1955}
1956
ac50fbac
CR
1957int
1958parser_expanding_alias ()
1959{
1960 return (expanding_alias ());
1961}
1962
1963void
1964parser_save_alias ()
1965{
1966#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
1967 push_string ((char *)NULL, 0, (alias_t *)NULL);
1968 pushed_string_list->flags = PSH_SOURCE; /* XXX - for now */
1969#else
1970 ;
1971#endif
1972}
1973
1974void
1975parser_restore_alias ()
1976{
1977#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
1978 if (pushed_string_list)
1979 pop_string ();
1980#else
1981 ;
1982#endif
1983}
1984
d233b485
CR
1985#if defined (ALIAS)
1986/* Before freeing AP, make sure that there aren't any cases of pointer
1987 aliasing that could cause us to reference freed memory later on. */
1988void
1989clear_string_list_expander (ap)
1990 alias_t *ap;
1991{
1992 register STRING_SAVER *t;
1993
1994 for (t = pushed_string_list; t; t = t->next)
1995 {
1996 if (t->expander && t->expander == ap)
1997 t->expander = 0;
1998 }
1999}
2000#endif
2001
a0c0a00f
CR
2002void
2003clear_shell_input_line ()
2004{
2005 if (shell_input_line)
2006 shell_input_line[shell_input_line_index = 0] = '\0';
2007}
2008
726f6388
JA
2009/* Return a line of text, taken from wherever yylex () reads input.
2010 If there is no more input, then we return NULL. If REMOVE_QUOTED_NEWLINE
2011 is non-zero, we remove unquoted \<newline> pairs. This is used by
2012 read_secondary_line to read here documents. */
2013static char *
2014read_a_line (remove_quoted_newline)
2015 int remove_quoted_newline;
2016{
2017 static char *line_buffer = (char *)NULL;
2018 static int buffer_size = 0;
0001803f 2019 int indx, c, peekc, pass_next;
726f6388 2020
ccc6cda3 2021#if defined (READLINE)
b80f6443 2022 if (no_line_editing && SHOULD_PROMPT ())
ccc6cda3 2023#else
b80f6443 2024 if (SHOULD_PROMPT ())
ccc6cda3
JA
2025#endif
2026 print_prompt ();
2027
0001803f 2028 pass_next = indx = 0;
726f6388
JA
2029 while (1)
2030 {
726f6388
JA
2031 /* Allow immediate exit if interrupted during input. */
2032 QUIT;
2033
95732b49
JA
2034 c = yy_getc ();
2035
28ef6c31 2036 /* Ignore null bytes in input. */
726f6388 2037 if (c == 0)
28ef6c31
JA
2038 {
2039#if 0
2040 internal_warning ("read_a_line: ignored null byte in input");
2041#endif
2042 continue;
2043 }
726f6388
JA
2044
2045 /* If there is no more input, then we return NULL. */
2046 if (c == EOF)
2047 {
ccc6cda3
JA
2048 if (interactive && bash_input.type == st_stream)
2049 clearerr (stdin);
726f6388
JA
2050 if (indx == 0)
2051 return ((char *)NULL);
2052 c = '\n';
2053 }
2054
d233b485
CR
2055 /* `+2' in case the final character in the buffer is a newline or we
2056 have to handle CTLESC or CTLNUL. */
ccc6cda3 2057 RESIZE_MALLOCED_BUFFER (line_buffer, indx, 2, buffer_size, 128);
726f6388
JA
2058
2059 /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
2060 here document with an unquoted delimiter. In this case,
2061 the line will be expanded as if it were in double quotes.
2062 We allow a backslash to escape the next character, but we
2063 need to treat the backslash specially only if a backslash
2064 quoting a backslash-newline pair appears in the line. */
2065 if (pass_next)
28ef6c31 2066 {
726f6388
JA
2067 line_buffer[indx++] = c;
2068 pass_next = 0;
28ef6c31 2069 }
726f6388
JA
2070 else if (c == '\\' && remove_quoted_newline)
2071 {
495aee44 2072 QUIT;
726f6388
JA
2073 peekc = yy_getc ();
2074 if (peekc == '\n')
b80f6443
JA
2075 {
2076 line_number++;
2077 continue; /* Make the unquoted \<newline> pair disappear. */
2078 }
726f6388
JA
2079 else
2080 {
2081 yy_ungetc (peekc);
2082 pass_next = 1;
2083 line_buffer[indx++] = c; /* Preserve the backslash. */
2084 }
2085 }
2086 else
d233b485
CR
2087 {
2088 /* remove_quoted_newline is non-zero if the here-document delimiter
2089 is unquoted. In this case, we will be expanding the lines and
2090 need to make sure CTLESC and CTLNUL in the input are quoted. */
2091 if (remove_quoted_newline && (c == CTLESC || c == CTLNUL))
2092 line_buffer[indx++] = CTLESC;
2093 line_buffer[indx++] = c;
2094 }
726f6388
JA
2095
2096 if (c == '\n')
2097 {
2098 line_buffer[indx] = '\0';
2099 return (line_buffer);
2100 }
2101 }
2102}
2103
2104/* Return a line as in read_a_line (), but insure that the prompt is
2105 the secondary prompt. This is used to read the lines of a here
2106 document. REMOVE_QUOTED_NEWLINE is non-zero if we should remove
2107 newlines quoted with backslashes while reading the line. It is
2108 non-zero unless the delimiter of the here document was quoted. */
2109char *
2110read_secondary_line (remove_quoted_newline)
2111 int remove_quoted_newline;
2112{
3185942a
JA
2113 char *ret;
2114 int n, c;
2115
726f6388 2116 prompt_string_pointer = &ps2_prompt;
b80f6443
JA
2117 if (SHOULD_PROMPT())
2118 prompt_again ();
3185942a
JA
2119 ret = read_a_line (remove_quoted_newline);
2120#if defined (HISTORY)
89a92869 2121 if (ret && remember_on_history && (parser_state & PST_HEREDOC))
3185942a 2122 {
a0c0a00f
CR
2123 /* To make adding the here-document body right, we need to rely on
2124 history_delimiting_chars() returning \n for the first line of the
2125 here-document body and the null string for the second and subsequent
2126 lines, so we avoid double newlines.
3185942a
JA
2127 current_command_line_count == 2 for the first line of the body. */
2128
2129 current_command_line_count++;
2130 maybe_add_history (ret);
2131 }
2132#endif /* HISTORY */
2133 return ret;
726f6388
JA
2134}
2135
726f6388
JA
2136/* **************************************************************** */
2137/* */
2138/* YYLEX () */
2139/* */
2140/* **************************************************************** */
2141
2142/* Reserved words. These are only recognized as the first word of a
2143 command. */
2144STRING_INT_ALIST word_token_alist[] = {
2145 { "if", IF },
2146 { "then", THEN },
2147 { "else", ELSE },
2148 { "elif", ELIF },
2149 { "fi", FI },
2150 { "case", CASE },
2151 { "esac", ESAC },
2152 { "for", FOR },
2153#if defined (SELECT_COMMAND)
2154 { "select", SELECT },
2155#endif
2156 { "while", WHILE },
2157 { "until", UNTIL },
2158 { "do", DO },
2159 { "done", DONE },
2160 { "in", IN },
2161 { "function", FUNCTION },
ccc6cda3
JA
2162#if defined (COMMAND_TIMING)
2163 { "time", TIME },
2164#endif
726f6388
JA
2165 { "{", '{' },
2166 { "}", '}' },
2167 { "!", BANG },
cce855bc
JA
2168#if defined (COND_COMMAND)
2169 { "[[", COND_START },
2170 { "]]", COND_END },
3185942a
JA
2171#endif
2172#if defined (COPROCESS_SUPPORT)
2173 { "coproc", COPROC },
cce855bc 2174#endif
726f6388
JA
2175 { (char *)NULL, 0}
2176};
2177
7117c2d2
JA
2178/* other tokens that can be returned by read_token() */
2179STRING_INT_ALIST other_token_alist[] = {
2180 /* Multiple-character tokens with special values */
495aee44 2181 { "--", TIMEIGN },
7117c2d2
JA
2182 { "-p", TIMEOPT },
2183 { "&&", AND_AND },
2184 { "||", OR_OR },
2185 { ">>", GREATER_GREATER },
2186 { "<<", LESS_LESS },
2187 { "<&", LESS_AND },
2188 { ">&", GREATER_AND },
2189 { ";;", SEMI_SEMI },
3185942a
JA
2190 { ";&", SEMI_AND },
2191 { ";;&", SEMI_SEMI_AND },
7117c2d2
JA
2192 { "<<-", LESS_LESS_MINUS },
2193 { "<<<", LESS_LESS_LESS },
2194 { "&>", AND_GREATER },
3185942a 2195 { "&>>", AND_GREATER_GREATER },
7117c2d2
JA
2196 { "<>", LESS_GREATER },
2197 { ">|", GREATER_BAR },
3185942a 2198 { "|&", BAR_AND },
7117c2d2
JA
2199 { "EOF", yacc_EOF },
2200 /* Tokens whose value is the character itself */
2201 { ">", '>' },
2202 { "<", '<' },
2203 { "-", '-' },
2204 { "{", '{' },
2205 { "}", '}' },
2206 { ";", ';' },
2207 { "(", '(' },
2208 { ")", ')' },
2209 { "|", '|' },
2210 { "&", '&' },
2211 { "newline", '\n' },
2212 { (char *)NULL, 0}
2213};
2214
2215/* others not listed here:
2216 WORD look at yylval.word
2217 ASSIGNMENT_WORD look at yylval.word
2218 NUMBER look at yylval.number
2219 ARITH_CMD look at yylval.word_list
2220 ARITH_FOR_EXPRS look at yylval.word_list
2221 COND_CMD look at yylval.command
2222*/
b72432fd 2223
ccc6cda3
JA
2224/* These are used by read_token_word, but appear up here so that shell_getc
2225 can use them to decide when to add otherwise blank lines to the history. */
2226
2227/* The primary delimiter stack. */
2228struct dstack dstack = { (char *)NULL, 0, 0 };
2229
2230/* A temporary delimiter stack to be used when decoding prompt strings.
2231 This is needed because command substitutions in prompt strings (e.g., PS2)
2232 can screw up the parser's quoting state. */
2233static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
2234
2235/* Macro for accessing the top delimiter on the stack. Returns the
2236 delimiter or zero if none. */
2237#define current_delimiter(ds) \
2238 (ds.delimiter_depth ? ds.delimiters[ds.delimiter_depth - 1] : 0)
2239
2240#define push_delimiter(ds, character) \
2241 do \
2242 { \
2243 if (ds.delimiter_depth + 2 > ds.delimiter_space) \
f73dda09 2244 ds.delimiters = (char *)xrealloc \
ccc6cda3
JA
2245 (ds.delimiters, (ds.delimiter_space += 10) * sizeof (char)); \
2246 ds.delimiters[ds.delimiter_depth] = character; \
2247 ds.delimiter_depth++; \
2248 } \
2249 while (0)
2250
2251#define pop_delimiter(ds) ds.delimiter_depth--
2252
726f6388
JA
2253/* Return the next shell input character. This always reads characters
2254 from shell_input_line; when that line is exhausted, it is time to
2255 read the next line. This is called by read_token when the shell is
2256 processing normal command input. */
ccc6cda3 2257
28ef6c31
JA
2258/* This implements one-character lookahead/lookbehind across physical input
2259 lines, to avoid something being lost because it's pushed back with
2260 shell_ungetc when we're at the start of a line. */
2261static int eol_ungetc_lookahead = 0;
2262
726f6388
JA
2263static int
2264shell_getc (remove_quoted_newline)
2265 int remove_quoted_newline;
2266{
ccc6cda3 2267 register int i;
a0c0a00f 2268 int c, truncating, last_was_backslash;
f73dda09 2269 unsigned char uc;
726f6388
JA
2270
2271 QUIT;
2272
a0c0a00f 2273 last_was_backslash = 0;
95732b49
JA
2274 if (sigwinch_received)
2275 {
2276 sigwinch_received = 0;
2277 get_new_window_size (0, (int *)0, (int *)0);
2278 }
2279
28ef6c31
JA
2280 if (eol_ungetc_lookahead)
2281 {
2282 c = eol_ungetc_lookahead;
2283 eol_ungetc_lookahead = 0;
2284 return (c);
2285 }
2286
cce855bc 2287#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
726f6388
JA
2288 /* If shell_input_line[shell_input_line_index] == 0, but there is
2289 something on the pushed list of strings, then we don't want to go
2290 off and get another line. We let the code down below handle it. */
2291
2292 if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
2293 (pushed_string_list == (STRING_SAVER *)NULL)))
cce855bc 2294#else /* !ALIAS && !DPAREN_ARITHMETIC */
726f6388 2295 if (!shell_input_line || !shell_input_line[shell_input_line_index])
cce855bc 2296#endif /* !ALIAS && !DPAREN_ARITHMETIC */
726f6388 2297 {
726f6388
JA
2298 line_number++;
2299
ac50fbac
CR
2300 /* Let's not let one really really long line blow up memory allocation */
2301 if (shell_input_line && shell_input_line_size >= 32768)
2302 {
2303 free (shell_input_line);
2304 shell_input_line = 0;
2305 shell_input_line_size = 0;
2306 }
2307
726f6388
JA
2308 restart_read:
2309
2310 /* Allow immediate exit if interrupted during input. */
2311 QUIT;
2312
ac50fbac 2313 i = truncating = 0;
726f6388
JA
2314 shell_input_line_terminator = 0;
2315
b80f6443
JA
2316 /* If the shell is interatctive, but not currently printing a prompt
2317 (interactive_shell && interactive == 0), we don't want to print
2318 notifies or cleanup the jobs -- we want to defer it until we do
2319 print the next prompt. */
2320 if (interactive_shell == 0 || SHOULD_PROMPT())
2321 {
726f6388
JA
2322#if defined (JOB_CONTROL)
2323 /* This can cause a problem when reading a command as the result
2324 of a trap, when the trap is called from flush_child. This call
2325 had better not cause jobs to disappear from the job table in
2326 that case, or we will have big trouble. */
b80f6443 2327 notify_and_cleanup ();
726f6388 2328#else /* !JOB_CONTROL */
b80f6443 2329 cleanup_dead_jobs ();
726f6388 2330#endif /* !JOB_CONTROL */
b80f6443 2331 }
726f6388
JA
2332
2333#if defined (READLINE)
b80f6443 2334 if (no_line_editing && SHOULD_PROMPT())
726f6388 2335#else
b80f6443 2336 if (SHOULD_PROMPT())
726f6388
JA
2337#endif
2338 print_prompt ();
2339
2340 if (bash_input.type == st_stream)
2341 clearerr (stdin);
2342
28ef6c31 2343 while (1)
726f6388 2344 {
28ef6c31
JA
2345 c = yy_getc ();
2346
726f6388
JA
2347 /* Allow immediate exit if interrupted during input. */
2348 QUIT;
2349
28ef6c31
JA
2350 if (c == '\0')
2351 {
2352#if 0
2353 internal_warning ("shell_getc: ignored null byte in input");
2354#endif
d233b485
CR
2355 /* If we get EOS while parsing a string, treat it as EOF so we
2356 don't just keep looping. Happens very rarely */
2357 if (bash_input.type == st_string)
2358 {
2359 if (i == 0)
2360 shell_input_line_terminator = EOF;
2361 shell_input_line[i] = '\0';
2362 c = EOF;
2363 break;
2364 }
28ef6c31
JA
2365 continue;
2366 }
2367
ac50fbac
CR
2368 /* Theoretical overflow */
2369 /* If we can't put 256 bytes more into the buffer, allocate
2370 everything we can and fill it as full as we can. */
2371 /* XXX - we ignore rest of line using `truncating' flag */
2372 if (shell_input_line_size > (SIZE_MAX - 256))
2373 {
2374 size_t n;
2375
2376 n = SIZE_MAX - i; /* how much more can we put into the buffer? */
2377 if (n <= 2) /* we have to save 1 for the newline added below */
2378 {
2379 if (truncating == 0)
a0c0a00f 2380 internal_warning(_("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%lu): line truncated"), shell_input_line_size, (unsigned long)SIZE_MAX);
ac50fbac
CR
2381 shell_input_line[i] = '\0';
2382 truncating = 1;
2383 }
2384 if (shell_input_line_size < SIZE_MAX)
2385 {
2386 shell_input_line_size = SIZE_MAX;
2387 shell_input_line = xrealloc (shell_input_line, shell_input_line_size);
2388 }
2389 }
2390 else
2391 RESIZE_MALLOCED_BUFFER (shell_input_line, i, 2, shell_input_line_size, 256);
726f6388
JA
2392
2393 if (c == EOF)
2394 {
2395 if (bash_input.type == st_stream)
2396 clearerr (stdin);
2397
ccc6cda3 2398 if (i == 0)
726f6388
JA
2399 shell_input_line_terminator = EOF;
2400
2401 shell_input_line[i] = '\0';
2402 break;
2403 }
2404
ac50fbac
CR
2405 if (truncating == 0 || c == '\n')
2406 shell_input_line[i++] = c;
726f6388
JA
2407
2408 if (c == '\n')
2409 {
2410 shell_input_line[--i] = '\0';
2411 current_command_line_count++;
2412 break;
2413 }
a0c0a00f
CR
2414
2415 last_was_backslash = last_was_backslash == 0 && c == '\\';
726f6388 2416 }
28ef6c31 2417
726f6388
JA
2418 shell_input_line_index = 0;
2419 shell_input_line_len = i; /* == strlen (shell_input_line) */
2420
7117c2d2
JA
2421 set_line_mbstate ();
2422
726f6388 2423#if defined (HISTORY)
ccc6cda3 2424 if (remember_on_history && shell_input_line && shell_input_line[0])
726f6388
JA
2425 {
2426 char *expansions;
ccc6cda3 2427# if defined (BANG_HISTORY)
ccc6cda3
JA
2428 /* If the current delimiter is a single quote, we should not be
2429 performing history expansion, even if we're on a different
2430 line from the original single quote. */
ccc6cda3 2431 if (current_delimiter (dstack) == '\'')
d233b485
CR
2432 history_quoting_state = '\'';
2433 else if (current_delimiter (dstack) == '"')
2434 history_quoting_state = '"';
2435 else
2436 history_quoting_state = 0;
ccc6cda3 2437# endif
a0c0a00f
CR
2438 /* Calling with a third argument of 1 allows remember_on_history to
2439 determine whether or not the line is saved to the history list */
726f6388 2440 expansions = pre_process_line (shell_input_line, 1, 1);
ccc6cda3 2441# if defined (BANG_HISTORY)
d233b485 2442 history_quoting_state = 0;
ccc6cda3 2443# endif
d166f048
JA
2444 if (expansions != shell_input_line)
2445 {
2446 free (shell_input_line);
2447 shell_input_line = expansions;
2448 shell_input_line_len = shell_input_line ?
2449 strlen (shell_input_line) : 0;
495aee44 2450 if (shell_input_line_len == 0)
d166f048
JA
2451 current_command_line_count--;
2452
2453 /* We have to force the xrealloc below because we don't know
28ef6c31 2454 the true allocated size of shell_input_line anymore. */
d166f048 2455 shell_input_line_size = shell_input_line_len;
7117c2d2
JA
2456
2457 set_line_mbstate ();
d166f048 2458 }
726f6388 2459 }
28ef6c31
JA
2460 /* Try to do something intelligent with blank lines encountered while
2461 entering multi-line commands. XXX - this is grotesque */
ccc6cda3
JA
2462 else if (remember_on_history && shell_input_line &&
2463 shell_input_line[0] == '\0' &&
28ef6c31 2464 current_command_line_count > 1)
ccc6cda3 2465 {
28ef6c31
JA
2466 if (current_delimiter (dstack))
2467 /* We know shell_input_line[0] == 0 and we're reading some sort of
2468 quoted string. This means we've got a line consisting of only
2469 a newline in a quoted string. We want to make sure this line
2470 gets added to the history. */
2471 maybe_add_history (shell_input_line);
2472 else
2473 {
2474 char *hdcs;
495aee44 2475 hdcs = history_delimiting_chars (shell_input_line);
28ef6c31
JA
2476 if (hdcs && hdcs[0] == ';')
2477 maybe_add_history (shell_input_line);
2478 }
ccc6cda3
JA
2479 }
2480
726f6388
JA
2481#endif /* HISTORY */
2482
2483 if (shell_input_line)
2484 {
2485 /* Lines that signify the end of the shell's input should not be
ac50fbac
CR
2486 echoed. We should not echo lines while parsing command
2487 substitutions with recursive calls into the parsing engine; those
2488 should only be echoed once when we read the word. That is the
2489 reason for the test against shell_eof_token, which is set to a
2490 right paren when parsing the contents of command substitutions. */
726f6388 2491 if (echo_input_at_read && (shell_input_line[0] ||
ac50fbac
CR
2492 shell_input_line_terminator != EOF) &&
2493 shell_eof_token == 0)
726f6388
JA
2494 fprintf (stderr, "%s\n", shell_input_line);
2495 }
2496 else
2497 {
2498 shell_input_line_size = 0;
2499 prompt_string_pointer = &current_prompt_string;
b80f6443
JA
2500 if (SHOULD_PROMPT ())
2501 prompt_again ();
726f6388
JA
2502 goto restart_read;
2503 }
2504
2505 /* Add the newline to the end of this string, iff the string does
2506 not already end in an EOF character. */
2507 if (shell_input_line_terminator != EOF)
2508 {
6ebbb24a 2509 if (shell_input_line_size < SIZE_MAX-3 && (shell_input_line_len+3 > shell_input_line_size))
f73dda09 2510 shell_input_line = (char *)xrealloc (shell_input_line,
726f6388
JA
2511 1 + (shell_input_line_size += 2));
2512
a0c0a00f
CR
2513 /* Don't add a newline to a string that ends with a backslash if we're
2514 going to be removing quoted newlines, since that will eat the
2515 backslash. Add another backslash instead (will be removed by
2516 word expansion). */
2517 if (bash_input.type == st_string && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline)
2518 shell_input_line[shell_input_line_len] = '\\';
2519 else
2520 shell_input_line[shell_input_line_len] = '\n';
ccc6cda3 2521 shell_input_line[shell_input_line_len + 1] = '\0';
7117c2d2
JA
2522
2523 set_line_mbstate ();
726f6388
JA
2524 }
2525 }
ccc6cda3 2526
495aee44 2527next_alias_char:
f73dda09 2528 uc = shell_input_line[shell_input_line_index];
726f6388 2529
f73dda09 2530 if (uc)
726f6388
JA
2531 shell_input_line_index++;
2532
cce855bc 2533#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
f73dda09 2534 /* If UC is NULL, we have reached the end of the current input string. If
726f6388
JA
2535 pushed_string_list is non-empty, it's time to pop to the previous string
2536 because we have fully consumed the result of the last alias expansion.
2537 Do it transparently; just return the next character of the string popped
2538 to. */
ac50fbac
CR
2539 /* If pushed_string_list != 0 but pushed_string_list->expander == 0 (not
2540 currently tested) and the flags value is not PSH_SOURCE, we are not
2541 parsing an alias, we have just saved one (push_string, when called by
2542 the parse_dparen code) In this case, just go on as well. The PSH_SOURCE
2543 case is handled below. */
d233b485
CR
2544
2545 /* If we're at the end of an alias expansion add a space to make sure that
2546 the alias remains marked as being in use while we expand its last word.
2547 This makes sure that pop_string doesn't mark the alias as not in use
2548 before the string resulting from the alias expansion is tokenized and
2549 checked for alias expansion, preventing recursion. At this point, the
2550 last character in shell_input_line is the last character of the alias
2551 expansion. We test that last character to determine whether or not to
2552 return the space that will delimit the token and postpone the pop_string.
2553 This set of conditions duplicates what used to be in mk_alexpansion ()
2554 below, with the addition that we don't add a space if we're currently
2555 reading a quoted string or in a shell comment. */
2556#ifndef OLD_ALIAS_HACK
2557 if (uc == 0 && pushed_string_list && pushed_string_list->flags != PSH_SOURCE &&
2558 pushed_string_list->flags != PSH_DPAREN &&
2559 (parser_state & PST_COMMENT) == 0 &&
ddf3f643 2560 (parser_state & PST_ENDALIAS) == 0 && /* only once */
d233b485 2561 shell_input_line_index > 0 &&
ddf3f643 2562 shellblank (shell_input_line[shell_input_line_index-1]) == 0 &&
d233b485
CR
2563 shell_input_line[shell_input_line_index-1] != '\n' &&
2564 shellmeta (shell_input_line[shell_input_line_index-1]) == 0 &&
2565 (current_delimiter (dstack) != '\'' && current_delimiter (dstack) != '"'))
2566 {
ddf3f643 2567 parser_state |= PST_ENDALIAS;
d233b485
CR
2568 return ' '; /* END_ALIAS */
2569 }
2570#endif
2571
0001803f 2572pop_alias:
d233b485 2573 /* This case works for PSH_DPAREN as well */
ac50fbac 2574 if (uc == 0 && pushed_string_list && pushed_string_list->flags != PSH_SOURCE)
726f6388 2575 {
ddf3f643 2576 parser_state &= ~PST_ENDALIAS;
b80f6443
JA
2577 pop_string ();
2578 uc = shell_input_line[shell_input_line_index];
2579 if (uc)
2580 shell_input_line_index++;
726f6388 2581 }
cce855bc 2582#endif /* ALIAS || DPAREN_ARITHMETIC */
726f6388 2583
95732b49
JA
2584 if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
2585 {
2586 if (SHOULD_PROMPT ())
2587 prompt_again ();
2588 line_number++;
495aee44
CR
2589 /* What do we do here if we're expanding an alias whose definition
2590 includes an escaped newline? If that's the last character in the
2591 alias expansion, we just pop the pushed string list (recall that
d233b485
CR
2592 we inhibit the appending of a space if newline is the last
2593 character). If it's not the last character, we need to consume the
2594 quoted newline and move to the next character in the expansion. */
509a4430 2595#if defined (ALIAS)
0001803f
CR
2596 if (expanding_alias () && shell_input_line[shell_input_line_index+1] == '\0')
2597 {
2598 uc = 0;
2599 goto pop_alias;
2600 }
495aee44
CR
2601 else if (expanding_alias () && shell_input_line[shell_input_line_index+1] != '\0')
2602 {
2603 shell_input_line_index++; /* skip newline */
2604 goto next_alias_char; /* and get next character */
2605 }
509a4430
CR
2606 else
2607#endif
495aee44 2608 goto restart_read;
95732b49
JA
2609 }
2610
495aee44 2611 if (uc == 0 && shell_input_line_terminator == EOF)
ccc6cda3 2612 return ((shell_input_line_index != 0) ? '\n' : EOF);
726f6388 2613
ac50fbac
CR
2614#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
2615 /* We already know that we are not parsing an alias expansion because of the
2616 check for expanding_alias() above. This knows how parse_and_execute
2617 handles switching to st_string input while an alias is being expanded,
2618 hence the check for pushed_string_list without pushed_string_list->expander
2619 and the check for PSH_SOURCE as pushed_string_list->flags.
2620 parse_and_execute and parse_string both change the input type to st_string
2621 and place the string to be parsed and executed into location.string, so
2622 we should not stop reading that until the pointer is '\0'.
2623 The check for shell_input_line_terminator may be superfluous.
2624
2625 This solves the problem of `.' inside a multi-line alias with embedded
2626 newlines executing things out of order. */
2627 if (uc == 0 && bash_input.type == st_string && *bash_input.location.string &&
2628 pushed_string_list && pushed_string_list->flags == PSH_SOURCE &&
2629 shell_input_line_terminator == 0)
2630 {
2631 shell_input_line_index = 0;
2632 goto restart_read;
2633 }
2634#endif
2635
f73dda09 2636 return (uc);
726f6388
JA
2637}
2638
7117c2d2
JA
2639/* Put C back into the input for the shell. This might need changes for
2640 HANDLE_MULTIBYTE around EOLs. Since we (currently) never push back a
2641 character different than we read, shell_input_line_property doesn't need
2642 to change when manipulating shell_input_line. The define for
2643 last_shell_getc_is_singlebyte should take care of it, though. */
726f6388
JA
2644static void
2645shell_ungetc (c)
2646 int c;
2647{
2648 if (shell_input_line && shell_input_line_index)
2649 shell_input_line[--shell_input_line_index] = c;
28ef6c31
JA
2650 else
2651 eol_ungetc_lookahead = c;
726f6388
JA
2652}
2653
ca6a2ba4
CR
2654char *
2655parser_remaining_input ()
2656{
2657 if (shell_input_line == 0)
2658 return 0;
d233b485 2659 if ((int)shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len)
a0c0a00f 2660 return ""; /* XXX */
ca6a2ba4
CR
2661 return (shell_input_line + shell_input_line_index);
2662}
2663
f73dda09
JA
2664#ifdef INCLUDE_UNUSED
2665/* Back the input pointer up by one, effectively `ungetting' a character. */
ccc6cda3
JA
2666static void
2667shell_ungetchar ()
2668{
2669 if (shell_input_line && shell_input_line_index)
2670 shell_input_line_index--;
2671}
f73dda09 2672#endif
ccc6cda3
JA
2673
2674/* Discard input until CHARACTER is seen, then push that character back
2675 onto the input stream. */
726f6388
JA
2676static void
2677discard_until (character)
2678 int character;
2679{
2680 int c;
2681
2682 while ((c = shell_getc (0)) != EOF && c != character)
2683 ;
2684
2685 if (c != EOF)
2686 shell_ungetc (c);
2687}
726f6388
JA
2688
2689void
0628567a
JA
2690execute_variable_command (command, vname)
2691 char *command, *vname;
726f6388 2692{
726f6388 2693 char *last_lastarg;
b80f6443 2694 sh_parser_state_t ps;
726f6388 2695
b80f6443 2696 save_parser_state (&ps);
726f6388
JA
2697 last_lastarg = get_string_value ("_");
2698 if (last_lastarg)
2699 last_lastarg = savestring (last_lastarg);
2700
0628567a 2701 parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST);
726f6388 2702
b80f6443 2703 restore_parser_state (&ps);
95732b49 2704 bind_variable ("_", last_lastarg, 0);
726f6388
JA
2705 FREE (last_lastarg);
2706
ccc6cda3 2707 if (token_to_read == '\n') /* reset_parser was called */
726f6388
JA
2708 token_to_read = 0;
2709}
2710
a0c0a00f
CR
2711void
2712push_token (x)
2713 int x;
2714{
2715 two_tokens_ago = token_before_that;
2716 token_before_that = last_read_token;
2717 last_read_token = current_token;
2718
2719 current_token = x;
2720}
2721
ccc6cda3
JA
2722/* Place to remember the token. We try to keep the buffer
2723 at a reasonable size, but it can grow. */
2724static char *token = (char *)NULL;
2725
2726/* Current size of the token buffer. */
2727static int token_buffer_size;
2728
726f6388
JA
2729/* Command to read_token () explaining what we want it to do. */
2730#define READ 0
2731#define RESET 1
2732#define prompt_is_ps1 \
2733 (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
2734
2735/* Function for yyparse to call. yylex keeps track of
2736 the last two tokens read, and calls read_token. */
ccc6cda3 2737static int
726f6388
JA
2738yylex ()
2739{
ccc6cda3 2740 if (interactive && (current_token == 0 || current_token == '\n'))
726f6388
JA
2741 {
2742 /* Before we print a prompt, we might have to check mailboxes.
2743 We do this only if it is time to do so. Notice that only here
2744 is the mail alarm reset; nothing takes place in check_mail ()
2745 except the checking of mail. Please don't change this. */
b4a8651a 2746 if (prompt_is_ps1 && parse_and_execute_level == 0 && time_to_check_mail ())
726f6388
JA
2747 {
2748 check_mail ();
2749 reset_mail_timer ();
2750 }
2751
2752 /* Avoid printing a prompt if we're not going to read anything, e.g.
2753 after resetting the parser with read_token (RESET). */
b80f6443 2754 if (token_to_read == 0 && SHOULD_PROMPT ())
726f6388
JA
2755 prompt_again ();
2756 }
2757
ccc6cda3 2758 two_tokens_ago = token_before_that;
726f6388
JA
2759 token_before_that = last_read_token;
2760 last_read_token = current_token;
2761 current_token = read_token (READ);
3185942a
JA
2762
2763 if ((parser_state & PST_EOFTOKEN) && current_token == shell_eof_token)
2764 {
2765 current_token = yacc_EOF;
2766 if (bash_input.type == st_string)
2767 rewind_input_string ();
2768 }
d233b485 2769 parser_state &= ~PST_EOFTOKEN; /* ??? */
3185942a 2770
726f6388
JA
2771 return (current_token);
2772}
2773
726f6388
JA
2774/* When non-zero, we have read the required tokens
2775 which allow ESAC to be the next one read. */
ccc6cda3 2776static int esacs_needed_count;
726f6388 2777
d233b485
CR
2778/* When non-zero, we can read IN as an acceptable token, regardless of how
2779 many newlines we read. */
2780static int expecting_in_token;
2781
90a39f32
CR
2782static void
2783push_heredoc (r)
2784 REDIRECT *r;
2785{
2786 if (need_here_doc >= HEREDOC_MAX)
2787 {
2788 last_command_exit_value = EX_BADUSAGE;
2789 need_here_doc = 0;
2790 report_syntax_error (_("maximum here-document count exceeded"));
2791 reset_parser ();
2792 exit_shell (last_command_exit_value);
2793 }
2794 redir_stack[need_here_doc++] = r;
2795}
2796
726f6388
JA
2797void
2798gather_here_documents ()
2799{
3185942a
JA
2800 int r;
2801
2802 r = 0;
a0c0a00f 2803 here_doc_first_line = 1;
daefb2c5 2804 while (need_here_doc > 0)
726f6388 2805 {
3185942a
JA
2806 parser_state |= PST_HEREDOC;
2807 make_here_document (redir_stack[r++], line_number);
2808 parser_state &= ~PST_HEREDOC;
726f6388 2809 need_here_doc--;
a0c0a00f 2810 redir_stack[r - 1] = 0; /* XXX */
726f6388 2811 }
a0c0a00f 2812 here_doc_first_line = 0; /* just in case */
726f6388
JA
2813}
2814
726f6388
JA
2815/* When non-zero, an open-brace used to create a group is awaiting a close
2816 brace partner. */
ccc6cda3 2817static int open_brace_count;
726f6388 2818
a0c0a00f
CR
2819/* In the following three macros, `token' is always last_read_token */
2820
2821/* Are we in the middle of parsing a redirection where we are about to read
2822 a word? This is used to make sure alias expansion doesn't happen in the
2823 middle of a redirection, even though we're parsing a simple command. */
2824#define parsing_redirection(token) \
2825 (token == '<' || token == '>' || \
2826 token == GREATER_GREATER || token == GREATER_BAR || \
2827 token == LESS_GREATER || token == LESS_LESS_MINUS || \
2828 token == LESS_LESS || token == LESS_LESS_LESS || \
2829 token == LESS_AND || token == GREATER_AND || token == AND_GREATER)
2830
2831/* Is `token' one that will allow a WORD to be read in a command position?
2832 We can read a simple command name on which we should attempt alias expansion
2833 or we can read an assignment statement. */
726f6388 2834#define command_token_position(token) \
a0c0a00f
CR
2835 (((token) == ASSIGNMENT_WORD) || \
2836 ((parser_state&PST_REDIRLIST) && parsing_redirection(token) == 0) || \
3185942a 2837 ((token) != SEMI_SEMI && (token) != SEMI_AND && (token) != SEMI_SEMI_AND && reserved_word_acceptable(token)))
726f6388 2838
a0c0a00f 2839/* Are we in a position where we can read an assignment statement? */
b80f6443
JA
2840#define assignment_acceptable(token) \
2841 (command_token_position(token) && ((parser_state & PST_CASEPAT) == 0))
726f6388
JA
2842
2843/* Check to see if TOKEN is a reserved word and return the token
2844 value if it is. */
2845#define CHECK_FOR_RESERVED_WORD(tok) \
2846 do { \
2847 if (!dollar_present && !quoted && \
2848 reserved_word_acceptable (last_read_token)) \
2849 { \
2850 int i; \
2851 for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
2852 if (STREQ (tok, word_token_alist[i].word)) \
2853 { \
ccc6cda3 2854 if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \
726f6388 2855 break; \
b80f6443 2856 if (word_token_alist[i].token == TIME && time_command_acceptable () == 0) \
cce855bc 2857 break; \
a0c0a00f
CR
2858 if ((parser_state & PST_CASEPAT) && last_read_token == '|' && word_token_alist[i].token == ESAC) \
2859 break; /* Posix grammar rule 4 */ \
726f6388 2860 if (word_token_alist[i].token == ESAC) \
ccc6cda3
JA
2861 parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
2862 else if (word_token_alist[i].token == CASE) \
2863 parser_state |= PST_CASESTMT; \
cce855bc
JA
2864 else if (word_token_alist[i].token == COND_END) \
2865 parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
2866 else if (word_token_alist[i].token == COND_START) \
2867 parser_state |= PST_CONDCMD; \
ccc6cda3
JA
2868 else if (word_token_alist[i].token == '{') \
2869 open_brace_count++; \
2870 else if (word_token_alist[i].token == '}' && open_brace_count) \
2871 open_brace_count--; \
726f6388
JA
2872 return (word_token_alist[i].token); \
2873 } \
2874 } \
2875 } while (0)
2876
ccc6cda3
JA
2877#if defined (ALIAS)
2878
2879 /* OK, we have a token. Let's try to alias expand it, if (and only if)
2880 it's eligible.
2881
7117c2d2 2882 It is eligible for expansion if EXPAND_ALIASES is set, and
ccc6cda3
JA
2883 the token is unquoted and the last token read was a command
2884 separator (or expand_next_token is set), and we are currently
2885 processing an alias (pushed_string_list is non-empty) and this
2886 token is not the same as the current or any previously
2887 processed alias.
2888
2889 Special cases that disqualify:
2890 In a pattern list in a case statement (parser_state & PST_CASEPAT). */
b80f6443
JA
2891
2892static char *
2893mk_alexpansion (s)
2894 char *s;
2895{
2896 int l;
2897 char *r;
2898
2899 l = strlen (s);
2900 r = xmalloc (l + 2);
2901 strcpy (r, s);
d233b485 2902#ifdef OLD_ALIAS_HACK
495aee44
CR
2903 /* If the last character in the alias is a newline, don't add a trailing
2904 space to the expansion. Works with shell_getc above. */
d233b485
CR
2905 /* Need to do something about the case where the alias expansion contains
2906 an unmatched quoted string, since appending this space affects the
2907 subsequent output. */
2908 if (l > 0 && r[l - 1] != ' ' && r[l - 1] != '\n' && shellmeta(r[l - 1]) == 0)
b80f6443 2909 r[l++] = ' ';
d233b485 2910#endif
b80f6443
JA
2911 r[l] = '\0';
2912 return r;
2913}
2914
ccc6cda3 2915static int
f73dda09
JA
2916alias_expand_token (tokstr)
2917 char *tokstr;
726f6388 2918{
ccc6cda3
JA
2919 char *expanded;
2920 alias_t *ap;
726f6388 2921
ccc6cda3
JA
2922 if (((parser_state & PST_ALEXPNEXT) || command_token_position (last_read_token)) &&
2923 (parser_state & PST_CASEPAT) == 0)
726f6388 2924 {
f73dda09 2925 ap = find_alias (tokstr);
ccc6cda3
JA
2926
2927 /* Currently expanding this token. */
2928 if (ap && (ap->flags & AL_BEINGEXPANDED))
2929 return (NO_EXPANSION);
2930
d233b485 2931#ifdef OLD_ALIAS_HACK
b80f6443 2932 /* mk_alexpansion puts an extra space on the end of the alias expansion,
d233b485
CR
2933 so the lookahead by the parser works right (the alias needs to remain
2934 `in use' while parsing its last word to avoid alias recursion for
2935 something like "alias echo=echo"). If this gets changed, make sure
2936 the code in shell_getc that deals with reaching the end of an
2937 expanded alias is changed with it. */
2938#endif
b80f6443
JA
2939 expanded = ap ? mk_alexpansion (ap->value) : (char *)NULL;
2940
ccc6cda3
JA
2941 if (expanded)
2942 {
2943 push_string (expanded, ap->flags & AL_EXPANDNEXT, ap);
2944 return (RE_READ_TOKEN);
2945 }
2946 else
2947 /* This is an eligible token that does not have an expansion. */
2948 return (NO_EXPANSION);
726f6388 2949 }
ccc6cda3
JA
2950 return (NO_EXPANSION);
2951}
2952#endif /* ALIAS */
726f6388 2953
cce855bc
JA
2954static int
2955time_command_acceptable ()
2956{
2957#if defined (COMMAND_TIMING)
495aee44
CR
2958 int i;
2959
2960 if (posixly_correct && shell_compatibility_level > 41)
2961 {
2962 /* Quick check of the rest of the line to find the next token. If it
2963 begins with a `-', Posix says to not return `time' as the token.
2964 This was interp 267. */
2965 i = shell_input_line_index;
2966 while (i < shell_input_line_len && (shell_input_line[i] == ' ' || shell_input_line[i] == '\t'))
2967 i++;
2968 if (shell_input_line[i] == '-')
2969 return 0;
2970 }
2971
cce855bc
JA
2972 switch (last_read_token)
2973 {
2974 case 0:
2975 case ';':
2976 case '\n':
a0c0a00f
CR
2977 if (token_before_that == '|')
2978 return (0);
2979 /* FALLTHROUGH */
cce855bc
JA
2980 case AND_AND:
2981 case OR_OR:
2982 case '&':
af61c549 2983 case WHILE:
b72432fd 2984 case DO:
af61c549
CR
2985 case UNTIL:
2986 case IF:
b72432fd 2987 case THEN:
af61c549 2988 case ELIF:
b72432fd 2989 case ELSE:
28ef6c31 2990 case '{': /* } */
af61c549
CR
2991 case '(': /* )( */
2992 case ')': /* only valid in case statement */
495aee44
CR
2993 case BANG: /* ! time pipeline */
2994 case TIME: /* time time pipeline */
2995 case TIMEOPT: /* time -p time pipeline */
2996 case TIMEIGN: /* time -p -- ... */
cce855bc
JA
2997 return 1;
2998 default:
2999 return 0;
3000 }
3001#else
3002 return 0;
3003#endif /* COMMAND_TIMING */
3004}
3005
ccc6cda3
JA
3006/* Handle special cases of token recognition:
3007 IN is recognized if the last token was WORD and the token
3008 before that was FOR or CASE or SELECT.
3009
3010 DO is recognized if the last token was WORD and the token
3011 before that was FOR or SELECT.
3012
3013 ESAC is recognized if the last token caused `esacs_needed_count'
3014 to be set
3015
3016 `{' is recognized if the last token as WORD and the token
28ef6c31
JA
3017 before that was FUNCTION, or if we just parsed an arithmetic
3018 `for' command.
ccc6cda3 3019
28ef6c31 3020 `}' is recognized if there is an unclosed `{' present.
cce855bc
JA
3021
3022 `-p' is returned as TIMEOPT if the last read token was TIME.
495aee44 3023 `--' is returned as TIMEIGN if the last read token was TIMEOPT.
cce855bc
JA
3024
3025 ']]' is returned as COND_END if the parser is currently parsing
3026 a conditional expression ((parser_state & PST_CONDEXPR) != 0)
3027
3028 `time' is returned as TIME if and only if it is immediately
3029 preceded by one of `;', `\n', `||', `&&', or `&'.
ccc6cda3
JA
3030*/
3031
3032static int
f73dda09
JA
3033special_case_tokens (tokstr)
3034 char *tokstr;
ccc6cda3 3035{
d233b485 3036 /* Posix grammar rule 6 */
ccc6cda3
JA
3037 if ((last_read_token == WORD) &&
3038#if defined (SELECT_COMMAND)
3039 ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
3040#else
3041 ((token_before_that == FOR) || (token_before_that == CASE)) &&
3042#endif
f73dda09 3043 (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
726f6388 3044 {
ccc6cda3
JA
3045 if (token_before_that == CASE)
3046 {
3047 parser_state |= PST_CASEPAT;
3048 esacs_needed_count++;
3049 }
d233b485
CR
3050 if (expecting_in_token)
3051 expecting_in_token--;
3052 return (IN);
3053 }
3054
3055 /* XXX - leaving above code intact for now, but it should eventually be
3056 removed in favor of this clause. */
3057 /* Posix grammar rule 6 */
3058 if (expecting_in_token && (last_read_token == WORD || last_read_token == '\n') &&
3059 (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
3060 {
3061 if (parser_state & PST_CASESTMT)
3062 {
3063 parser_state |= PST_CASEPAT;
3064 esacs_needed_count++;
3065 }
3066 expecting_in_token--;
ccc6cda3
JA
3067 return (IN);
3068 }
d233b485
CR
3069 /* Posix grammar rule 6, third word in FOR: for i; do command-list; done */
3070 else if (expecting_in_token && (last_read_token == '\n' || last_read_token == ';') &&
3071 (tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
3072 {
3073 expecting_in_token--;
3074 return (DO);
3075 }
726f6388 3076
d233b485 3077 /* for i do; command-list; done */
ccc6cda3
JA
3078 if (last_read_token == WORD &&
3079#if defined (SELECT_COMMAND)
3080 (token_before_that == FOR || token_before_that == SELECT) &&
3081#else
3082 (token_before_that == FOR) &&
3083#endif
f73dda09 3084 (tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
d233b485
CR
3085 {
3086 if (expecting_in_token)
3087 expecting_in_token--;
3088 return (DO);
3089 }
ccc6cda3
JA
3090
3091 /* Ditto for ESAC in the CASE case.
3092 Specifically, this handles "case word in esac", which is a legal
3093 construct, certainly because someone will pass an empty arg to the
3094 case construct, and we don't want it to barf. Of course, we should
3095 insist that the case construct has at least one pattern in it, but
3096 the designers disagree. */
3097 if (esacs_needed_count)
3098 {
d233b485 3099 if (last_read_token == IN && STREQ (tokstr, "esac"))
726f6388 3100 {
d233b485 3101 esacs_needed_count--;
ccc6cda3
JA
3102 parser_state &= ~PST_CASEPAT;
3103 return (ESAC);
726f6388 3104 }
ccc6cda3 3105 }
726f6388 3106
ccc6cda3
JA
3107 /* The start of a shell function definition. */
3108 if (parser_state & PST_ALLOWOPNBRC)
3109 {
3110 parser_state &= ~PST_ALLOWOPNBRC;
f73dda09 3111 if (tokstr[0] == '{' && tokstr[1] == '\0') /* } */
726f6388 3112 {
ccc6cda3
JA
3113 open_brace_count++;
3114 function_bstart = line_number;
3115 return ('{'); /* } */
726f6388 3116 }
ccc6cda3
JA
3117 }
3118
28ef6c31
JA
3119 /* We allow a `do' after a for ((...)) without an intervening
3120 list_terminator */
f73dda09 3121 if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == 'd' && tokstr[1] == 'o' && !tokstr[2])
28ef6c31 3122 return (DO);
f73dda09 3123 if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == '{' && tokstr[1] == '\0') /* } */
28ef6c31
JA
3124 {
3125 open_brace_count++;
3126 return ('{'); /* } */
3127 }
3128
f73dda09 3129 if (open_brace_count && reserved_word_acceptable (last_read_token) && tokstr[0] == '}' && !tokstr[1])
ccc6cda3
JA
3130 {
3131 open_brace_count--; /* { */
3132 return ('}');
3133 }
3134
cce855bc 3135#if defined (COMMAND_TIMING)
ccc6cda3 3136 /* Handle -p after `time'. */
f73dda09 3137 if (last_read_token == TIME && tokstr[0] == '-' && tokstr[1] == 'p' && !tokstr[2])
ccc6cda3 3138 return (TIMEOPT);
495aee44
CR
3139 /* Handle -- after `time -p'. */
3140 if (last_read_token == TIMEOPT && tokstr[0] == '-' && tokstr[1] == '-' && !tokstr[2])
3141 return (TIMEIGN);
b80f6443 3142#endif
cce855bc
JA
3143
3144#if defined (COND_COMMAND) /* [[ */
f73dda09 3145 if ((parser_state & PST_CONDEXPR) && tokstr[0] == ']' && tokstr[1] == ']' && tokstr[2] == '\0')
cce855bc
JA
3146 return (COND_END);
3147#endif
726f6388 3148
ccc6cda3
JA
3149 return (-1);
3150}
3151
3152/* Called from shell.c when Control-C is typed at top level. Or
3153 by the error rule at top level. */
3154void
3155reset_parser ()
3156{
3157 dstack.delimiter_depth = 0; /* No delimiters found so far. */
3158 open_brace_count = 0;
3159
0001803f
CR
3160#if defined (EXTENDED_GLOB)
3161 /* Reset to global value of extended glob */
3162 if (parser_state & PST_EXTPAT)
3163 extended_glob = global_extglob;
3164#endif
3165
ccc6cda3 3166 parser_state = 0;
a0c0a00f 3167 here_doc_first_line = 0;
ccc6cda3 3168
cce855bc 3169#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
ccc6cda3 3170 if (pushed_string_list)
cce855bc
JA
3171 free_string_list ();
3172#endif /* ALIAS || DPAREN_ARITHMETIC */
726f6388 3173
a0c0a00f 3174 /* This is where we resynchronize to the next newline on error/reset */
ccc6cda3
JA
3175 if (shell_input_line)
3176 {
3177 free (shell_input_line);
3178 shell_input_line = (char *)NULL;
3179 shell_input_line_size = shell_input_line_index = 0;
3180 }
3181
3182 FREE (word_desc_to_read);
3183 word_desc_to_read = (WORD_DESC *)NULL;
3184
836a17be
CR
3185 eol_ungetc_lookahead = 0;
3186
89a92869 3187 current_token = '\n'; /* XXX */
ccc6cda3
JA
3188 last_read_token = '\n';
3189 token_to_read = '\n';
3190}
3191
d233b485
CR
3192void
3193reset_readahead_token ()
3194{
3195 if (token_to_read == '\n')
3196 token_to_read = 0;
3197}
3198
ccc6cda3
JA
3199/* Read the next token. Command can be READ (normal operation) or
3200 RESET (to normalize state). */
3201static int
3202read_token (command)
3203 int command;
3204{
3205 int character; /* Current character. */
3206 int peek_char; /* Temporary look-ahead character. */
3207 int result; /* The thing to return. */
3208
3209 if (command == RESET)
3210 {
3211 reset_parser ();
726f6388
JA
3212 return ('\n');
3213 }
3214
3215 if (token_to_read)
3216 {
ccc6cda3
JA
3217 result = token_to_read;
3218 if (token_to_read == WORD || token_to_read == ASSIGNMENT_WORD)
d166f048
JA
3219 {
3220 yylval.word = word_desc_to_read;
3221 word_desc_to_read = (WORD_DESC *)NULL;
3222 }
726f6388 3223 token_to_read = 0;
ccc6cda3 3224 return (result);
726f6388
JA
3225 }
3226
cce855bc
JA
3227#if defined (COND_COMMAND)
3228 if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD)
3229 {
3230 cond_lineno = line_number;
3231 parser_state |= PST_CONDEXPR;
3232 yylval.command = parse_cond_command ();
3233 if (cond_token != COND_END)
3234 {
7117c2d2 3235 cond_error ();
cce855bc
JA
3236 return (-1);
3237 }
3238 token_to_read = COND_END;
3239 parser_state &= ~(PST_CONDEXPR|PST_CONDCMD);
3240 return (COND_CMD);
3241 }
3242#endif
3243
726f6388 3244#if defined (ALIAS)
726f6388
JA
3245 /* This is a place to jump back to once we have successfully expanded a
3246 token with an alias and pushed the string with push_string () */
3247 re_read_token:
726f6388
JA
3248#endif /* ALIAS */
3249
3250 /* Read a single word from input. Start by skipping blanks. */
0628567a 3251 while ((character = shell_getc (1)) != EOF && shellblank (character))
ccc6cda3 3252 ;
726f6388
JA
3253
3254 if (character == EOF)
3255 {
3256 EOF_Reached = 1;
3257 return (yacc_EOF);
3258 }
3259
d233b485
CR
3260 /* If we hit the end of the string and we're not expanding an alias (e.g.,
3261 we are eval'ing a string that is an incomplete command), return EOF */
3262 if (character == '\0' && bash_input.type == st_string && expanding_alias() == 0)
3263 {
3264#if defined (DEBUG)
3265itrace("shell_getc: bash_input.location.string = `%s'", bash_input.location.string);
3266#endif
3267 EOF_Reached = 1;
3268 return (yacc_EOF);
3269 }
3270
7117c2d2 3271 if MBTEST(character == '#' && (!interactive || interactive_comments))
726f6388
JA
3272 {
3273 /* A comment. Discard until EOL or EOF, and then return a newline. */
d233b485 3274 parser_state |= PST_COMMENT;
726f6388
JA
3275 discard_until ('\n');
3276 shell_getc (0);
d233b485 3277 parser_state &= ~PST_COMMENT;
ccc6cda3 3278 character = '\n'; /* this will take the next if statement and return. */
726f6388
JA
3279 }
3280
3281 if (character == '\n')
3282 {
3283 /* If we're about to return an unquoted newline, we can go and collect
3284 the text of any pending here document. */
3285 if (need_here_doc)
3286 gather_here_documents ();
3287
3288#if defined (ALIAS)
ccc6cda3 3289 parser_state &= ~PST_ALEXPNEXT;
726f6388
JA
3290#endif /* ALIAS */
3291
95732b49
JA
3292 parser_state &= ~PST_ASSIGNOK;
3293
726f6388
JA
3294 return (character);
3295 }
3296
f1be666c
JA
3297 if (parser_state & PST_REGEXP)
3298 goto tokword;
3299
ccc6cda3 3300 /* Shell meta-characters. */
7117c2d2 3301 if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
726f6388
JA
3302 {
3303#if defined (ALIAS)
3304 /* Turn off alias tokenization iff this character sequence would
3305 not leave us ready to read a command. */
3306 if (character == '<' || character == '>')
ccc6cda3 3307 parser_state &= ~PST_ALEXPNEXT;
726f6388
JA
3308#endif /* ALIAS */
3309
95732b49
JA
3310 parser_state &= ~PST_ASSIGNOK;
3311
a0c0a00f
CR
3312 /* If we are parsing a command substitution and we have read a character
3313 that marks the end of it, don't bother to skip over quoted newlines
3314 when we read the next token. We're just interested in a character
3315 that will turn this into a two-character token, so we let the higher
3316 layers deal with quoted newlines following the command substitution. */
3317 if ((parser_state & PST_CMDSUBST) && character == shell_eof_token)
3318 peek_char = shell_getc (0);
3319 else
3320 peek_char = shell_getc (1);
3321
ccc6cda3 3322 if (character == peek_char)
726f6388
JA
3323 {
3324 switch (character)
3325 {
ccc6cda3 3326 case '<':
726f6388
JA
3327 /* If '<' then we could be at "<<" or at "<<-". We have to
3328 look ahead one more character. */
726f6388 3329 peek_char = shell_getc (1);
3185942a 3330 if MBTEST(peek_char == '-')
726f6388 3331 return (LESS_LESS_MINUS);
3185942a 3332 else if MBTEST(peek_char == '<')
7117c2d2 3333 return (LESS_LESS_LESS);
726f6388
JA
3334 else
3335 {
3336 shell_ungetc (peek_char);
3337 return (LESS_LESS);
3338 }
3339
3340 case '>':
3341 return (GREATER_GREATER);
3342
3343 case ';':
ccc6cda3 3344 parser_state |= PST_CASEPAT;
726f6388 3345#if defined (ALIAS)
ccc6cda3 3346 parser_state &= ~PST_ALEXPNEXT;
726f6388 3347#endif /* ALIAS */
95732b49 3348
3185942a
JA
3349 peek_char = shell_getc (1);
3350 if MBTEST(peek_char == '&')
3351 return (SEMI_SEMI_AND);
3352 else
3353 {
3354 shell_ungetc (peek_char);
3355 return (SEMI_SEMI);
3356 }
726f6388
JA
3357
3358 case '&':
3359 return (AND_AND);
3360
3361 case '|':
3362 return (OR_OR);
ccc6cda3 3363
bb70624e 3364#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
ccc6cda3 3365 case '(': /* ) */
7117c2d2
JA
3366 result = parse_dparen (character);
3367 if (result == -2)
3368 break;
3369 else
3370 return result;
ccc6cda3 3371#endif
726f6388 3372 }
726f6388 3373 }
7117c2d2 3374 else if MBTEST(character == '<' && peek_char == '&')
ccc6cda3 3375 return (LESS_AND);
7117c2d2 3376 else if MBTEST(character == '>' && peek_char == '&')
ccc6cda3 3377 return (GREATER_AND);
7117c2d2 3378 else if MBTEST(character == '<' && peek_char == '>')
ccc6cda3 3379 return (LESS_GREATER);
7117c2d2 3380 else if MBTEST(character == '>' && peek_char == '|')
ccc6cda3 3381 return (GREATER_BAR);
3185942a
JA
3382 else if MBTEST(character == '&' && peek_char == '>')
3383 {
3384 peek_char = shell_getc (1);
3385 if MBTEST(peek_char == '>')
3386 return (AND_GREATER_GREATER);
3387 else
3388 {
3389 shell_ungetc (peek_char);
3390 return (AND_GREATER);
3391 }
3392 }
3393 else if MBTEST(character == '|' && peek_char == '&')
3394 return (BAR_AND);
3395 else if MBTEST(character == ';' && peek_char == '&')
3396 {
3397 parser_state |= PST_CASEPAT;
3398#if defined (ALIAS)
3399 parser_state &= ~PST_ALEXPNEXT;
3400#endif /* ALIAS */
3401 return (SEMI_AND);
3402 }
ccc6cda3 3403
726f6388
JA
3404 shell_ungetc (peek_char);
3405
3406 /* If we look like we are reading the start of a function
3407 definition, then let the reader know about it so that
3408 we will do the right thing with `{'. */
7117c2d2 3409 if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
726f6388 3410 {
ccc6cda3 3411 parser_state |= PST_ALLOWOPNBRC;
726f6388 3412#if defined (ALIAS)
ccc6cda3 3413 parser_state &= ~PST_ALEXPNEXT;
726f6388 3414#endif /* ALIAS */
ccc6cda3 3415 function_dstart = line_number;
726f6388
JA
3416 }
3417
ccc6cda3
JA
3418 /* case pattern lists may be preceded by an optional left paren. If
3419 we're not trying to parse a case pattern list, the left paren
3420 indicates a subshell. */
7117c2d2 3421 if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
ccc6cda3
JA
3422 parser_state |= PST_SUBSHELL;
3423 /*(*/
7117c2d2 3424 else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
28ef6c31 3425 parser_state &= ~PST_CASEPAT;
ccc6cda3 3426 /*(*/
7117c2d2 3427 else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
ccc6cda3 3428 parser_state &= ~PST_SUBSHELL;
726f6388
JA
3429
3430#if defined (PROCESS_SUBSTITUTION)
3431 /* Check for the constructs which introduce process substitution.
3432 Shells running in `posix mode' don't do process substitution. */
7117c2d2 3433 if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
726f6388
JA
3434#endif /* PROCESS_SUBSTITUTION */
3435 return (character);
3436 }
3437
7117c2d2
JA
3438 /* Hack <&- (close stdin) case. Also <&N- (dup and close). */
3439 if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
ccc6cda3
JA
3440 return (character);
3441
f1be666c 3442tokword:
726f6388
JA
3443 /* Okay, if we got this far, we have to read a word. Read one,
3444 and then check it against the known ones. */
ccc6cda3
JA
3445 result = read_token_word (character);
3446#if defined (ALIAS)
3447 if (result == RE_READ_TOKEN)
3448 goto re_read_token;
3449#endif
3450 return result;
3451}
726f6388 3452
7117c2d2
JA
3453/*
3454 * Match a $(...) or other grouping construct. This has to handle embedded
3455 * quoted strings ('', ``, "") and nested constructs. It also must handle
95732b49
JA
3456 * reprompting the user, if necessary, after reading a newline, and returning
3457 * correct error values if it reads EOF.
7117c2d2 3458 */
495aee44
CR
3459#define P_FIRSTCLOSE 0x0001
3460#define P_ALLOWESC 0x0002
3461#define P_DQUOTE 0x0004
3462#define P_COMMAND 0x0008 /* parsing a command, so look for comments */
3463#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
3464#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
3465#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
b72432fd 3466
3185942a 3467/* Lexical state while parsing a grouping construct or $(...). */
d233b485
CR
3468#define LEX_WASDOL 0x0001
3469#define LEX_CKCOMMENT 0x0002
3470#define LEX_INCOMMENT 0x0004
3471#define LEX_PASSNEXT 0x0008
3472#define LEX_RESWDOK 0x0010
3473#define LEX_CKCASE 0x0020
3474#define LEX_INCASE 0x0040
3475#define LEX_INHEREDOC 0x0080
3476#define LEX_HEREDELIM 0x0100 /* reading here-doc delimiter */
3477#define LEX_STRIPDOC 0x0200 /* <<- strip tabs from here doc delim */
3478#define LEX_QUOTEDDOC 0x0400 /* here doc with quoted delim */
3479#define LEX_INWORD 0x0800
3480#define LEX_GTLT 0x1000
3185942a
JA
3481
3482#define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
3483
3484#define CHECK_NESTRET_ERROR() \
3485 do { \
3486 if (nestret == &matched_pair_error) \
3487 { \
3488 free (ret); \
3489 return &matched_pair_error; \
3490 } \
3491 } while (0)
3492
3493#define APPEND_NESTRET() \
3494 do { \
3495 if (nestlen) \
3496 { \
3497 RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64); \
3498 strcpy (ret + retind, nestret); \
3499 retind += nestlen; \
3500 } \
3501 } while (0)
3502
ccc6cda3 3503static char matched_pair_error;
3185942a 3504
ccc6cda3
JA
3505static char *
3506parse_matched_pair (qc, open, close, lenp, flags)
3507 int qc; /* `"' if this construct is within double quotes */
3508 int open, close;
3509 int *lenp, flags;
3510{
d233b485 3511 int count, ch, prevch, tflags;
3185942a 3512 int nestlen, ttranslen, start_lineno;
28ef6c31 3513 char *ret, *nestret, *ttrans;
b80f6443 3514 int retind, retsize, rflags;
495aee44
CR
3515 int dolbrace_state;
3516
3517 dolbrace_state = (flags & P_DOLBRACE) ? DOLBRACE_PARAM : 0;
726f6388 3518
0001803f 3519/*itrace("parse_matched_pair[%d]: open = %c close = %c flags = %d", line_number, open, close, flags);*/
ccc6cda3 3520 count = 1;
3185942a
JA
3521 tflags = 0;
3522
3523 if ((flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
3524 tflags |= LEX_CKCOMMENT;
726f6388 3525
b80f6443
JA
3526 /* RFLAGS is the set of flags we want to pass to recursive calls. */
3527 rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
3528
f73dda09 3529 ret = (char *)xmalloc (retsize = 64);
ccc6cda3 3530 retind = 0;
726f6388 3531
ccc6cda3 3532 start_lineno = line_number;
d233b485 3533 ch = EOF; /* just in case */
ccc6cda3
JA
3534 while (count)
3535 {
d233b485 3536 prevch = ch;
495aee44 3537 ch = shell_getc (qc != '\'' && (tflags & (LEX_PASSNEXT)) == 0);
0628567a 3538
ccc6cda3
JA
3539 if (ch == EOF)
3540 {
3541 free (ret);
b80f6443 3542 parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
ccc6cda3
JA
3543 EOF_Reached = 1; /* XXX */
3544 return (&matched_pair_error);
3545 }
726f6388 3546
ccc6cda3 3547 /* Possible reprompting. */
b80f6443 3548 if (ch == '\n' && SHOULD_PROMPT ())
ccc6cda3 3549 prompt_again ();
726f6388 3550
3185942a
JA
3551 /* Don't bother counting parens or doing anything else if in a comment
3552 or part of a case statement */
3553 if (tflags & LEX_INCOMMENT)
95732b49
JA
3554 {
3555 /* Add this character. */
3556 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3557 ret[retind++] = ch;
3558
3559 if (ch == '\n')
3185942a 3560 tflags &= ~LEX_INCOMMENT;
95732b49
JA
3561
3562 continue;
3563 }
3185942a 3564
0628567a
JA
3565 /* Not exactly right yet, should handle shell metacharacters, too. If
3566 any changes are made to this test, make analogous changes to subst.c:
3567 extract_delimited_string(). */
3185942a
JA
3568 else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
3569 tflags |= LEX_INCOMMENT;
0628567a 3570
3185942a 3571 if (tflags & LEX_PASSNEXT) /* last char was backslash */
ccc6cda3 3572 {
3185942a 3573 tflags &= ~LEX_PASSNEXT;
ccc6cda3
JA
3574 if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
3575 {
3185942a
JA
3576 if (retind > 0)
3577 retind--; /* swallow previously-added backslash */
ccc6cda3
JA
3578 continue;
3579 }
726f6388 3580
ccc6cda3 3581 RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
ac50fbac 3582 if MBTEST(ch == CTLESC)
ccc6cda3
JA
3583 ret[retind++] = CTLESC;
3584 ret[retind++] = ch;
3585 continue;
3586 }
3185942a
JA
3587 /* If we're reparsing the input (e.g., from parse_string_to_word_list),
3588 we've already prepended CTLESC to single-quoted results of $'...'.
3589 We may want to do this for other CTLESC-quoted characters in
3590 reparse, too. */
3591 else if MBTEST((parser_state & PST_REPARSE) && open == '\'' && (ch == CTLESC || ch == CTLNUL))
3592 {
3593 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3594 ret[retind++] = ch;
3595 continue;
3596 }
7117c2d2 3597 else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
ccc6cda3
JA
3598 {
3599 RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
3600 ret[retind++] = CTLESC;
3601 ret[retind++] = ch;
3602 continue;
3603 }
7117c2d2 3604 else if MBTEST(ch == close) /* ending delimiter */
ccc6cda3 3605 count--;
bb70624e 3606 /* handle nested ${...} specially. */
3185942a 3607 else if MBTEST(open != close && (tflags & LEX_WASDOL) && open == '{' && ch == open) /* } */
28ef6c31 3608 count++;
7117c2d2 3609 else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
ccc6cda3 3610 count++;
726f6388 3611
ccc6cda3
JA
3612 /* Add this character. */
3613 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3614 ret[retind++] = ch;
726f6388 3615
3185942a
JA
3616 /* If we just read the ending character, don't bother continuing. */
3617 if (count == 0)
3618 break;
3619
ccc6cda3 3620 if (open == '\'') /* '' inside grouping construct */
bb70624e 3621 {
7117c2d2 3622 if MBTEST((flags & P_ALLOWESC) && ch == '\\')
3185942a 3623 tflags |= LEX_PASSNEXT;
bb70624e
JA
3624 continue;
3625 }
726f6388 3626
7117c2d2 3627 if MBTEST(ch == '\\') /* backslashes */
3185942a
JA
3628 tflags |= LEX_PASSNEXT;
3629
495aee44
CR
3630 /* Based on which dolstate is currently in (param, op, or word),
3631 decide what the op is. We're really only concerned if it's % or
3632 #, so we can turn on a flag that says whether or not we should
3633 treat single quotes as special when inside a double-quoted
3634 ${...}. This logic must agree with subst.c:extract_dollar_brace_string
3635 since they share the same defines. */
ac50fbac 3636 /* FLAG POSIX INTERP 221 */
495aee44
CR
3637 if (flags & P_DOLBRACE)
3638 {
3639 /* ${param%[%]word} */
3640 if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '%' && retind > 1)
3641 dolbrace_state = DOLBRACE_QUOTE;
3642 /* ${param#[#]word} */
3643 else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '#' && retind > 1)
3644 dolbrace_state = DOLBRACE_QUOTE;
3645 /* ${param/[/]pat/rep} */
3646 else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '/' && retind > 1)
ac50fbac 3647 dolbrace_state = DOLBRACE_QUOTE2; /* XXX */
495aee44
CR
3648 /* ${param^[^]pat} */
3649 else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '^' && retind > 1)
3650 dolbrace_state = DOLBRACE_QUOTE;
3651 /* ${param,[,]pat} */
3652 else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == ',' && retind > 1)
3653 dolbrace_state = DOLBRACE_QUOTE;
3654 else if MBTEST(dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", ch) != 0)
3655 dolbrace_state = DOLBRACE_OP;
3656 else if MBTEST(dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", ch) == 0)
3657 dolbrace_state = DOLBRACE_WORD;
3658 }
3659
3185942a 3660 /* The big hammer. Single quotes aren't special in double quotes. The
495aee44 3661 problem is that Posix used to say the single quotes are semi-special:
3185942a
JA
3662 within a double-quoted ${...} construct "an even number of
3663 unescaped double-quotes or single-quotes, if any, shall occur." */
495aee44 3664 /* This was changed in Austin Group Interp 221 */
bc63a081 3665 if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && dolbrace_state != DOLBRACE_QUOTE2 && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'')
3185942a 3666 continue;
726f6388 3667
3185942a
JA
3668 /* Could also check open == '`' if we want to parse grouping constructs
3669 inside old-style command substitution. */
ccc6cda3
JA
3670 if (open != close) /* a grouping construct */
3671 {
7117c2d2 3672 if MBTEST(shellquote (ch))
ccc6cda3
JA
3673 {
3674 /* '', ``, or "" inside $(...) or other grouping construct. */
3675 push_delimiter (dstack, ch);
3185942a 3676 if MBTEST((tflags & LEX_WASDOL) && ch == '\'') /* $'...' inside group */
b80f6443 3677 nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
28ef6c31 3678 else
b80f6443 3679 nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
ccc6cda3 3680 pop_delimiter (dstack);
3185942a
JA
3681 CHECK_NESTRET_ERROR ();
3682
3683 if MBTEST((tflags & LEX_WASDOL) && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
28ef6c31
JA
3684 {
3685 /* Translate $'...' here. */
3686 ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
d233b485 3687 free (nestret);
95732b49 3688
ac50fbac
CR
3689 /* If we're parsing a double-quoted brace expansion and we are
3690 not in a place where single quotes are treated specially,
3691 make sure we single-quote the results of the ansi
3692 expansion because quote removal should remove them later */
3693 /* FLAG POSIX INTERP 221 */
3694 if ((shell_compatibility_level > 42) && (rflags & P_DQUOTE) && (dolbrace_state == DOLBRACE_QUOTE2) && (flags & P_DOLBRACE))
3695 {
3696 nestret = sh_single_quote (ttrans);
3697 free (ttrans);
3698 nestlen = strlen (nestret);
3699 }
3700 else if ((rflags & P_DQUOTE) == 0)
95732b49
JA
3701 {
3702 nestret = sh_single_quote (ttrans);
3703 free (ttrans);
3704 nestlen = strlen (nestret);
3705 }
3706 else
3707 {
3708 nestret = ttrans;
3709 nestlen = ttranslen;
3710 }
28ef6c31
JA
3711 retind -= 2; /* back up before the $' */
3712 }
3185942a 3713 else if MBTEST((tflags & LEX_WASDOL) && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
28ef6c31
JA
3714 {
3715 /* Locale expand $"..." here. */
3716 ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
d233b485 3717 free (nestret);
95732b49
JA
3718
3719 nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
28ef6c31 3720 free (ttrans);
95732b49 3721 nestlen = ttranslen + 2;
28ef6c31
JA
3722 retind -= 2; /* back up before the $" */
3723 }
7117c2d2 3724
3185942a 3725 APPEND_NESTRET ();
ccc6cda3
JA
3726 FREE (nestret);
3727 }
a0c0a00f 3728 else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
89a92869 3729 goto parse_dollar_word;
d233b485
CR
3730#if defined (PROCESS_SUBSTITUTION)
3731 /* XXX - technically this should only be recognized at the start of
3732 a word */
3733 else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_GTLT) && (ch == '(')) /* ) */
3734 goto parse_dollar_word;
3735#endif
ccc6cda3
JA
3736 }
3737 /* Parse an old-style command substitution within double quotes as a
3738 single word. */
3739 /* XXX - sh and ksh93 don't do this - XXX */
7117c2d2 3740 else if MBTEST(open == '"' && ch == '`')
ccc6cda3 3741 {
b80f6443 3742 nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags);
3185942a
JA
3743
3744 CHECK_NESTRET_ERROR ();
3745 APPEND_NESTRET ();
3746
3747 FREE (nestret);
3748 }
3749 else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
3750 /* check for $(), $[], or ${} inside quoted string. */
3751 {
89a92869 3752parse_dollar_word:
3185942a
JA
3753 if (open == ch) /* undo previous increment */
3754 count--;
3755 if (ch == '(') /* ) */
3756 nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
3757 else if (ch == '{') /* } */
495aee44 3758 nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
3185942a
JA
3759 else if (ch == '[') /* ] */
3760 nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
3761
3762 CHECK_NESTRET_ERROR ();
3763 APPEND_NESTRET ();
3764
3765 FREE (nestret);
3766 }
d233b485
CR
3767#if defined (PROCESS_SUBSTITUTION)
3768 if MBTEST((ch == '<' || ch == '>') && (tflags & LEX_GTLT) == 0)
3769 tflags |= LEX_GTLT;
3770 else
3771 tflags &= ~LEX_GTLT;
3772#endif
3773 if MBTEST(ch == '$' && (tflags & LEX_WASDOL) == 0)
3185942a
JA
3774 tflags |= LEX_WASDOL;
3775 else
3776 tflags &= ~LEX_WASDOL;
3777 }
3778
3779 ret[retind] = '\0';
3780 if (lenp)
3781 *lenp = retind;
0001803f 3782/*itrace("parse_matched_pair[%d]: returning %s", line_number, ret);*/
3185942a
JA
3783 return ret;
3784}
3785
a0c0a00f
CR
3786#if defined (DEBUG)
3787static void
3788dump_tflags (flags)
3789 int flags;
3790{
3791 int f;
3792
3793 f = flags;
3794 fprintf (stderr, "%d -> ", f);
3795 if (f & LEX_WASDOL)
3796 {
3797 f &= ~LEX_WASDOL;
3798 fprintf (stderr, "LEX_WASDOL%s", f ? "|" : "");
3799 }
3800 if (f & LEX_CKCOMMENT)
3801 {
3802 f &= ~LEX_CKCOMMENT;
3803 fprintf (stderr, "LEX_CKCOMMENT%s", f ? "|" : "");
3804 }
3805 if (f & LEX_INCOMMENT)
3806 {
3807 f &= ~LEX_INCOMMENT;
3808 fprintf (stderr, "LEX_INCOMMENT%s", f ? "|" : "");
3809 }
3810 if (f & LEX_PASSNEXT)
3811 {
3812 f &= ~LEX_PASSNEXT;
3813 fprintf (stderr, "LEX_PASSNEXT%s", f ? "|" : "");
3814 }
3815 if (f & LEX_RESWDOK)
3816 {
3817 f &= ~LEX_RESWDOK;
3818 fprintf (stderr, "LEX_RESWDOK%s", f ? "|" : "");
3819 }
3820 if (f & LEX_CKCASE)
3821 {
3822 f &= ~LEX_CKCASE;
3823 fprintf (stderr, "LEX_CKCASE%s", f ? "|" : "");
3824 }
3825 if (f & LEX_INCASE)
3826 {
3827 f &= ~LEX_INCASE;
3828 fprintf (stderr, "LEX_INCASE%s", f ? "|" : "");
3829 }
3830 if (f & LEX_INHEREDOC)
3831 {
3832 f &= ~LEX_INHEREDOC;
3833 fprintf (stderr, "LEX_INHEREDOC%s", f ? "|" : "");
3834 }
3835 if (f & LEX_HEREDELIM)
3836 {
3837 f &= ~LEX_HEREDELIM;
3838 fprintf (stderr, "LEX_HEREDELIM%s", f ? "|" : "");
3839 }
3840 if (f & LEX_STRIPDOC)
3841 {
3842 f &= ~LEX_STRIPDOC;
3843 fprintf (stderr, "LEX_WASDOL%s", f ? "|" : "");
3844 }
3845 if (f & LEX_QUOTEDDOC)
3846 {
3847 f &= ~LEX_QUOTEDDOC;
3848 fprintf (stderr, "LEX_QUOTEDDOC%s", f ? "|" : "");
3849 }
3850 if (f & LEX_INWORD)
3851 {
3852 f &= ~LEX_INWORD;
3853 fprintf (stderr, "LEX_INWORD%s", f ? "|" : "");
3854 }
3855
3856 fprintf (stderr, "\n");
3857 fflush (stderr);
3858}
3859#endif
3860
3185942a
JA
3861/* Parse a $(...) command substitution. This is messier than I'd like, and
3862 reproduces a lot more of the token-reading code than I'd like. */
3863static char *
3864parse_comsub (qc, open, close, lenp, flags)
3865 int qc; /* `"' if this construct is within double quotes */
3866 int open, close;
3867 int *lenp, flags;
3868{
89a92869 3869 int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
3185942a
JA
3870 int nestlen, ttranslen, start_lineno;
3871 char *ret, *nestret, *ttrans, *heredelim;
3872 int retind, retsize, rflags, hdlen;
3873
495aee44
CR
3874 /* Posix interp 217 says arithmetic expressions have precedence, so
3875 assume $(( introduces arithmetic expansion and parse accordingly. */
3876 peekc = shell_getc (0);
3877 shell_ungetc (peekc);
3878 if (peekc == '(')
3879 return (parse_matched_pair (qc, open, close, lenp, 0));
3880
3185942a
JA
3881/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
3882 count = 1;
3883 tflags = LEX_RESWDOK;
3884
3885 if ((flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
3886 tflags |= LEX_CKCASE;
3887 if ((tflags & LEX_CKCASE) && (interactive == 0 || interactive_comments))
3888 tflags |= LEX_CKCOMMENT;
3889
3890 /* RFLAGS is the set of flags we want to pass to recursive calls. */
3891 rflags = (flags & P_DQUOTE);
3892
3893 ret = (char *)xmalloc (retsize = 64);
3894 retind = 0;
3895
3896 start_lineno = line_number;
89a92869 3897 lex_rwlen = lex_wlen = 0;
3185942a
JA
3898
3899 heredelim = 0;
3900 lex_firstind = -1;
3901
3902 while (count)
3903 {
3904comsub_readchar:
d233b485 3905 ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT|LEX_QUOTEDDOC)) == 0);
3185942a
JA
3906
3907 if (ch == EOF)
3908 {
3909eof_error:
3910 free (ret);
3911 FREE (heredelim);
3912 parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
3913 EOF_Reached = 1; /* XXX */
3914 return (&matched_pair_error);
3915 }
3916
3917 /* If we hit the end of a line and are reading the contents of a here
3918 document, and it's not the same line that the document starts on,
3919 check for this line being the here doc delimiter. Otherwise, if
3920 we're in a here document, mark the next character as the beginning
3921 of a line. */
3922 if (ch == '\n')
3923 {
3924 if ((tflags & LEX_HEREDELIM) && heredelim)
ccc6cda3 3925 {
3185942a
JA
3926 tflags &= ~LEX_HEREDELIM;
3927 tflags |= LEX_INHEREDOC;
3928 lex_firstind = retind + 1;
ccc6cda3 3929 }
3185942a 3930 else if (tflags & LEX_INHEREDOC)
ccc6cda3 3931 {
3185942a
JA
3932 int tind;
3933 tind = lex_firstind;
3934 while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
3935 tind++;
d233b485 3936 if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen))
3185942a 3937 {
a0c0a00f 3938 tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC|LEX_QUOTEDDOC);
3185942a 3939/*itrace("parse_comsub:%d: found here doc end `%s'", line_number, ret + tind);*/
0001803f
CR
3940 free (heredelim);
3941 heredelim = 0;
3185942a
JA
3942 lex_firstind = -1;
3943 }
3944 else
3945 lex_firstind = retind + 1;
ccc6cda3 3946 }
ccc6cda3 3947 }
3185942a
JA
3948
3949 /* Possible reprompting. */
3950 if (ch == '\n' && SHOULD_PROMPT ())
3951 prompt_again ();
3952
0001803f
CR
3953 /* XXX -- possibly allow here doc to be delimited by ending right
3954 paren. */
3955 if ((tflags & LEX_INHEREDOC) && ch == close && count == 1)
3956 {
3957 int tind;
a0c0a00f 3958/*itrace("parse_comsub:%d: in here doc, ch == close, retind - firstind = %d hdlen = %d retind = %d", line_number, retind-lex_firstind, hdlen, retind);*/
0001803f
CR
3959 tind = lex_firstind;
3960 while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
3961 tind++;
3962 if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen))
3963 {
a0c0a00f
CR
3964 tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC|LEX_QUOTEDDOC);
3965/*itrace("parse_comsub:%d: found here doc end `%*s'", line_number, hdlen, ret + tind);*/
0001803f
CR
3966 free (heredelim);
3967 heredelim = 0;
3968 lex_firstind = -1;
3969 }
3970 }
3971
a0c0a00f
CR
3972 /* Don't bother counting parens or doing anything else if in a comment or
3973 here document (not exactly right for here-docs -- if we want to allow
3974 recursive calls to parse_comsub to have their own here documents,
3975 change the LEX_INHEREDOC to LEX_QUOTEDDOC here and uncomment the next
3976 clause below. Note that to make this work completely, we need to make
3977 additional changes to allow xparse_dolparen to work right when the
3978 command substitution is parsed, because read_secondary_line doesn't know
3979 to recursively parse through command substitutions embedded in here-
3980 documents */
3185942a
JA
3981 if (tflags & (LEX_INCOMMENT|LEX_INHEREDOC))
3982 {
3983 /* Add this character. */
3984 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3985 ret[retind++] = ch;
3986
3987 if ((tflags & LEX_INCOMMENT) && ch == '\n')
ac50fbac 3988 {
0001803f 3989/*itrace("parse_comsub:%d: lex_incomment -> 0 ch = `%c'", line_number, ch);*/
ac50fbac
CR
3990 tflags &= ~LEX_INCOMMENT;
3991 }
3185942a
JA
3992
3993 continue;
3994 }
a0c0a00f
CR
3995#if 0
3996 /* If we're going to recursively parse a command substitution inside a
3997 here-document, make sure we call parse_comsub recursively below. See
3998 above for additional caveats. */
3999 if ((tflags & LEX_INHEREDOC) && ((tflags & LEX_WASDOL) == 0 || ch != '(')) /*)*/
4000 {
4001 /* Add this character. */
4002 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4003 ret[retind++] = ch;
4004 if MBTEST(ch == '$')
4005 tflags |= LEX_WASDOL;
4006 else
4007 tflags &= ~LEX_WASDOL;
4008 }
4009#endif
3185942a 4010
89a92869
CR
4011 if (tflags & LEX_PASSNEXT) /* last char was backslash */
4012 {
4013/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
4014 tflags &= ~LEX_PASSNEXT;
4015 if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
4016 {
4017 if (retind > 0)
4018 retind--; /* swallow previously-added backslash */
4019 continue;
4020 }
4021
4022 RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
ac50fbac 4023 if MBTEST(ch == CTLESC)
89a92869
CR
4024 ret[retind++] = CTLESC;
4025 ret[retind++] = ch;
4026 continue;
4027 }
4028
4029 /* If this is a shell break character, we are not in a word. If not,
4030 we either start or continue a word. */
4031 if MBTEST(shellbreak (ch))
4032 {
4033 tflags &= ~LEX_INWORD;
4034/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
4035 }
4036 else
4037 {
4038 if (tflags & LEX_INWORD)
4039 {
4040 lex_wlen++;
4041/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
4042 }
4043 else
4044 {
4045/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
4046 tflags |= LEX_INWORD;
4047 lex_wlen = 0;
ae339e9c
CR
4048 if (tflags & LEX_RESWDOK)
4049 lex_rwlen = 0;
89a92869
CR
4050 }
4051 }
4052
3185942a 4053 /* Skip whitespace */
495aee44 4054 if MBTEST(shellblank (ch) && (tflags & LEX_HEREDELIM) == 0 && lex_rwlen == 0)
3185942a
JA
4055 {
4056 /* Add this character. */
4057 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4058 ret[retind++] = ch;
4059 continue;
4060 }
4061
4062 /* Either we are looking for the start of the here-doc delimiter
4063 (lex_firstind == -1) or we are reading one (lex_firstind >= 0).
4064 If this character is a shell break character and we are reading
4065 the delimiter, save it and note that we are now reading a here
4066 document. If we've found the start of the delimiter, note it by
4067 setting lex_firstind. Backslashes can quote shell metacharacters
4068 in here-doc delimiters. */
4069 if (tflags & LEX_HEREDELIM)
4070 {
4071 if (lex_firstind == -1 && shellbreak (ch) == 0)
4072 lex_firstind = retind;
0001803f
CR
4073#if 0
4074 else if (heredelim && (tflags & LEX_PASSNEXT) == 0 && ch == '\n')
4075 {
4076 tflags |= LEX_INHEREDOC;
4077 tflags &= ~LEX_HEREDELIM;
4078 lex_firstind = retind + 1;
4079 }
4080#endif
3185942a
JA
4081 else if (lex_firstind >= 0 && (tflags & LEX_PASSNEXT) == 0 && shellbreak (ch))
4082 {
0001803f
CR
4083 if (heredelim == 0)
4084 {
4085 nestret = substring (ret, lex_firstind, retind);
4086 heredelim = string_quote_removal (nestret, 0);
0001803f 4087 hdlen = STRLEN(heredelim);
3185942a 4088/*itrace("parse_comsub:%d: found here doc delimiter `%s' (%d)", line_number, heredelim, hdlen);*/
a0c0a00f
CR
4089 if (STREQ (heredelim, nestret) == 0)
4090 tflags |= LEX_QUOTEDDOC;
4091 free (nestret);
0001803f 4092 }
3185942a
JA
4093 if (ch == '\n')
4094 {
4095 tflags |= LEX_INHEREDOC;
4096 tflags &= ~LEX_HEREDELIM;
4097 lex_firstind = retind + 1;
4098 }
4099 else
4100 lex_firstind = -1;
4101 }
4102 }
4103
4104 /* Meta-characters that can introduce a reserved word. Not perfect yet. */
89a92869 4105 if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && (shellmeta(ch) || ch == '\n'))
95732b49 4106 {
3185942a
JA
4107 /* Add this character. */
4108 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4109 ret[retind++] = ch;
4110 peekc = shell_getc (1);
4111 if (ch == peekc && (ch == '&' || ch == '|' || ch == ';')) /* two-character tokens */
4112 {
4113 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4114 ret[retind++] = peekc;
0001803f 4115/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
3185942a
JA
4116 tflags |= LEX_RESWDOK;
4117 lex_rwlen = 0;
4118 continue;
4119 }
4120 else if (ch == '\n' || COMSUB_META(ch))
4121 {
4122 shell_ungetc (peekc);
3185942a 4123/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
0001803f 4124 tflags |= LEX_RESWDOK;
3185942a
JA
4125 lex_rwlen = 0;
4126 continue;
4127 }
4128 else if (ch == EOF)
4129 goto eof_error;
4130 else
4131 {
4132 /* `unget' the character we just added and fall through */
4133 retind--;
4134 shell_ungetc (peekc);
4135 }
95732b49 4136 }
3185942a
JA
4137
4138 /* If we can read a reserved word, try to read one. */
4139 if (tflags & LEX_RESWDOK)
4140 {
a0c0a00f 4141 if MBTEST(islower ((unsigned char)ch))
3185942a
JA
4142 {
4143 /* Add this character. */
4144 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4145 ret[retind++] = ch;
4146 lex_rwlen++;
4147 continue;
4148 }
4149 else if MBTEST(lex_rwlen == 4 && shellbreak (ch))
4150 {
4151 if (STREQN (ret + retind - 4, "case", 4))
ac50fbac
CR
4152 {
4153 tflags |= LEX_INCASE;
a0c0a00f 4154 tflags &= ~LEX_RESWDOK;
0001803f 4155/*itrace("parse_comsub:%d: found `case', lex_incase -> 1 lex_reswdok -> 0", line_number);*/
ac50fbac 4156 }
3185942a 4157 else if (STREQN (ret + retind - 4, "esac", 4))
ac50fbac
CR
4158 {
4159 tflags &= ~LEX_INCASE;
a0c0a00f
CR
4160/*itrace("parse_comsub:%d: found `esac', lex_incase -> 0 lex_reswdok -> 1", line_number);*/
4161 tflags |= LEX_RESWDOK;
4162 lex_rwlen = 0;
4163 }
4164 else if (STREQN (ret + retind - 4, "done", 4) ||
4165 STREQN (ret + retind - 4, "then", 4) ||
4166 STREQN (ret + retind - 4, "else", 4) ||
4167 STREQN (ret + retind - 4, "elif", 4) ||
4168 STREQN (ret + retind - 4, "time", 4))
4169 {
4170 /* these are four-character reserved words that can be
4171 followed by a reserved word; anything else turns off
4172 the reserved-word-ok flag */
4173/*itrace("parse_comsub:%d: found `%.4s', lex_reswdok -> 1", line_number, ret+retind-4);*/
4174 tflags |= LEX_RESWDOK;
4175 lex_rwlen = 0;
4176 }
d233b485 4177 else if (shellmeta (ch) == 0)
a0c0a00f
CR
4178 {
4179 tflags &= ~LEX_RESWDOK;
4180/*itrace("parse_comsub:%d: found `%.4s', lex_reswdok -> 0", line_number, ret+retind-4);*/
ac50fbac 4181 }
d233b485
CR
4182 else /* can't be in a reserved word any more */
4183 lex_rwlen = 0;
3185942a 4184 }
89a92869
CR
4185 else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
4186 ; /* don't modify LEX_RESWDOK if we're starting a comment */
ac50fbac
CR
4187 /* Allow `do' followed by space, tab, or newline to preserve the
4188 RESWDOK flag, but reset the reserved word length counter so we
4189 can read another one. */
4190 else if MBTEST(((tflags & LEX_INCASE) == 0) &&
a0c0a00f 4191 (isblank((unsigned char)ch) || ch == '\n') &&
ac50fbac
CR
4192 lex_rwlen == 2 &&
4193 STREQN (ret + retind - 2, "do", 2))
4194 {
a0c0a00f 4195/*itrace("parse_comsub:%d: lex_incase == 0 found `%c', found \"do\"", line_number, ch);*/
ac50fbac
CR
4196 lex_rwlen = 0;
4197 }
89a92869
CR
4198 else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
4199 /* If we can read a reserved word and we're in case, we're at the
4200 point where we can read a new pattern list or an esac. We
4201 handle the esac case above. If we read a newline, we want to
4202 leave LEX_RESWDOK alone. If we read anything else, we want to
4203 turn off LEX_RESWDOK, since we're going to read a pattern list. */
ac50fbac
CR
4204 {
4205 tflags &= ~LEX_RESWDOK;
89a92869 4206/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
ac50fbac 4207 }
89a92869 4208 else if MBTEST(shellbreak (ch) == 0)
ac50fbac
CR
4209 {
4210 tflags &= ~LEX_RESWDOK;
3185942a 4211/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
ac50fbac
CR
4212 }
4213#if 0
4214 /* If we find a space or tab but have read something and it's not
4215 `do', turn off the reserved-word-ok flag */
a0c0a00f 4216 else if MBTEST(isblank ((unsigned char)ch) && lex_rwlen > 0)
ac50fbac
CR
4217 {
4218 tflags &= ~LEX_RESWDOK;
4219/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
4220 }
4221#endif
3185942a
JA
4222 }
4223
0001803f 4224 /* Might be the start of a here-doc delimiter */
3185942a
JA
4225 if MBTEST((tflags & LEX_INCOMMENT) == 0 && (tflags & LEX_CKCASE) && ch == '<')
4226 {
4227 /* Add this character. */
4228 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4229 ret[retind++] = ch;
4230 peekc = shell_getc (1);
4231 if (peekc == EOF)
4232 goto eof_error;
4233 if (peekc == ch)
4234 {
4235 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4236 ret[retind++] = peekc;
4237 peekc = shell_getc (1);
4238 if (peekc == EOF)
4239 goto eof_error;
4240 if (peekc == '-')
4241 {
4242 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4243 ret[retind++] = peekc;
4244 tflags |= LEX_STRIPDOC;
4245 }
4246 else
4247 shell_ungetc (peekc);
89a92869
CR
4248 if (peekc != '<')
4249 {
4250 tflags |= LEX_HEREDELIM;
4251 lex_firstind = -1;
4252 }
3185942a
JA
4253 continue;
4254 }
4255 else
d233b485
CR
4256 {
4257 shell_ungetc (peekc); /* not a here-doc, start over */
4258 continue;
4259 }
3185942a 4260 }
89a92869 4261 else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
ac50fbac 4262 {
89a92869 4263/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
ac50fbac
CR
4264 tflags |= LEX_INCOMMENT;
4265 }
3185942a 4266
89a92869 4267 if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
3185942a
JA
4268 {
4269 RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
4270 ret[retind++] = CTLESC;
4271 ret[retind++] = ch;
4272 continue;
4273 }
4274#if 0
4275 else if MBTEST((tflags & LEX_INCASE) && ch == close && close == ')')
4276 tflags &= ~LEX_INCASE; /* XXX */
0628567a 4277#endif
3185942a 4278 else if MBTEST(ch == close && (tflags & LEX_INCASE) == 0) /* ending delimiter */
ac50fbac
CR
4279 {
4280 count--;
3185942a 4281/*itrace("parse_comsub:%d: found close: count = %d", line_number, count);*/
ac50fbac 4282 }
3185942a 4283 else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && (tflags & LEX_INCASE) == 0 && ch == open) /* nested begin */
ac50fbac
CR
4284 {
4285 count++;
0001803f 4286/*itrace("parse_comsub:%d: found open: count = %d", line_number, count);*/
ac50fbac 4287 }
3185942a
JA
4288
4289 /* Add this character. */
4290 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
4291 ret[retind++] = ch;
4292
4293 /* If we just read the ending character, don't bother continuing. */
4294 if (count == 0)
4295 break;
4296
4297 if MBTEST(ch == '\\') /* backslashes */
4298 tflags |= LEX_PASSNEXT;
4299
4300 if MBTEST(shellquote (ch))
4301 {
4302 /* '', ``, or "" inside $(...). */
4303 push_delimiter (dstack, ch);
4304 if MBTEST((tflags & LEX_WASDOL) && ch == '\'') /* $'...' inside group */
4305 nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
4306 else
4307 nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
4308 pop_delimiter (dstack);
4309 CHECK_NESTRET_ERROR ();
4310
4311 if MBTEST((tflags & LEX_WASDOL) && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
4312 {
4313 /* Translate $'...' here. */
4314 ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
d233b485 4315 free (nestret);
3185942a
JA
4316
4317 if ((rflags & P_DQUOTE) == 0)
4318 {
4319 nestret = sh_single_quote (ttrans);
4320 free (ttrans);
4321 nestlen = strlen (nestret);
4322 }
4323 else
4324 {
4325 nestret = ttrans;
4326 nestlen = ttranslen;
4327 }
4328 retind -= 2; /* back up before the $' */
4329 }
4330 else if MBTEST((tflags & LEX_WASDOL) && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
4331 {
4332 /* Locale expand $"..." here. */
4333 ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
d233b485 4334 free (nestret);
3185942a
JA
4335
4336 nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
4337 free (ttrans);
4338 nestlen = ttranslen + 2;
4339 retind -= 2; /* back up before the $" */
4340 }
4341
4342 APPEND_NESTRET ();
4343 FREE (nestret);
4344 }
4345 else if MBTEST((tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
4346 /* check for $(), $[], or ${} inside command substitution. */
ccc6cda3 4347 {
3185942a 4348 if ((tflags & LEX_INCASE) == 0 && open == ch) /* undo previous increment */
ccc6cda3
JA
4349 count--;
4350 if (ch == '(') /* ) */
3185942a 4351 nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
ccc6cda3 4352 else if (ch == '{') /* } */
495aee44 4353 nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
ccc6cda3 4354 else if (ch == '[') /* ] */
b80f6443 4355 nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
95732b49 4356
3185942a
JA
4357 CHECK_NESTRET_ERROR ();
4358 APPEND_NESTRET ();
4359
4360 FREE (nestret);
ccc6cda3 4361 }
d233b485 4362 if MBTEST(ch == '$' && (tflags & LEX_WASDOL) == 0)
3185942a
JA
4363 tflags |= LEX_WASDOL;
4364 else
4365 tflags &= ~LEX_WASDOL;
ccc6cda3 4366 }
726f6388 4367
3185942a 4368 FREE (heredelim);
ccc6cda3
JA
4369 ret[retind] = '\0';
4370 if (lenp)
4371 *lenp = retind;
3185942a
JA
4372/*itrace("parse_comsub:%d: returning `%s'", line_number, ret);*/
4373 return ret;
4374}
4375
495aee44 4376/* Recursively call the parser to parse a $(...) command substitution. */
3185942a
JA
4377char *
4378xparse_dolparen (base, string, indp, flags)
4379 char *base;
4380 char *string;
4381 int *indp;
4382 int flags;
4383{
4384 sh_parser_state_t ps;
b4839c27 4385 sh_input_line_state_t ls;
ac50fbac 4386 int orig_ind, nc, sflags, orig_eof_token;
d233b485
CR
4387 char *ret, *ep, *ostring;
4388#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
4389 STRING_SAVER *saved_pushed_strings;
4390#endif
3185942a 4391
d233b485 4392/*debug_parser(1);*/
3185942a
JA
4393 orig_ind = *indp;
4394 ostring = string;
4395
d233b485
CR
4396 if (*string == 0)
4397 {
4398 if (flags & SX_NOALLOC)
4399 return (char *)NULL;
4400
4401 ret = xmalloc (1);
4402 ret[0] = '\0';
4403 return ret;
4404 }
4405
b4839c27 4406/*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/
3185942a
JA
4407 sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
4408 if (flags & SX_NOLONGJMP)
4409 sflags |= SEVAL_NOLONGJMP;
4410 save_parser_state (&ps);
b4839c27 4411 save_input_line_state (&ls);
ac50fbac 4412 orig_eof_token = shell_eof_token;
d233b485
CR
4413#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
4414 saved_pushed_strings = pushed_string_list; /* separate parsing context */
4415 pushed_string_list = (STRING_SAVER *)NULL;
4416#endif
3185942a
JA
4417
4418 /*(*/
4419 parser_state |= PST_CMDSUBST|PST_EOFTOKEN; /* allow instant ')' */ /*(*/
4420 shell_eof_token = ')';
a0c0a00f 4421
d233b485
CR
4422 /* Should we save and restore the bison/yacc lookahead token (yychar) here?
4423 Or only if it's not YYEMPTY? */
4424
a0c0a00f 4425 nc = parse_string (string, "command substitution", sflags, &ep);
3185942a 4426
d233b485
CR
4427 if (current_token == shell_eof_token)
4428 yyclearin; /* might want to clear lookahead token unconditionally */
4429
ac50fbac 4430 shell_eof_token = orig_eof_token;
3185942a
JA
4431 restore_parser_state (&ps);
4432 reset_parser ();
b4839c27
CR
4433 /* reset_parser clears shell_input_line and associated variables */
4434 restore_input_line_state (&ls);
ca6a2ba4 4435
d233b485
CR
4436#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
4437 pushed_string_list = saved_pushed_strings;
4438#endif
4439
ca6a2ba4 4440 token_to_read = 0;
3185942a 4441
a0c0a00f 4442 /* If parse_string returns < 0, we need to jump to top level with the
d233b485
CR
4443 negative of the return value. We abandon the rest of this input line
4444 first */
a0c0a00f 4445 if (nc < 0)
d233b485
CR
4446 {
4447 clear_shell_input_line (); /* XXX */
4448 jump_to_top_level (-nc); /* XXX */
4449 }
a0c0a00f 4450
3185942a
JA
4451 /* Need to find how many characters parse_and_execute consumed, update
4452 *indp, if flags != 0, copy the portion of the string parsed into RET
d233b485 4453 and return it. If flags & 1 (SX_NOALLOC) we can return NULL. */
3185942a
JA
4454
4455 /*(*/
4456 if (ep[-1] != ')')
4457 {
4458#if DEBUG
4459 if (ep[-1] != '\n')
4460 itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
4461#endif
4462 while (ep > ostring && ep[-1] == '\n') ep--;
4463 }
4464
4465 nc = ep - ostring;
4466 *indp = ep - base - 1;
4467
4468 /*(*/
4469#if DEBUG
4470 if (base[*indp] != ')')
4471 itrace("xparse_dolparen:%d: base[%d] != RPAREN (%d), base = `%s'", line_number, *indp, base[*indp], base);
d233b485
CR
4472 if (*indp < orig_ind)
4473 itrace("xparse_dolparen:%d: *indp (%d) < orig_ind (%d), orig_string = `%s'", line_number, *indp, orig_ind, ostring);
3185942a
JA
4474#endif
4475
4476 if (flags & SX_NOALLOC)
4477 return (char *)NULL;
4478
4479 if (nc == 0)
4480 {
4481 ret = xmalloc (1);
4482 ret[0] = '\0';
4483 }
4484 else
4485 ret = substring (ostring, 0, nc - 1);
4486
ccc6cda3
JA
4487 return ret;
4488}
726f6388 4489
bb70624e 4490#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
7117c2d2
JA
4491/* Parse a double-paren construct. It can be either an arithmetic
4492 command, an arithmetic `for' command, or a nested subshell. Returns
4493 the parsed token, -1 on error, or -2 if we didn't do anything and
4494 should just go on. */
4495static int
4496parse_dparen (c)
4497 int c;
4498{
0628567a
JA
4499 int cmdtyp, sline;
4500 char *wval;
7117c2d2
JA
4501 WORD_DESC *wd;
4502
4503#if defined (ARITH_FOR_COMMAND)
4504 if (last_read_token == FOR)
4505 {
4506 arith_for_lineno = line_number;
b80f6443 4507 cmdtyp = parse_arith_cmd (&wval, 0);
7117c2d2
JA
4508 if (cmdtyp == 1)
4509 {
95732b49
JA
4510 wd = alloc_word_desc ();
4511 wd->word = wval;
7117c2d2 4512 yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
7117c2d2
JA
4513 return (ARITH_FOR_EXPRS);
4514 }
4515 else
4516 return -1; /* ERROR */
4517 }
4518#endif
4519
4520#if defined (DPAREN_ARITHMETIC)
4521 if (reserved_word_acceptable (last_read_token))
4522 {
4523 sline = line_number;
95732b49 4524
b80f6443 4525 cmdtyp = parse_arith_cmd (&wval, 0);
7117c2d2
JA
4526 if (cmdtyp == 1) /* arithmetic command */
4527 {
95732b49
JA
4528 wd = alloc_word_desc ();
4529 wd->word = wval;
4530 wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
7117c2d2 4531 yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
7117c2d2
JA
4532 return (ARITH_CMD);
4533 }
4534 else if (cmdtyp == 0) /* nested subshell */
4535 {
4536 push_string (wval, 0, (alias_t *)NULL);
ac50fbac 4537 pushed_string_list->flags = PSH_DPAREN;
7117c2d2
JA
4538 if ((parser_state & PST_CASEPAT) == 0)
4539 parser_state |= PST_SUBSHELL;
4540 return (c);
4541 }
4542 else /* ERROR */
4543 return -1;
4544 }
4545#endif
4546
4547 return -2; /* XXX */
4548}
4549
d166f048
JA
4550/* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
4551 If not, assume it's a nested subshell for backwards compatibility and
4552 return 0. In any case, put the characters we've consumed into a locally-
4553 allocated buffer and make *ep point to that buffer. Return -1 on an
4554 error, for example EOF. */
4555static int
b80f6443 4556parse_arith_cmd (ep, adddq)
d166f048 4557 char **ep;
b80f6443 4558 int adddq;
d166f048
JA
4559{
4560 int exp_lineno, rval, c;
f73dda09 4561 char *ttok, *tokstr;
d166f048
JA
4562 int ttoklen;
4563
4564 exp_lineno = line_number;
4565 ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
4566 rval = 1;
4567 if (ttok == &matched_pair_error)
4568 return -1;
4569 /* Check that the next character is the closing right paren. If
4570 not, this is a syntax error. ( */
7117c2d2
JA
4571 c = shell_getc (0);
4572 if MBTEST(c != ')')
d166f048
JA
4573 rval = 0;
4574
f73dda09 4575 tokstr = (char *)xmalloc (ttoklen + 4);
d166f048 4576
b80f6443
JA
4577 /* if ADDDQ != 0 then (( ... )) -> "..." */
4578 if (rval == 1 && adddq) /* arith cmd, add double quotes */
d166f048 4579 {
b80f6443
JA
4580 tokstr[0] = '"';
4581 strncpy (tokstr + 1, ttok, ttoklen - 1);
f73dda09
JA
4582 tokstr[ttoklen] = '"';
4583 tokstr[ttoklen+1] = '\0';
d166f048 4584 }
b80f6443 4585 else if (rval == 1) /* arith cmd, don't add double quotes */
d166f048 4586 {
b80f6443
JA
4587 strncpy (tokstr, ttok, ttoklen - 1);
4588 tokstr[ttoklen-1] = '\0';
4589 }
4590 else /* nested subshell */
4591 {
4592 tokstr[0] = '(';
4593 strncpy (tokstr + 1, ttok, ttoklen - 1);
f73dda09
JA
4594 tokstr[ttoklen] = ')';
4595 tokstr[ttoklen+1] = c;
4596 tokstr[ttoklen+2] = '\0';
d166f048 4597 }
b80f6443 4598
f73dda09 4599 *ep = tokstr;
d166f048
JA
4600 FREE (ttok);
4601 return rval;
4602}
bb70624e 4603#endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
d166f048 4604
cce855bc 4605#if defined (COND_COMMAND)
7117c2d2
JA
4606static void
4607cond_error ()
4608{
4609 char *etext;
4610
4611 if (EOF_Reached && cond_token != COND_ERROR) /* [[ */
b80f6443 4612 parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
7117c2d2
JA
4613 else if (cond_token != COND_ERROR)
4614 {
4615 if (etext = error_token_from_token (cond_token))
4616 {
b80f6443 4617 parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
7117c2d2
JA
4618 free (etext);
4619 }
4620 else
b80f6443 4621 parser_error (cond_lineno, _("syntax error in conditional expression"));
7117c2d2
JA
4622 }
4623}
4624
cce855bc
JA
4625static COND_COM *
4626cond_expr ()
4627{
4628 return (cond_or ());
4629}
4630
4631static COND_COM *
4632cond_or ()
4633{
4634 COND_COM *l, *r;
4635
4636 l = cond_and ();
4637 if (cond_token == OR_OR)
4638 {
4639 r = cond_or ();
4640 l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
4641 }
4642 return l;
4643}
4644
4645static COND_COM *
4646cond_and ()
4647{
4648 COND_COM *l, *r;
4649
4650 l = cond_term ();
4651 if (cond_token == AND_AND)
4652 {
4653 r = cond_and ();
4654 l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
4655 }
4656 return l;
4657}
4658
4659static int
4660cond_skip_newlines ()
4661{
4662 while ((cond_token = read_token (READ)) == '\n')
4663 {
b80f6443 4664 if (SHOULD_PROMPT ())
cce855bc
JA
4665 prompt_again ();
4666 }
4667 return (cond_token);
4668}
4669
4670#define COND_RETURN_ERROR() \
4671 do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
4672
4673static COND_COM *
4674cond_term ()
4675{
4676 WORD_DESC *op;
4677 COND_COM *term, *tleft, *tright;
4678 int tok, lineno;
7117c2d2 4679 char *etext;
cce855bc
JA
4680
4681 /* Read a token. It can be a left paren, a `!', a unary operator, or a
4682 word that should be the first argument of a binary operator. Start by
4683 skipping newlines, since this is a compound command. */
4684 tok = cond_skip_newlines ();
4685 lineno = line_number;
4686 if (tok == COND_END)
4687 {
4688 COND_RETURN_ERROR ();
4689 }
4690 else if (tok == '(')
4691 {
4692 term = cond_expr ();
4693 if (cond_token != ')')
4694 {
4695 if (term)
4696 dispose_cond_node (term); /* ( */
7117c2d2
JA
4697 if (etext = error_token_from_token (cond_token))
4698 {
b80f6443 4699 parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
7117c2d2
JA
4700 free (etext);
4701 }
4702 else
b80f6443 4703 parser_error (lineno, _("expected `)'"));
cce855bc
JA
4704 COND_RETURN_ERROR ();
4705 }
4706 term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
4707 (void)cond_skip_newlines ();
4708 }
4709 else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
4710 {
4711 if (tok == WORD)
4712 dispose_word (yylval.word); /* not needed */
4713 term = cond_term ();
4714 if (term)
4715 term->flags |= CMD_INVERT_RETURN;
4716 }
d233b485 4717 else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[1] && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
cce855bc
JA
4718 {
4719 op = yylval.word;
4720 tok = read_token (READ);
4721 if (tok == WORD)
4722 {
4723 tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4724 term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
4725 }
4726 else
4727 {
4728 dispose_word (op);
7117c2d2
JA
4729 if (etext = error_token_from_token (tok))
4730 {
b80f6443 4731 parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
7117c2d2
JA
4732 free (etext);
4733 }
4734 else
b80f6443 4735 parser_error (line_number, _("unexpected argument to conditional unary operator"));
cce855bc
JA
4736 COND_RETURN_ERROR ();
4737 }
4738
4739 (void)cond_skip_newlines ();
4740 }
bb70624e 4741 else if (tok == WORD) /* left argument to binary operator */
cce855bc
JA
4742 {
4743 /* lhs */
4744 tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4745
4746 /* binop */
4747 tok = read_token (READ);
4748 if (tok == WORD && test_binop (yylval.word->word))
0001803f
CR
4749 {
4750 op = yylval.word;
4751 if (op->word[0] == '=' && (op->word[1] == '\0' || (op->word[1] == '=' && op->word[2] == '\0')))
4752 parser_state |= PST_EXTPAT;
4753 else if (op->word[0] == '!' && op->word[1] == '=' && op->word[2] == '\0')
4754 parser_state |= PST_EXTPAT;
4755 }
b80f6443 4756#if defined (COND_REGEXP)
f1be666c
JA
4757 else if (tok == WORD && STREQ (yylval.word->word, "=~"))
4758 {
4759 op = yylval.word;
4760 parser_state |= PST_REGEXP;
4761 }
b80f6443 4762#endif
cce855bc 4763 else if (tok == '<' || tok == '>')
28ef6c31
JA
4764 op = make_word_from_token (tok); /* ( */
4765 /* There should be a check before blindly accepting the `)' that we have
4766 seen the opening `('. */
4767 else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
cce855bc
JA
4768 {
4769 /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
4770 the test command. Similarly for [[ x && expr ]] or
28ef6c31 4771 [[ x || expr ]] or [[ (x) ]]. */
cce855bc
JA
4772 op = make_word ("-n");
4773 term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
4774 cond_token = tok;
4775 return (term);
4776 }
4777 else
4778 {
7117c2d2
JA
4779 if (etext = error_token_from_token (tok))
4780 {
b80f6443 4781 parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
7117c2d2
JA
4782 free (etext);
4783 }
4784 else
b80f6443 4785 parser_error (line_number, _("conditional binary operator expected"));
cce855bc
JA
4786 dispose_cond_node (tleft);
4787 COND_RETURN_ERROR ();
4788 }
4789
4790 /* rhs */
0001803f
CR
4791 if (parser_state & PST_EXTPAT)
4792 extended_glob = 1;
cce855bc 4793 tok = read_token (READ);
0001803f
CR
4794 if (parser_state & PST_EXTPAT)
4795 extended_glob = global_extglob;
4796 parser_state &= ~(PST_REGEXP|PST_EXTPAT);
4797
cce855bc
JA
4798 if (tok == WORD)
4799 {
4800 tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4801 term = make_cond_node (COND_BINARY, op, tleft, tright);
4802 }
4803 else
4804 {
7117c2d2
JA
4805 if (etext = error_token_from_token (tok))
4806 {
b80f6443 4807 parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
7117c2d2
JA
4808 free (etext);
4809 }
4810 else
b80f6443 4811 parser_error (line_number, _("unexpected argument to conditional binary operator"));
cce855bc
JA
4812 dispose_cond_node (tleft);
4813 dispose_word (op);
4814 COND_RETURN_ERROR ();
4815 }
4816
4817 (void)cond_skip_newlines ();
4818 }
bb70624e
JA
4819 else
4820 {
4821 if (tok < 256)
b80f6443 4822 parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
7117c2d2
JA
4823 else if (etext = error_token_from_token (tok))
4824 {
b80f6443 4825 parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
7117c2d2
JA
4826 free (etext);
4827 }
bb70624e 4828 else
b80f6443 4829 parser_error (line_number, _("unexpected token %d in conditional command"), tok);
bb70624e
JA
4830 COND_RETURN_ERROR ();
4831 }
cce855bc
JA
4832 return (term);
4833}
4834
4835/* This is kind of bogus -- we slip a mini recursive-descent parser in
4836 here to handle the conditional statement syntax. */
4837static COMMAND *
4838parse_cond_command ()
4839{
4840 COND_COM *cexp;
4841
0001803f 4842 global_extglob = extended_glob;
cce855bc
JA
4843 cexp = cond_expr ();
4844 return (make_cond_command (cexp));
4845}
4846#endif
4847
7117c2d2
JA
4848#if defined (ARRAY_VARS)
4849/* When this is called, it's guaranteed that we don't care about anything
d233b485
CR
4850 in t beyond i. We use a buffer with room for the characters we add just
4851 in case assignment() ends up doing something like parsing a command
4852 substitution that will reallocate atoken. We don't want to write beyond
4853 the end of an allocated buffer. */
7117c2d2
JA
4854static int
4855token_is_assignment (t, i)
4856 char *t;
4857 int i;
4858{
7117c2d2 4859 int r;
d233b485 4860 char *atoken;
7117c2d2 4861
d233b485
CR
4862 atoken = xmalloc (i + 3);
4863 memcpy (atoken, t, i);
4864 atoken[i] = '=';
4865 atoken[i+1] = '\0';
4866
4867 r = assignment (atoken, (parser_state & PST_COMPASSIGN) != 0);
4868
4869 free (atoken);
4870
4871 /* XXX - check that r == i to avoid returning false positive for
4872 t containing `=' before t[i]. */
4873 return (r > 0 && r == i);
7117c2d2
JA
4874}
4875
95732b49 4876/* XXX - possible changes here for `+=' */
7117c2d2
JA
4877static int
4878token_is_ident (t, i)
4879 char *t;
4880 int i;
4881{
4882 unsigned char c;
4883 int r;
4884
4885 c = t[i];
4886 t[i] = '\0';
4887 r = legal_identifier (t);
4888 t[i] = c;
4889 return r;
4890}
4891#endif
4892
ccc6cda3
JA
4893static int
4894read_token_word (character)
4895 int character;
4896{
4897 /* The value for YYLVAL when a WORD is read. */
4898 WORD_DESC *the_word;
726f6388 4899
ccc6cda3
JA
4900 /* Index into the token that we are building. */
4901 int token_index;
726f6388 4902
ccc6cda3 4903 /* ALL_DIGITS becomes zero when we see a non-digit. */
f73dda09 4904 int all_digit_token;
726f6388 4905
ccc6cda3
JA
4906 /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
4907 int dollar_present;
726f6388 4908
95732b49
JA
4909 /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
4910 assignment. */
4911 int compound_assignment;
4912
ccc6cda3
JA
4913 /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
4914 int quoted;
726f6388 4915
ccc6cda3
JA
4916 /* Non-zero means to ignore the value of the next character, and just
4917 to add it no matter what. */
a0c0a00f 4918 int pass_next_character;
726f6388 4919
ccc6cda3
JA
4920 /* The current delimiting character. */
4921 int cd;
4922 int result, peek_char;
4923 char *ttok, *ttrans;
4924 int ttoklen, ttranslen;
7117c2d2 4925 intmax_t lvalue;
726f6388 4926
d166f048 4927 if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
f73dda09 4928 token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
726f6388 4929
ccc6cda3 4930 token_index = 0;
f73dda09 4931 all_digit_token = DIGIT (character);
95732b49 4932 dollar_present = quoted = pass_next_character = compound_assignment = 0;
726f6388 4933
ccc6cda3
JA
4934 for (;;)
4935 {
4936 if (character == EOF)
4937 goto got_token;
726f6388 4938
ccc6cda3
JA
4939 if (pass_next_character)
4940 {
4941 pass_next_character = 0;
f1be666c 4942 goto got_escaped_character;
ccc6cda3 4943 }
726f6388 4944
ccc6cda3 4945 cd = current_delimiter (dstack);
726f6388 4946
ccc6cda3
JA
4947 /* Handle backslashes. Quote lots of things when not inside of
4948 double-quotes, quote some things inside of double-quotes. */
7117c2d2 4949 if MBTEST(character == '\\')
ccc6cda3
JA
4950 {
4951 peek_char = shell_getc (0);
726f6388 4952
ccc6cda3
JA
4953 /* Backslash-newline is ignored in all cases except
4954 when quoted with single quotes. */
4955 if (peek_char == '\n')
4956 {
4957 character = '\n';
4958 goto next_character;
4959 }
4960 else
4961 {
4962 shell_ungetc (peek_char);
726f6388 4963
ccc6cda3
JA
4964 /* If the next character is to be quoted, note it now. */
4965 if (cd == 0 || cd == '`' ||
f73dda09 4966 (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
ccc6cda3 4967 pass_next_character++;
726f6388 4968
ccc6cda3
JA
4969 quoted = 1;
4970 goto got_character;
4971 }
4972 }
726f6388 4973
ccc6cda3 4974 /* Parse a matched pair of quote characters. */
7117c2d2 4975 if MBTEST(shellquote (character))
ccc6cda3
JA
4976 {
4977 push_delimiter (dstack, character);
95732b49 4978 ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
ccc6cda3
JA
4979 pop_delimiter (dstack);
4980 if (ttok == &matched_pair_error)
4981 return -1; /* Bail immediately. */
4982 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4983 token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
4984 token[token_index++] = character;
4985 strcpy (token + token_index, ttok);
4986 token_index += ttoklen;
f73dda09 4987 all_digit_token = 0;
d233b485
CR
4988 if (character != '`')
4989 quoted = 1;
ccc6cda3
JA
4990 dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
4991 FREE (ttok);
4992 goto next_character;
4993 }
726f6388 4994
f1be666c
JA
4995#ifdef COND_REGEXP
4996 /* When parsing a regexp as a single word inside a conditional command,
4997 we need to special-case characters special to both the shell and
4998 regular expressions. Right now, that is only '(' and '|'. */ /*)*/
4999 if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|')) /*)*/
3185942a
JA
5000 {
5001 if (character == '|')
5002 goto got_character;
f1be666c
JA
5003
5004 push_delimiter (dstack, character);
5005 ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
5006 pop_delimiter (dstack);
5007 if (ttok == &matched_pair_error)
5008 return -1; /* Bail immediately. */
5009 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
5010 token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
5011 token[token_index++] = character;
5012 strcpy (token + token_index, ttok);
5013 token_index += ttoklen;
5014 FREE (ttok);
5015 dollar_present = all_digit_token = 0;
5016 goto next_character;
3185942a 5017 }
f1be666c
JA
5018#endif /* COND_REGEXP */
5019
cce855bc
JA
5020#ifdef EXTENDED_GLOB
5021 /* Parse a ksh-style extended pattern matching specification. */
f1be666c 5022 if MBTEST(extended_glob && PATTERN_CHAR (character))
cce855bc
JA
5023 {
5024 peek_char = shell_getc (1);
7117c2d2 5025 if MBTEST(peek_char == '(') /* ) */
cce855bc
JA
5026 {
5027 push_delimiter (dstack, peek_char);
5028 ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
5029 pop_delimiter (dstack);
5030 if (ttok == &matched_pair_error)
5031 return -1; /* Bail immediately. */
ac50fbac 5032 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
cce855bc
JA
5033 token_buffer_size,
5034 TOKEN_DEFAULT_GROW_SIZE);
5035 token[token_index++] = character;
5036 token[token_index++] = peek_char;
5037 strcpy (token + token_index, ttok);
5038 token_index += ttoklen;
5039 FREE (ttok);
f73dda09 5040 dollar_present = all_digit_token = 0;
cce855bc
JA
5041 goto next_character;
5042 }
5043 else
5044 shell_ungetc (peek_char);
5045 }
5046#endif /* EXTENDED_GLOB */
5047
ccc6cda3
JA
5048 /* If the delimiter character is not single quote, parse some of
5049 the shell expansions that must be read as a single word. */
28ef6c31 5050 if (shellexp (character))
ccc6cda3
JA
5051 {
5052 peek_char = shell_getc (1);
5053 /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
ac50fbac 5054 if MBTEST(peek_char == '(' ||
ccc6cda3
JA
5055 ((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
5056 {
5057 if (peek_char == '{') /* } */
495aee44 5058 ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE|P_DOLBRACE);
ccc6cda3 5059 else if (peek_char == '(') /* ) */
d166f048
JA
5060 {
5061 /* XXX - push and pop the `(' as a delimiter for use by
5062 the command-oriented-history code. This way newlines
5063 appearing in the $(...) string get added to the
5064 history literally rather than causing a possibly-
bb70624e 5065 incorrect `;' to be added. ) */
d166f048 5066 push_delimiter (dstack, peek_char);
3185942a 5067 ttok = parse_comsub (cd, '(', ')', &ttoklen, P_COMMAND);
d166f048
JA
5068 pop_delimiter (dstack);
5069 }
ccc6cda3
JA
5070 else
5071 ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
5072 if (ttok == &matched_pair_error)
5073 return -1; /* Bail immediately. */
ac50fbac 5074 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
ccc6cda3
JA
5075 token_buffer_size,
5076 TOKEN_DEFAULT_GROW_SIZE);
5077 token[token_index++] = character;
5078 token[token_index++] = peek_char;
5079 strcpy (token + token_index, ttok);
5080 token_index += ttoklen;
5081 FREE (ttok);
5082 dollar_present = 1;
f73dda09 5083 all_digit_token = 0;
ccc6cda3
JA
5084 goto next_character;
5085 }
5086 /* This handles $'...' and $"..." new-style quoted strings. */
7117c2d2 5087 else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
ccc6cda3 5088 {
cce855bc
JA
5089 int first_line;
5090
5091 first_line = line_number;
bb70624e
JA
5092 push_delimiter (dstack, peek_char);
5093 ttok = parse_matched_pair (peek_char, peek_char, peek_char,
5094 &ttoklen,
5095 (peek_char == '\'') ? P_ALLOWESC : 0);
5096 pop_delimiter (dstack);
ccc6cda3
JA
5097 if (ttok == &matched_pair_error)
5098 return -1;
5099 if (peek_char == '\'')
bb70624e
JA
5100 {
5101 ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
5102 free (ttok);
95732b49 5103
bb70624e
JA
5104 /* Insert the single quotes and correctly quote any
5105 embedded single quotes (allowed because P_ALLOWESC was
5106 passed to parse_matched_pair). */
28ef6c31 5107 ttok = sh_single_quote (ttrans);
bb70624e 5108 free (ttrans);
95732b49 5109 ttranslen = strlen (ttok);
bb70624e 5110 ttrans = ttok;
bb70624e 5111 }
ccc6cda3 5112 else
bb70624e 5113 {
0628567a 5114 /* Try to locale-expand the converted string. */
bb70624e
JA
5115 ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
5116 free (ttok);
5117
5118 /* Add the double quotes back */
95732b49 5119 ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
bb70624e 5120 free (ttrans);
95732b49 5121 ttranslen += 2;
bb70624e
JA
5122 ttrans = ttok;
5123 }
5124
ac50fbac 5125 RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 1,
ccc6cda3
JA
5126 token_buffer_size,
5127 TOKEN_DEFAULT_GROW_SIZE);
ccc6cda3
JA
5128 strcpy (token + token_index, ttrans);
5129 token_index += ttranslen;
ccc6cda3
JA
5130 FREE (ttrans);
5131 quoted = 1;
f73dda09 5132 all_digit_token = 0;
ccc6cda3
JA
5133 goto next_character;
5134 }
b72432fd
JA
5135 /* This could eventually be extended to recognize all of the
5136 shell's single-character parameter expansions, and set flags.*/
7117c2d2 5137 else if MBTEST(character == '$' && peek_char == '$')
b72432fd 5138 {
b72432fd
JA
5139 RESIZE_MALLOCED_BUFFER (token, token_index, 3,
5140 token_buffer_size,
5141 TOKEN_DEFAULT_GROW_SIZE);
ac50fbac
CR
5142 token[token_index++] = '$';
5143 token[token_index++] = peek_char;
b72432fd 5144 dollar_present = 1;
f73dda09 5145 all_digit_token = 0;
b72432fd
JA
5146 goto next_character;
5147 }
ccc6cda3
JA
5148 else
5149 shell_ungetc (peek_char);
5150 }
726f6388 5151
ccc6cda3 5152#if defined (ARRAY_VARS)
3185942a
JA
5153 /* Identify possible array subscript assignment; match [...]. If
5154 parser_state&PST_COMPASSIGN, we need to parse [sub]=words treating
5155 `sub' as if it were enclosed in double quotes. */
5156 else if MBTEST(character == '[' && /* ] */
5157 ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
5158 (token_index == 0 && (parser_state&PST_COMPASSIGN))))
7117c2d2 5159 {
89a92869 5160 ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
7117c2d2
JA
5161 if (ttok == &matched_pair_error)
5162 return -1; /* Bail immediately. */
5163 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
5164 token_buffer_size,
5165 TOKEN_DEFAULT_GROW_SIZE);
5166 token[token_index++] = character;
5167 strcpy (token + token_index, ttok);
5168 token_index += ttoklen;
5169 FREE (ttok);
5170 all_digit_token = 0;
5171 goto next_character;
5172 }
ccc6cda3 5173 /* Identify possible compound array variable assignment. */
95732b49 5174 else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
ccc6cda3
JA
5175 {
5176 peek_char = shell_getc (1);
7117c2d2 5177 if MBTEST(peek_char == '(') /* ) */
ccc6cda3 5178 {
7117c2d2
JA
5179 ttok = parse_compound_assignment (&ttoklen);
5180
5181 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
ccc6cda3
JA
5182 token_buffer_size,
5183 TOKEN_DEFAULT_GROW_SIZE);
7117c2d2
JA
5184
5185 token[token_index++] = '=';
5186 token[token_index++] = '(';
5187 if (ttok)
5188 {
5189 strcpy (token + token_index, ttok);
5190 token_index += ttoklen;
5191 }
5192 token[token_index++] = ')';
ccc6cda3 5193 FREE (ttok);
f73dda09 5194 all_digit_token = 0;
95732b49 5195 compound_assignment = 1;
0628567a 5196#if 1
ccc6cda3 5197 goto next_character;
95732b49
JA
5198#else
5199 goto got_token; /* ksh93 seems to do this */
5200#endif
ccc6cda3
JA
5201 }
5202 else
5203 shell_ungetc (peek_char);
5204 }
5205#endif
726f6388 5206
ccc6cda3
JA
5207 /* When not parsing a multi-character word construct, shell meta-
5208 characters break words. */
7117c2d2 5209 if MBTEST(shellbreak (character))
ccc6cda3
JA
5210 {
5211 shell_ungetc (character);
5212 goto got_token;
5213 }
726f6388 5214
ac50fbac 5215got_character:
ccc6cda3 5216 if (character == CTLESC || character == CTLNUL)
ac50fbac
CR
5217 {
5218 RESIZE_MALLOCED_BUFFER (token, token_index, 2, token_buffer_size,
5219 TOKEN_DEFAULT_GROW_SIZE);
5220 token[token_index++] = CTLESC;
5221 }
5222 else
5223got_escaped_character:
5224 RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
5225 TOKEN_DEFAULT_GROW_SIZE);
726f6388 5226
ac50fbac 5227 token[token_index++] = character;
f1be666c
JA
5228
5229 all_digit_token &= DIGIT (character);
5230 dollar_present |= character == '$';
5231
ccc6cda3 5232 next_character:
b80f6443 5233 if (character == '\n' && SHOULD_PROMPT ())
ccc6cda3 5234 prompt_again ();
726f6388 5235
ccc6cda3
JA
5236 /* We want to remove quoted newlines (that is, a \<newline> pair)
5237 unless we are within single quotes or pass_next_character is
5238 set (the shell equivalent of literal-next). */
5239 cd = current_delimiter (dstack);
5240 character = shell_getc (cd != '\'' && pass_next_character == 0);
5241 } /* end for (;;) */
726f6388 5242
ccc6cda3 5243got_token:
726f6388 5244
ac50fbac 5245 /* Calls to RESIZE_MALLOCED_BUFFER ensure there is sufficient room. */
ccc6cda3 5246 token[token_index] = '\0';
726f6388 5247
ccc6cda3
JA
5248 /* Check to see what thing we should return. If the last_read_token
5249 is a `<', or a `&', or the character which ended this token is
5250 a '>' or '<', then, and ONLY then, is this input token a NUMBER.
5251 Otherwise, it is just a word, and should be returned as such. */
ac50fbac
CR
5252 if MBTEST(all_digit_token && (character == '<' || character == '>' ||
5253 last_read_token == LESS_AND ||
ccc6cda3 5254 last_read_token == GREATER_AND))
726f6388 5255 {
f73dda09 5256 if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
ac50fbac
CR
5257 {
5258 yylval.number = lvalue;
5259 return (NUMBER);
5260 }
726f6388
JA
5261 }
5262
ccc6cda3 5263 /* Check for special case tokens. */
7117c2d2 5264 result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
ccc6cda3
JA
5265 if (result >= 0)
5266 return result;
726f6388
JA
5267
5268#if defined (ALIAS)
ccc6cda3
JA
5269 /* Posix.2 does not allow reserved words to be aliased, so check for all
5270 of them, including special cases, before expanding the current token
5271 as an alias. */
7117c2d2 5272 if MBTEST(posixly_correct)
ccc6cda3
JA
5273 CHECK_FOR_RESERVED_WORD (token);
5274
5275 /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
5276 inhibits alias expansion. */
5277 if (expand_aliases && quoted == 0)
5278 {
5279 result = alias_expand_token (token);
5280 if (result == RE_READ_TOKEN)
5281 return (RE_READ_TOKEN);
5282 else if (result == NO_EXPANSION)
5283 parser_state &= ~PST_ALEXPNEXT;
5284 }
726f6388 5285
ccc6cda3
JA
5286 /* If not in Posix.2 mode, check for reserved words after alias
5287 expansion. */
7117c2d2 5288 if MBTEST(posixly_correct == 0)
ccc6cda3
JA
5289#endif
5290 CHECK_FOR_RESERVED_WORD (token);
5291
a0c0a00f 5292 the_word = alloc_word_desc ();
f73dda09 5293 the_word->word = (char *)xmalloc (1 + token_index);
ccc6cda3
JA
5294 the_word->flags = 0;
5295 strcpy (the_word->word, token);
5296 if (dollar_present)
5297 the_word->flags |= W_HASDOLLAR;
5298 if (quoted)
0628567a
JA
5299 the_word->flags |= W_QUOTED; /*(*/
5300 if (compound_assignment && token[token_index-1] == ')')
95732b49 5301 the_word->flags |= W_COMPASSIGN;
ccc6cda3
JA
5302 /* A word is an assignment if it appears at the beginning of a
5303 simple command, or after another assignment word. This is
5304 context-dependent, so it cannot be handled in the grammar. */
b80f6443 5305 if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
ccc6cda3
JA
5306 {
5307 the_word->flags |= W_ASSIGNMENT;
5308 /* Don't perform word splitting on assignment statements. */
b80f6443 5309 if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
ac50fbac
CR
5310 {
5311 the_word->flags |= W_NOSPLIT;
5312 if (parser_state & PST_COMPASSIGN)
5313 the_word->flags |= W_NOGLOB; /* XXX - W_NOBRACE? */
5314 }
ccc6cda3 5315 }
726f6388 5316
95732b49
JA
5317 if (command_token_position (last_read_token))
5318 {
5319 struct builtin *b;
5320 b = builtin_address_internal (token, 0);
5321 if (b && (b->flags & ASSIGNMENT_BUILTIN))
0628567a
JA
5322 parser_state |= PST_ASSIGNOK;
5323 else if (STREQ (token, "eval") || STREQ (token, "let"))
5324 parser_state |= PST_ASSIGNOK;
95732b49
JA
5325 }
5326
ccc6cda3 5327 yylval.word = the_word;
726f6388 5328
d233b485 5329 /* should we check that quoted == 0 as well? */
0001803f
CR
5330 if (token[0] == '{' && token[token_index-1] == '}' &&
5331 (character == '<' || character == '>'))
5332 {
5333 /* can use token; already copied to the_word */
5334 token[token_index-1] = '\0';
ac50fbac 5335#if defined (ARRAY_VARS)
a0c0a00f 5336 if (legal_identifier (token+1) || valid_array_reference (token+1, 0))
ac50fbac 5337#else
0001803f 5338 if (legal_identifier (token+1))
ac50fbac 5339#endif
0001803f
CR
5340 {
5341 strcpy (the_word->word, token+1);
d233b485
CR
5342/* itrace("read_token_word: returning REDIR_WORD for %s", the_word->word); */
5343 yylval.word = the_word; /* accommodate recursive call */
0001803f
CR
5344 return (REDIR_WORD);
5345 }
d233b485
CR
5346 else
5347 /* valid_array_reference can call the parser recursively; need to
5348 make sure that yylval.word doesn't change if we are going to
5349 return WORD or ASSIGNMENT_WORD */
5350 yylval.word = the_word;
0001803f
CR
5351 }
5352
ccc6cda3
JA
5353 result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
5354 ? ASSIGNMENT_WORD : WORD;
726f6388 5355
b80f6443 5356 switch (last_read_token)
ccc6cda3 5357 {
b80f6443 5358 case FUNCTION:
ccc6cda3
JA
5359 parser_state |= PST_ALLOWOPNBRC;
5360 function_dstart = line_number;
b80f6443
JA
5361 break;
5362 case CASE:
5363 case SELECT:
5364 case FOR:
5365 if (word_top < MAX_CASE_NEST)
5366 word_top++;
5367 word_lineno[word_top] = line_number;
d233b485 5368 expecting_in_token++;
b80f6443 5369 break;
ccc6cda3 5370 }
726f6388 5371
ccc6cda3
JA
5372 return (result);
5373}
726f6388 5374
f73dda09 5375/* Return 1 if TOKSYM is a token that after being read would allow
726f6388
JA
5376 a reserved word to be seen, else 0. */
5377static int
f73dda09
JA
5378reserved_word_acceptable (toksym)
5379 int toksym;
726f6388 5380{
7117c2d2
JA
5381 switch (toksym)
5382 {
5383 case '\n':
5384 case ';':
5385 case '(':
5386 case ')':
5387 case '|':
5388 case '&':
5389 case '{':
5390 case '}': /* XXX */
5391 case AND_AND:
5392 case BANG:
89a92869 5393 case BAR_AND:
7117c2d2
JA
5394 case DO:
5395 case DONE:
5396 case ELIF:
5397 case ELSE:
5398 case ESAC:
5399 case FI:
5400 case IF:
5401 case OR_OR:
5402 case SEMI_SEMI:
3185942a
JA
5403 case SEMI_AND:
5404 case SEMI_SEMI_AND:
7117c2d2
JA
5405 case THEN:
5406 case TIME:
5407 case TIMEOPT:
495aee44 5408 case TIMEIGN:
3185942a 5409 case COPROC:
7117c2d2
JA
5410 case UNTIL:
5411 case WHILE:
5412 case 0:
5413 return 1;
5414 default:
3185942a
JA
5415#if defined (COPROCESS_SUPPORT)
5416 if (last_read_token == WORD && token_before_that == COPROC)
5417 return 1;
5418#endif
495aee44
CR
5419 if (last_read_token == WORD && token_before_that == FUNCTION)
5420 return 1;
7117c2d2
JA
5421 return 0;
5422 }
726f6388 5423}
7117c2d2 5424
726f6388
JA
5425/* Return the index of TOKEN in the alist of reserved words, or -1 if
5426 TOKEN is not a shell reserved word. */
5427int
f73dda09
JA
5428find_reserved_word (tokstr)
5429 char *tokstr;
726f6388
JA
5430{
5431 int i;
ccc6cda3 5432 for (i = 0; word_token_alist[i].word; i++)
f73dda09 5433 if (STREQ (tokstr, word_token_alist[i].word))
726f6388
JA
5434 return i;
5435 return -1;
5436}
5437
ac50fbac
CR
5438/* An interface to let the rest of the shell (primarily the completion
5439 system) know what the parser is expecting. */
5440int
5441parser_in_command_position ()
5442{
5443 return (command_token_position (last_read_token));
5444}
5445
ccc6cda3 5446#if 0
726f6388
JA
5447#if defined (READLINE)
5448/* Called after each time readline is called. This insures that whatever
5449 the new prompt string is gets propagated to readline's local prompt
5450 variable. */
5451static void
5452reset_readline_prompt ()
5453{
ccc6cda3
JA
5454 char *temp_prompt;
5455
726f6388
JA
5456 if (prompt_string_pointer)
5457 {
ccc6cda3 5458 temp_prompt = (*prompt_string_pointer)
726f6388
JA
5459 ? decode_prompt_string (*prompt_string_pointer)
5460 : (char *)NULL;
5461
5462 if (temp_prompt == 0)
5463 {
f73dda09 5464 temp_prompt = (char *)xmalloc (1);
726f6388
JA
5465 temp_prompt[0] = '\0';
5466 }
5467
5468 FREE (current_readline_prompt);
726f6388
JA
5469 current_readline_prompt = temp_prompt;
5470 }
5471}
5472#endif /* READLINE */
ccc6cda3 5473#endif /* 0 */
726f6388
JA
5474
5475#if defined (HISTORY)
5476/* A list of tokens which can be followed by newlines, but not by
5477 semi-colons. When concatenating multiple lines of history, the
5478 newline separator for such tokens is replaced with a space. */
3185942a 5479static const int no_semi_successors[] = {
726f6388 5480 '\n', '{', '(', ')', ';', '&', '|',
3185942a
JA
5481 CASE, DO, ELSE, IF, SEMI_SEMI, SEMI_AND, SEMI_SEMI_AND, THEN, UNTIL,
5482 WHILE, AND_AND, OR_OR, IN,
726f6388
JA
5483 0
5484};
5485
5486/* If we are not within a delimited expression, try to be smart
5487 about which separators can be semi-colons and which must be
ccc6cda3 5488 newlines. Returns the string that should be added into the
495aee44
CR
5489 history entry. LINE is the line we're about to add; it helps
5490 make some more intelligent decisions in certain cases. */
726f6388 5491char *
495aee44
CR
5492history_delimiting_chars (line)
5493 const char *line;
726f6388 5494{
495aee44 5495 static int last_was_heredoc = 0; /* was the last entry the start of a here document? */
ccc6cda3
JA
5496 register int i;
5497
495aee44
CR
5498 if ((parser_state & PST_HEREDOC) == 0)
5499 last_was_heredoc = 0;
5500
ccc6cda3
JA
5501 if (dstack.delimiter_depth != 0)
5502 return ("\n");
3185942a
JA
5503
5504 /* We look for current_command_line_count == 2 because we are looking to
5505 add the first line of the body of the here document (the second line
495aee44
CR
5506 of the command). We also keep LAST_WAS_HEREDOC as a private sentinel
5507 variable to note when we think we added the first line of a here doc
5508 (the one with a "<<" somewhere in it) */
3185942a 5509 if (parser_state & PST_HEREDOC)
495aee44
CR
5510 {
5511 if (last_was_heredoc)
5512 {
5513 last_was_heredoc = 0;
5514 return "\n";
5515 }
a0c0a00f 5516 return (here_doc_first_line ? "\n" : "");
495aee44 5517 }
3185942a 5518
801b47cb
CR
5519 if (parser_state & PST_COMPASSIGN)
5520 return (" ");
5521
ccc6cda3
JA
5522 /* First, handle some special cases. */
5523 /*(*/
5524 /* If we just read `()', assume it's a function definition, and don't
5525 add a semicolon. If the token before the `)' was not `(', and we're
5526 not in the midst of parsing a case statement, assume it's a
5527 parenthesized command and add the semicolon. */
5528 /*)(*/
5529 if (token_before_that == ')')
726f6388 5530 {
ccc6cda3
JA
5531 if (two_tokens_ago == '(') /*)*/ /* function def */
5532 return " ";
5533 /* This does not work for subshells inside case statement
5534 command lists. It's a suboptimal solution. */
5535 else if (parser_state & PST_CASESTMT) /* case statement pattern */
28ef6c31 5536 return " ";
a0c0a00f 5537 else
28ef6c31 5538 return "; "; /* (...) subshell */
ccc6cda3 5539 }
cce855bc
JA
5540 else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
5541 return " "; /* function def using `function name' without `()' */
726f6388 5542
495aee44
CR
5543 /* If we're not in a here document, but we think we're about to parse one,
5544 and we would otherwise return a `;', return a newline to delimit the
5545 line with the here-doc delimiter */
5546 else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
5547 {
5548 last_was_heredoc = 1;
5549 return "\n";
5550 }
a0c0a00f
CR
5551 else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && need_here_doc > 0)
5552 return "\n";
bb70624e
JA
5553 else if (token_before_that == WORD && two_tokens_ago == FOR)
5554 {
5555 /* Tricky. `for i\nin ...' should not have a semicolon, but
5556 `for i\ndo ...' should. We do what we can. */
3185942a 5557 for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
28ef6c31 5558 ;
bb70624e
JA
5559 if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
5560 return " ";
5561 return ";";
5562 }
95732b49
JA
5563 else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
5564 return " ";
bb70624e 5565
ccc6cda3
JA
5566 for (i = 0; no_semi_successors[i]; i++)
5567 {
5568 if (token_before_that == no_semi_successors[i])
5569 return (" ");
726f6388 5570 }
ccc6cda3 5571
d233b485
CR
5572 if (line_isblank (line))
5573 return ("");
5574
ccc6cda3 5575 return ("; ");
726f6388
JA
5576}
5577#endif /* HISTORY */
5578
5579/* Issue a prompt, or prepare to issue a prompt when the next character
5580 is read. */
5581static void
5582prompt_again ()
5583{
5584 char *temp_prompt;
5585
0001803f 5586 if (interactive == 0 || expanding_alias ()) /* XXX */
726f6388
JA
5587 return;
5588
5589 ps1_prompt = get_string_value ("PS1");
5590 ps2_prompt = get_string_value ("PS2");
5591
a0c0a00f
CR
5592 ps0_prompt = get_string_value ("PS0");
5593
726f6388
JA
5594 if (!prompt_string_pointer)
5595 prompt_string_pointer = &ps1_prompt;
5596
ccc6cda3 5597 temp_prompt = *prompt_string_pointer
726f6388
JA
5598 ? decode_prompt_string (*prompt_string_pointer)
5599 : (char *)NULL;
5600
5601 if (temp_prompt == 0)
5602 {
f73dda09 5603 temp_prompt = (char *)xmalloc (1);
726f6388
JA
5604 temp_prompt[0] = '\0';
5605 }
5606
5607 current_prompt_string = *prompt_string_pointer;
5608 prompt_string_pointer = &ps2_prompt;
5609
5610#if defined (READLINE)
5611 if (!no_line_editing)
5612 {
5613 FREE (current_readline_prompt);
5614 current_readline_prompt = temp_prompt;
5615 }
5616 else
5617#endif /* READLINE */
5618 {
5619 FREE (current_decoded_prompt);
5620 current_decoded_prompt = temp_prompt;
5621 }
5622}
5623
bb70624e
JA
5624int
5625get_current_prompt_level ()
5626{
5627 return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
5628}
5629
5630void
5631set_current_prompt_level (x)
5632 int x;
5633{
5634 prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
5635 current_prompt_string = *prompt_string_pointer;
5636}
5637
726f6388
JA
5638static void
5639print_prompt ()
5640{
5641 fprintf (stderr, "%s", current_decoded_prompt);
5642 fflush (stderr);
5643}
5644
d233b485
CR
5645#if defined (HISTORY)
5646 /* The history library increments the history offset as soon as it stores
5647 the first line of a potentially multi-line command, so we compensate
5648 here by returning one fewer when appropriate. */
5649static int
5650prompt_history_number (pmt)
5651 char *pmt;
5652{
5653 int ret;
5654
5655 ret = history_number ();
5656 if (ret == 1)
5657 return ret;
5658
5659 if (pmt == ps1_prompt) /* are we expanding $PS1? */
5660 return ret;
5661 else if (pmt == ps2_prompt && command_oriented_history == 0)
5662 return ret; /* not command oriented history */
5663 else if (pmt == ps2_prompt && command_oriented_history && current_command_first_line_saved)
5664 return ret - 1;
5665 else
5666 return ret - 1; /* PS0, PS4, ${var@P}, PS2 other cases */
5667}
5668#endif
5669
726f6388
JA
5670/* Return a string which will be printed as a prompt. The string
5671 may contain special characters which are decoded as follows:
ccc6cda3
JA
5672
5673 \a bell (ascii 07)
ccc6cda3 5674 \d the date in Day Mon Date format
7117c2d2 5675 \e escape (ascii 033)
ccc6cda3
JA
5676 \h the hostname up to the first `.'
5677 \H the hostname
bb70624e
JA
5678 \j the number of active jobs
5679 \l the basename of the shell's tty device name
726f6388 5680 \n CRLF
7117c2d2 5681 \r CR
726f6388 5682 \s the name of the shell
ccc6cda3
JA
5683 \t the time in 24-hour hh:mm:ss format
5684 \T the time in 12-hour hh:mm:ss format
7117c2d2
JA
5685 \@ the time in 12-hour hh:mm am/pm format
5686 \A the time in 24-hour hh:mm format
5687 \D{fmt} the result of passing FMT to strftime(3)
5688 \u your username
ccc6cda3
JA
5689 \v the version of bash (e.g., 2.00)
5690 \V the release of bash, version + patchlevel (e.g., 2.00.0)
726f6388 5691 \w the current working directory
ccc6cda3 5692 \W the last element of $PWD
726f6388 5693 \! the history number of this command
7117c2d2 5694 \# the command number of this command
726f6388 5695 \$ a $ or a # if you are root
ccc6cda3 5696 \nnn character code nnn in octal
726f6388 5697 \\ a backslash
ccc6cda3
JA
5698 \[ begin a sequence of non-printing chars
5699 \] end a sequence of non-printing chars
726f6388 5700*/
d166f048 5701#define PROMPT_GROWTH 48
726f6388
JA
5702char *
5703decode_prompt_string (string)
5704 char *string;
5705{
726f6388 5706 WORD_LIST *list;
d233b485 5707 char *result, *t, *orig_string;
ccc6cda3 5708 struct dstack save_dstack;
0001803f 5709 int last_exit_value, last_comsub_pid;
726f6388 5710#if defined (PROMPT_STRING_DECODE)
a0c0a00f
CR
5711 size_t result_size;
5712 int result_index;
0628567a 5713 int c, n, i;
a0c0a00f 5714 char *temp, *t_host, octal_string[4];
7117c2d2 5715 struct tm *tm;
ccc6cda3 5716 time_t the_time;
7117c2d2
JA
5717 char timebuf[128];
5718 char *timefmt;
726f6388 5719
f73dda09 5720 result = (char *)xmalloc (result_size = PROMPT_GROWTH);
ccc6cda3
JA
5721 result[result_index = 0] = 0;
5722 temp = (char *)NULL;
d233b485 5723 orig_string = string;
726f6388
JA
5724
5725 while (c = *string++)
5726 {
5727 if (posixly_correct && c == '!')
5728 {
5729 if (*string == '!')
5730 {
5731 temp = savestring ("!");
5732 goto add_string;
5733 }
5734 else
5735 {
5736#if !defined (HISTORY)
5737 temp = savestring ("1");
5738#else /* HISTORY */
d233b485 5739 temp = itos (prompt_history_number (orig_string));
726f6388
JA
5740#endif /* HISTORY */
5741 string--; /* add_string increments string again. */
5742 goto add_string;
5743 }
ccc6cda3 5744 }
726f6388
JA
5745 if (c == '\\')
5746 {
5747 c = *string;
5748
5749 switch (c)
5750 {
5751 case '0':
5752 case '1':
5753 case '2':
5754 case '3':
5755 case '4':
5756 case '5':
5757 case '6':
5758 case '7':
ccc6cda3
JA
5759 strncpy (octal_string, string, 3);
5760 octal_string[3] = '\0';
726f6388 5761
ccc6cda3 5762 n = read_octal (octal_string);
f73dda09 5763 temp = (char *)xmalloc (3);
726f6388 5764
ccc6cda3
JA
5765 if (n == CTLESC || n == CTLNUL)
5766 {
ccc6cda3
JA
5767 temp[0] = CTLESC;
5768 temp[1] = n;
5769 temp[2] = '\0';
5770 }
5771 else if (n == -1)
5772 {
5773 temp[0] = '\\';
5774 temp[1] = '\0';
5775 }
5776 else
5777 {
ccc6cda3
JA
5778 temp[0] = n;
5779 temp[1] = '\0';
5780 }
726f6388 5781
28ef6c31
JA
5782 for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
5783 string++;
5784
7117c2d2 5785 c = 0; /* tested at add_string: */
ccc6cda3 5786 goto add_string;
726f6388 5787
726f6388 5788 case 'd':
7117c2d2 5789 case 't':
ccc6cda3
JA
5790 case 'T':
5791 case '@':
f73dda09 5792 case 'A':
726f6388 5793 /* Make the current time/date into a string. */
7117c2d2 5794 (void) time (&the_time);
2bbe8058
CR
5795#if defined (HAVE_TZSET)
5796 sv_tz ("TZ"); /* XXX -- just make sure */
5797#endif
7117c2d2
JA
5798 tm = localtime (&the_time);
5799
5800 if (c == 'd')
5801 n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
5802 else if (c == 't')
5803 n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
5804 else if (c == 'T')
5805 n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
5806 else if (c == '@')
5807 n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
5808 else if (c == 'A')
5809 n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
5810
b80f6443
JA
5811 if (n == 0)
5812 timebuf[0] = '\0';
5813 else
5814 timebuf[sizeof(timebuf) - 1] = '\0';
5815
7117c2d2
JA
5816 temp = savestring (timebuf);
5817 goto add_string;
726f6388 5818
7117c2d2
JA
5819 case 'D': /* strftime format */
5820 if (string[1] != '{') /* } */
5821 goto not_escape;
726f6388 5822
7117c2d2
JA
5823 (void) time (&the_time);
5824 tm = localtime (&the_time);
5825 string += 2; /* skip { */
5826 timefmt = xmalloc (strlen (string) + 3);
5827 for (t = timefmt; *string && *string != '}'; )
5828 *t++ = *string++;
5829 *t = '\0';
5830 c = *string; /* tested at add_string */
5831 if (timefmt[0] == '\0')
ccc6cda3 5832 {
7117c2d2
JA
5833 timefmt[0] = '%';
5834 timefmt[1] = 'X'; /* locale-specific current time */
5835 timefmt[2] = '\0';
ccc6cda3 5836 }
7117c2d2
JA
5837 n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
5838 free (timefmt);
5839
b80f6443
JA
5840 if (n == 0)
5841 timebuf[0] = '\0';
5842 else
5843 timebuf[sizeof(timebuf) - 1] = '\0';
5844
7117c2d2
JA
5845 if (promptvars || posixly_correct)
5846 /* Make sure that expand_prompt_string is called with a
5847 second argument of Q_DOUBLE_QUOTES if we use this
5848 function here. */
5849 temp = sh_backslash_quote_for_double_quotes (timebuf);
5850 else
5851 temp = savestring (timebuf);
ccc6cda3 5852 goto add_string;
7117c2d2 5853
726f6388 5854 case 'n':
f73dda09 5855 temp = (char *)xmalloc (3);
ccc6cda3
JA
5856 temp[0] = no_line_editing ? '\n' : '\r';
5857 temp[1] = no_line_editing ? '\0' : '\n';
5858 temp[2] = '\0';
726f6388
JA
5859 goto add_string;
5860
5861 case 's':
ccc6cda3 5862 temp = base_pathname (shell_name);
a0c0a00f
CR
5863 /* Try to quote anything the user can set in the file system */
5864 if (promptvars || posixly_correct)
5865 temp = sh_backslash_quote_for_double_quotes (temp);
5866 else
5867 temp = savestring (temp);
ccc6cda3
JA
5868 goto add_string;
5869
5870 case 'v':
5871 case 'V':
7117c2d2 5872 temp = (char *)xmalloc (16);
ccc6cda3
JA
5873 if (c == 'v')
5874 strcpy (temp, dist_version);
5875 else
5876 sprintf (temp, "%s.%d", dist_version, patch_level);
5877 goto add_string;
5878
726f6388
JA
5879 case 'w':
5880 case 'W':
5881 {
ccc6cda3 5882 /* Use the value of PWD because it is much more efficient. */
0628567a 5883 char t_string[PATH_MAX];
e8ce775d 5884 int tlen;
726f6388
JA
5885
5886 temp = get_string_value ("PWD");
5887
ccc6cda3
JA
5888 if (temp == 0)
5889 {
5890 if (getcwd (t_string, sizeof(t_string)) == 0)
5891 {
28ef6c31 5892 t_string[0] = '.';
e8ce775d 5893 tlen = 1;
ccc6cda3 5894 }
e8ce775d
JA
5895 else
5896 tlen = strlen (t_string);
ccc6cda3 5897 }
726f6388 5898 else
e8ce775d
JA
5899 {
5900 tlen = sizeof (t_string) - 1;
5901 strncpy (t_string, temp, tlen);
5902 }
5903 t_string[tlen] = '\0';
726f6388 5904
0001803f
CR
5905#if defined (MACOSX)
5906 /* Convert from "fs" format to "input" format */
5907 temp = fnx_fromfs (t_string, strlen (t_string));
5908 if (temp != t_string)
5909 strcpy (t_string, temp);
5910#endif
5911
28ef6c31
JA
5912#define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0)
5913#define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
b80f6443 5914 /* Abbreviate \W as ~ if $PWD == $HOME */
95732b49 5915 if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
726f6388 5916 {
28ef6c31
JA
5917 if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
5918 {
5919 t = strrchr (t_string, '/');
5920 if (t)
495aee44 5921 memmove (t_string, t + 1, strlen (t)); /* strlen(t) to copy NULL */
28ef6c31 5922 }
726f6388 5923 }
28ef6c31
JA
5924#undef ROOT_PATH
5925#undef DOUBLE_SLASH_ROOT
726f6388 5926 else
ac50fbac
CR
5927 {
5928 /* polite_directory_format is guaranteed to return a string
5929 no longer than PATH_MAX - 1 characters. */
5930 temp = polite_directory_format (t_string);
5931 if (temp != t_string)
5932 strcpy (t_string, temp);
5933 }
ccc6cda3 5934
3185942a 5935 temp = trim_pathname (t_string, PATH_MAX - 1);
ccc6cda3
JA
5936 /* If we're going to be expanding the prompt string later,
5937 quote the directory name. */
5938 if (promptvars || posixly_correct)
bb70624e 5939 /* Make sure that expand_prompt_string is called with a
7117c2d2 5940 second argument of Q_DOUBLE_QUOTES if we use this
bb70624e 5941 function here. */
28ef6c31 5942 temp = sh_backslash_quote_for_double_quotes (t_string);
ccc6cda3
JA
5943 else
5944 temp = savestring (t_string);
5945
726f6388
JA
5946 goto add_string;
5947 }
ccc6cda3 5948
726f6388 5949 case 'u':
bb70624e
JA
5950 if (current_user.user_name == 0)
5951 get_current_user_info ();
ccc6cda3
JA
5952 temp = savestring (current_user.user_name);
5953 goto add_string;
726f6388
JA
5954
5955 case 'h':
ccc6cda3 5956 case 'H':
a0c0a00f
CR
5957 t_host = savestring (current_host_name);
5958 if (c == 'h' && (t = (char *)strchr (t_host, '.')))
ccc6cda3 5959 *t = '\0';
a0c0a00f
CR
5960 if (promptvars || posixly_correct)
5961 /* Make sure that expand_prompt_string is called with a
5962 second argument of Q_DOUBLE_QUOTES if we use this
5963 function here. */
5964 temp = sh_backslash_quote_for_double_quotes (t_host);
5965 else
5966 temp = savestring (t_host);
5967 free (t_host);
ccc6cda3 5968 goto add_string;
726f6388
JA
5969
5970 case '#':
d233b485
CR
5971 n = current_command_number;
5972 /* If we have already incremented current_command_number (PS4,
5973 ${var@P}), compensate */
5974 if (orig_string != ps0_prompt && orig_string != ps1_prompt && orig_string != ps2_prompt)
5975 n--;
5976 temp = itos (n);
ccc6cda3 5977 goto add_string;
726f6388
JA
5978
5979 case '!':
726f6388 5980#if !defined (HISTORY)
ccc6cda3 5981 temp = savestring ("1");
726f6388 5982#else /* HISTORY */
d233b485 5983 temp = itos (prompt_history_number (orig_string));
726f6388 5984#endif /* HISTORY */
ccc6cda3 5985 goto add_string;
726f6388
JA
5986
5987 case '$':
f73dda09 5988 t = temp = (char *)xmalloc (3);
b72432fd
JA
5989 if ((promptvars || posixly_correct) && (current_user.euid != 0))
5990 *t++ = '\\';
5991 *t++ = current_user.euid == 0 ? '#' : '$';
5992 *t = '\0';
726f6388
JA
5993 goto add_string;
5994
bb70624e
JA
5995 case 'j':
5996 temp = itos (count_all_jobs ());
5997 goto add_string;
5998
5999 case 'l':
6000#if defined (HAVE_TTYNAME)
6001 temp = (char *)ttyname (fileno (stdin));
6002 t = temp ? base_pathname (temp) : "tty";
6003 temp = savestring (t);
6004#else
6005 temp = savestring ("tty");
6006#endif /* !HAVE_TTYNAME */
6007 goto add_string;
6008
726f6388
JA
6009#if defined (READLINE)
6010 case '[':
6011 case ']':
b80f6443
JA
6012 if (no_line_editing)
6013 {
6014 string++;
6015 break;
6016 }
f73dda09 6017 temp = (char *)xmalloc (3);
0628567a
JA
6018 n = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
6019 i = 0;
6020 if (n == CTLESC || n == CTLNUL)
6021 temp[i++] = CTLESC;
6022 temp[i++] = n;
6023 temp[i] = '\0';
726f6388 6024 goto add_string;
ccc6cda3 6025#endif /* READLINE */
726f6388
JA
6026
6027 case '\\':
ccc6cda3
JA
6028 case 'a':
6029 case 'e':
7117c2d2 6030 case 'r':
f73dda09 6031 temp = (char *)xmalloc (2);
7117c2d2
JA
6032 if (c == 'a')
6033 temp[0] = '\07';
6034 else if (c == 'e')
6035 temp[0] = '\033';
6036 else if (c == 'r')
6037 temp[0] = '\r';
6038 else /* (c == '\\') */
6039 temp[0] = c;
ccc6cda3 6040 temp[1] = '\0';
726f6388
JA
6041 goto add_string;
6042
6043 default:
7117c2d2 6044not_escape:
f73dda09 6045 temp = (char *)xmalloc (3);
ccc6cda3 6046 temp[0] = '\\';
726f6388 6047 temp[1] = c;
ccc6cda3 6048 temp[2] = '\0';
726f6388
JA
6049
6050 add_string:
6051 if (c)
6052 string++;
6053 result =
6054 sub_append_string (temp, result, &result_index, &result_size);
ccc6cda3 6055 temp = (char *)NULL; /* Freed in sub_append_string (). */
726f6388
JA
6056 result[result_index] = '\0';
6057 break;
6058 }
6059 }
6060 else
6061 {
ccc6cda3 6062 RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
a0c0a00f
CR
6063 /* dequote_string should take care of removing this if we are not
6064 performing the rest of the word expansions. */
6065 if (c == CTLESC || c == CTLNUL)
6066 result[result_index++] = CTLESC;
726f6388
JA
6067 result[result_index++] = c;
6068 result[result_index] = '\0';
6069 }
6070 }
6071#else /* !PROMPT_STRING_DECODE */
6072 result = savestring (string);
6073#endif /* !PROMPT_STRING_DECODE */
6074
ccc6cda3
JA
6075 /* Save the delimiter stack and point `dstack' to temp space so any
6076 command substitutions in the prompt string won't result in screwing
6077 up the parser's quoting state. */
6078 save_dstack = dstack;
6079 dstack = temp_dstack;
6080 dstack.delimiter_depth = 0;
6081
726f6388
JA
6082 /* Perform variable and parameter expansion and command substitution on
6083 the prompt string. */
ccc6cda3
JA
6084 if (promptvars || posixly_correct)
6085 {
f73dda09 6086 last_exit_value = last_command_exit_value;
0001803f 6087 last_comsub_pid = last_command_subst_pid;
f1be666c 6088 list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
ccc6cda3
JA
6089 free (result);
6090 result = string_list (list);
6091 dispose_words (list);
f73dda09 6092 last_command_exit_value = last_exit_value;
0001803f 6093 last_command_subst_pid = last_comsub_pid;
ccc6cda3
JA
6094 }
6095 else
6096 {
6097 t = dequote_string (result);
6098 free (result);
6099 result = t;
6100 }
6101
6102 dstack = save_dstack;
726f6388
JA
6103
6104 return (result);
6105}
6106
7117c2d2
JA
6107/************************************************
6108 * *
6109 * ERROR HANDLING *
6110 * *
6111 ************************************************/
6112
726f6388
JA
6113/* Report a syntax error, and restart the parser. Call here for fatal
6114 errors. */
ccc6cda3 6115int
f73dda09
JA
6116yyerror (msg)
6117 const char *msg;
726f6388
JA
6118{
6119 report_syntax_error ((char *)NULL);
6120 reset_parser ();
ccc6cda3 6121 return (0);
726f6388
JA
6122}
6123
7117c2d2 6124static char *
0628567a
JA
6125error_token_from_token (tok)
6126 int tok;
7117c2d2
JA
6127{
6128 char *t;
6129
0628567a 6130 if (t = find_token_in_alist (tok, word_token_alist, 0))
7117c2d2
JA
6131 return t;
6132
0628567a 6133 if (t = find_token_in_alist (tok, other_token_alist, 0))
7117c2d2
JA
6134 return t;
6135
6136 t = (char *)NULL;
6137 /* This stuff is dicy and needs closer inspection */
6138 switch (current_token)
6139 {
6140 case WORD:
6141 case ASSIGNMENT_WORD:
6142 if (yylval.word)
6143 t = savestring (yylval.word->word);
6144 break;
6145 case NUMBER:
6146 t = itos (yylval.number);
6147 break;
6148 case ARITH_CMD:
6149 if (yylval.word_list)
6150 t = string_list (yylval.word_list);
6151 break;
6152 case ARITH_FOR_EXPRS:
6153 if (yylval.word_list)
6154 t = string_list_internal (yylval.word_list, " ; ");
6155 break;
6156 case COND_CMD:
6157 t = (char *)NULL; /* punt */
6158 break;
6159 }
6160
6161 return t;
6162}
6163
6164static char *
6165error_token_from_text ()
6166{
6167 char *msg, *t;
6168 int token_end, i;
6169
6170 t = shell_input_line;
6171 i = shell_input_line_index;
6172 token_end = 0;
6173 msg = (char *)NULL;
6174
6175 if (i && t[i] == '\0')
6176 i--;
6177
6178 while (i && (whitespace (t[i]) || t[i] == '\n'))
6179 i--;
6180
6181 if (i)
6182 token_end = i + 1;
6183
6184 while (i && (member (t[i], " \n\t;|&") == 0))
6185 i--;
6186
6187 while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
6188 i++;
6189
6190 /* Return our idea of the offending token. */
6191 if (token_end || (i == 0 && token_end == 0))
6192 {
6193 if (token_end)
6194 msg = substring (t, i, token_end);
6195 else /* one-character token */
6196 {
6197 msg = (char *)xmalloc (2);
6198 msg[0] = t[i];
6199 msg[1] = '\0';
6200 }
6201 }
6202
6203 return (msg);
6204}
6205
6206static void
6207print_offending_line ()
6208{
6209 char *msg;
6210 int token_end;
6211
6212 msg = savestring (shell_input_line);
6213 token_end = strlen (msg);
6214 while (token_end && msg[token_end - 1] == '\n')
6215 msg[--token_end] = '\0';
6216
6217 parser_error (line_number, "`%s'", msg);
6218 free (msg);
6219}
6220
726f6388
JA
6221/* Report a syntax error with line numbers, etc.
6222 Call here for recoverable errors. If you have a message to print,
6223 then place it in MESSAGE, otherwise pass NULL and this will figure
6224 out an appropriate message for you. */
6225static void
6226report_syntax_error (message)
6227 char *message;
6228{
495aee44 6229 char *msg, *p;
ccc6cda3 6230
726f6388
JA
6231 if (message)
6232 {
ccc6cda3
JA
6233 parser_error (line_number, "%s", message);
6234 if (interactive && EOF_Reached)
6235 EOF_Reached = 0;
0001803f 6236 last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
726f6388
JA
6237 return;
6238 }
6239
ccc6cda3 6240 /* If the line of input we're reading is not null, try to find the
7117c2d2
JA
6241 objectionable token. First, try to figure out what token the
6242 parser's complaining about by looking at current_token. */
6243 if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
726f6388 6244 {
495aee44
CR
6245 if (ansic_shouldquote (msg))
6246 {
6247 p = ansic_quote (msg, 0, NULL);
6248 free (msg);
6249 msg = p;
6250 }
b80f6443 6251 parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
7117c2d2 6252 free (msg);
726f6388 6253
7117c2d2
JA
6254 if (interactive == 0)
6255 print_offending_line ();
726f6388 6256
0001803f 6257 last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
7117c2d2
JA
6258 return;
6259 }
726f6388 6260
7117c2d2
JA
6261 /* If looking at the current token doesn't prove fruitful, try to find the
6262 offending token by analyzing the text of the input line near the current
6263 input line index and report what we find. */
6264 if (shell_input_line && *shell_input_line)
6265 {
6266 msg = error_token_from_text ();
6267 if (msg)
726f6388 6268 {
b80f6443 6269 parser_error (line_number, _("syntax error near `%s'"), msg);
7117c2d2 6270 free (msg);
726f6388
JA
6271 }
6272
ccc6cda3
JA
6273 /* If not interactive, print the line containing the error. */
6274 if (interactive == 0)
7117c2d2 6275 print_offending_line ();
726f6388
JA
6276 }
6277 else
6278 {
b80f6443 6279 msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
ccc6cda3
JA
6280 parser_error (line_number, "%s", msg);
6281 /* When the shell is interactive, this file uses EOF_Reached
6282 only for error reporting. Other mechanisms are used to
6283 decide whether or not to exit. */
6284 if (interactive && EOF_Reached)
6285 EOF_Reached = 0;
726f6388 6286 }
7117c2d2 6287
0001803f 6288 last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
726f6388
JA
6289}
6290
6291/* ??? Needed function. ??? We have to be able to discard the constructs
6292 created during parsing. In the case of error, we want to return
6293 allocated objects to the memory pool. In the case of no error, we want
6294 to throw away the information about where the allocated objects live.
7117c2d2 6295 (dispose_command () will actually free the command.) */
ccc6cda3 6296static void
726f6388
JA
6297discard_parser_constructs (error_p)
6298 int error_p;
6299{
6300}
ccc6cda3 6301
7117c2d2
JA
6302/************************************************
6303 * *
6304 * EOF HANDLING *
6305 * *
6306 ************************************************/
6307
726f6388
JA
6308/* Do that silly `type "bye" to exit' stuff. You know, "ignoreeof". */
6309
6310/* A flag denoting whether or not ignoreeof is set. */
6311int ignoreeof = 0;
6312
6313/* The number of times that we have encountered an EOF character without
6314 another character intervening. When this gets above the limit, the
6315 shell terminates. */
6316int eof_encountered = 0;
6317
6318/* The limit for eof_encountered. */
6319int eof_encountered_limit = 10;
6320
6321/* If we have EOF as the only input unit, this user wants to leave
6322 the shell. If the shell is not interactive, then just leave.
6323 Otherwise, if ignoreeof is set, and we haven't done this the
6324 required number of times in a row, print a message. */
6325static void
6326handle_eof_input_unit ()
6327{
6328 if (interactive)
6329 {
6330 /* shell.c may use this to decide whether or not to write out the
6331 history, among other things. We use it only for error reporting
6332 in this file. */
6333 if (EOF_Reached)
6334 EOF_Reached = 0;
6335
6336 /* If the user wants to "ignore" eof, then let her do so, kind of. */
6337 if (ignoreeof)
6338 {
6339 if (eof_encountered < eof_encountered_limit)
6340 {
b80f6443 6341 fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
726f6388
JA
6342 login_shell ? "logout" : "exit");
6343 eof_encountered++;
7117c2d2
JA
6344 /* Reset the parsing state. */
6345 last_read_token = current_token = '\n';
726f6388
JA
6346 /* Reset the prompt string to be $PS1. */
6347 prompt_string_pointer = (char **)NULL;
6348 prompt_again ();
726f6388 6349 return;
ccc6cda3 6350 }
726f6388
JA
6351 }
6352
6353 /* In this case EOF should exit the shell. Do it now. */
6354 reset_parser ();
6355 exit_builtin ((WORD_LIST *)NULL);
6356 }
6357 else
6358 {
6359 /* We don't write history files, etc., for non-interactive shells. */
6360 EOF_Reached = 1;
6361 }
6362}
bb70624e 6363
7117c2d2
JA
6364/************************************************
6365 * *
6366 * STRING PARSING FUNCTIONS *
6367 * *
6368 ************************************************/
6369
6370/* It's very important that these two functions treat the characters
6371 between ( and ) identically. */
6372
bb70624e
JA
6373static WORD_LIST parse_string_error;
6374
6375/* Take a string and run it through the shell parser, returning the
6376 resultant word list. Used by compound array assignment. */
6377WORD_LIST *
b80f6443 6378parse_string_to_word_list (s, flags, whom)
f73dda09 6379 char *s;
b80f6443 6380 int flags;
f73dda09 6381 const char *whom;
bb70624e
JA
6382{
6383 WORD_LIST *wl;
7117c2d2 6384 int tok, orig_current_token, orig_line_number, orig_input_terminator;
28ef6c31 6385 int orig_line_count;
7117c2d2 6386 int old_echo_input, old_expand_aliases;
bb70624e
JA
6387#if defined (HISTORY)
6388 int old_remember_on_history, old_history_expansion_inhibited;
6389#endif
6390
6391#if defined (HISTORY)
6392 old_remember_on_history = remember_on_history;
6393# if defined (BANG_HISTORY)
6394 old_history_expansion_inhibited = history_expansion_inhibited;
6395# endif
6396 bash_history_disable ();
6397#endif
6398
6399 orig_line_number = line_number;
28ef6c31 6400 orig_line_count = current_command_line_count;
bb70624e 6401 orig_input_terminator = shell_input_line_terminator;
7117c2d2
JA
6402 old_echo_input = echo_input_at_read;
6403 old_expand_aliases = expand_aliases;
bb70624e
JA
6404
6405 push_stream (1);
7117c2d2 6406 last_read_token = WORD; /* WORD to allow reserved words here */
28ef6c31 6407 current_command_line_count = 0;
7117c2d2 6408 echo_input_at_read = expand_aliases = 0;
bb70624e
JA
6409
6410 with_input_from_string (s, whom);
6411 wl = (WORD_LIST *)NULL;
b80f6443
JA
6412
6413 if (flags & 1)
3185942a 6414 parser_state |= PST_COMPASSIGN|PST_REPARSE;
b80f6443 6415
bb70624e
JA
6416 while ((tok = read_token (READ)) != yacc_EOF)
6417 {
6418 if (tok == '\n' && *bash_input.location.string == '\0')
6419 break;
28ef6c31
JA
6420 if (tok == '\n') /* Allow newlines in compound assignments */
6421 continue;
bb70624e
JA
6422 if (tok != WORD && tok != ASSIGNMENT_WORD)
6423 {
6424 line_number = orig_line_number + line_number - 1;
7117c2d2
JA
6425 orig_current_token = current_token;
6426 current_token = tok;
95732b49 6427 yyerror (NULL); /* does the right thing */
7117c2d2 6428 current_token = orig_current_token;
bb70624e
JA
6429 if (wl)
6430 dispose_words (wl);
6431 wl = &parse_string_error;
6432 break;
6433 }
6434 wl = make_word_list (yylval.word, wl);
6435 }
6436
6437 last_read_token = '\n';
6438 pop_stream ();
6439
6440#if defined (HISTORY)
6441 remember_on_history = old_remember_on_history;
6442# if defined (BANG_HISTORY)
6443 history_expansion_inhibited = old_history_expansion_inhibited;
6444# endif /* BANG_HISTORY */
6445#endif /* HISTORY */
6446
7117c2d2
JA
6447 echo_input_at_read = old_echo_input;
6448 expand_aliases = old_expand_aliases;
6449
28ef6c31 6450 current_command_line_count = orig_line_count;
bb70624e
JA
6451 shell_input_line_terminator = orig_input_terminator;
6452
b80f6443 6453 if (flags & 1)
3185942a 6454 parser_state &= ~(PST_COMPASSIGN|PST_REPARSE);
b80f6443 6455
bb70624e
JA
6456 if (wl == &parse_string_error)
6457 {
6458 last_command_exit_value = EXECUTION_FAILURE;
6459 if (interactive_shell == 0 && posixly_correct)
6460 jump_to_top_level (FORCE_EOF);
6461 else
6462 jump_to_top_level (DISCARD);
6463 }
6464
6465 return (REVERSE_LIST (wl, WORD_LIST *));
6466}
7117c2d2
JA
6467
6468static char *
6469parse_compound_assignment (retlenp)
6470 int *retlenp;
6471{
6472 WORD_LIST *wl, *rl;
0628567a 6473 int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
7117c2d2
JA
6474 char *saved_token, *ret;
6475
6476 saved_token = token;
6477 orig_token_size = token_buffer_size;
6478 orig_line_number = line_number;
0628567a 6479 orig_last_token = last_read_token;
7117c2d2
JA
6480
6481 last_read_token = WORD; /* WORD to allow reserved words here */
6482
6483 token = (char *)NULL;
6484 token_buffer_size = 0;
6485
0628567a
JA
6486 assignok = parser_state&PST_ASSIGNOK; /* XXX */
6487
7117c2d2 6488 wl = (WORD_LIST *)NULL; /* ( */
b80f6443
JA
6489 parser_state |= PST_COMPASSIGN;
6490
7117c2d2
JA
6491 while ((tok = read_token (READ)) != ')')
6492 {
6493 if (tok == '\n') /* Allow newlines in compound assignments */
b80f6443
JA
6494 {
6495 if (SHOULD_PROMPT ())
6496 prompt_again ();
6497 continue;
6498 }
7117c2d2
JA
6499 if (tok != WORD && tok != ASSIGNMENT_WORD)
6500 {
6501 current_token = tok; /* for error reporting */
6502 if (tok == yacc_EOF) /* ( */
b80f6443 6503 parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
7117c2d2 6504 else
95732b49 6505 yyerror(NULL); /* does the right thing */
7117c2d2
JA
6506 if (wl)
6507 dispose_words (wl);
6508 wl = &parse_string_error;
6509 break;
6510 }
6511 wl = make_word_list (yylval.word, wl);
6512 }
6513
6514 FREE (token);
6515 token = saved_token;
6516 token_buffer_size = orig_token_size;
6517
b80f6443
JA
6518 parser_state &= ~PST_COMPASSIGN;
6519
7117c2d2
JA
6520 if (wl == &parse_string_error)
6521 {
6522 last_command_exit_value = EXECUTION_FAILURE;
6523 last_read_token = '\n'; /* XXX */
6524 if (interactive_shell == 0 && posixly_correct)
6525 jump_to_top_level (FORCE_EOF);
6526 else
6527 jump_to_top_level (DISCARD);
6528 }
6529
0628567a
JA
6530 last_read_token = orig_last_token; /* XXX - was WORD? */
6531
7117c2d2
JA
6532 if (wl)
6533 {
6534 rl = REVERSE_LIST (wl, WORD_LIST *);
6535 ret = string_list (rl);
6536 dispose_words (rl);
6537 }
6538 else
6539 ret = (char *)NULL;
6540
6541 if (retlenp)
6542 *retlenp = (ret && *ret) ? strlen (ret) : 0;
0628567a
JA
6543
6544 if (assignok)
6545 parser_state |= PST_ASSIGNOK;
6546
7117c2d2
JA
6547 return ret;
6548}
6549
b80f6443
JA
6550/************************************************
6551 * *
6552 * SAVING AND RESTORING PARTIAL PARSE STATE *
6553 * *
6554 ************************************************/
6555
6556sh_parser_state_t *
6557save_parser_state (ps)
6558 sh_parser_state_t *ps;
6559{
b80f6443 6560 if (ps == 0)
95732b49 6561 ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
b80f6443
JA
6562 if (ps == 0)
6563 return ((sh_parser_state_t *)NULL);
6564
6565 ps->parser_state = parser_state;
6566 ps->token_state = save_token_state ();
6567
6568 ps->input_line_terminator = shell_input_line_terminator;
6569 ps->eof_encountered = eof_encountered;
6570
495aee44
CR
6571 ps->prompt_string_pointer = prompt_string_pointer;
6572
b80f6443
JA
6573 ps->current_command_line_count = current_command_line_count;
6574
6575#if defined (HISTORY)
6576 ps->remember_on_history = remember_on_history;
6577# if defined (BANG_HISTORY)
6578 ps->history_expansion_inhibited = history_expansion_inhibited;
6579# endif
6580#endif
6581
6582 ps->last_command_exit_value = last_command_exit_value;
6583#if defined (ARRAY_VARS)
495aee44 6584 ps->pipestatus = save_pipestatus_array ();
b80f6443
JA
6585#endif
6586
6587 ps->last_shell_builtin = last_shell_builtin;
6588 ps->this_shell_builtin = this_shell_builtin;
6589
6590 ps->expand_aliases = expand_aliases;
6591 ps->echo_input_at_read = echo_input_at_read;
daefb2c5 6592 ps->need_here_doc = need_here_doc;
a0c0a00f
CR
6593 ps->here_doc_first_line = here_doc_first_line;
6594
a0c0a00f
CR
6595 if (need_here_doc == 0)
6596 ps->redir_stack[0] = 0;
6597 else
6598 memcpy (ps->redir_stack, redir_stack, sizeof (redir_stack[0]) * HEREDOC_MAX);
b80f6443 6599
b4839c27
CR
6600 ps->token = token;
6601 ps->token_buffer_size = token_buffer_size;
6602 /* Force reallocation on next call to read_token_word */
6603 token = 0;
6604 token_buffer_size = 0;
6605
b80f6443
JA
6606 return (ps);
6607}
6608
6609void
6610restore_parser_state (ps)
6611 sh_parser_state_t *ps;
6612{
a0c0a00f
CR
6613 int i;
6614
b80f6443
JA
6615 if (ps == 0)
6616 return;
6617
6618 parser_state = ps->parser_state;
6619 if (ps->token_state)
6620 {
6621 restore_token_state (ps->token_state);
6622 free (ps->token_state);
6623 }
6624
6625 shell_input_line_terminator = ps->input_line_terminator;
6626 eof_encountered = ps->eof_encountered;
6627
495aee44
CR
6628 prompt_string_pointer = ps->prompt_string_pointer;
6629
b80f6443
JA
6630 current_command_line_count = ps->current_command_line_count;
6631
6632#if defined (HISTORY)
6633 remember_on_history = ps->remember_on_history;
6634# if defined (BANG_HISTORY)
6635 history_expansion_inhibited = ps->history_expansion_inhibited;
6636# endif
6637#endif
6638
6639 last_command_exit_value = ps->last_command_exit_value;
6640#if defined (ARRAY_VARS)
495aee44 6641 restore_pipestatus_array (ps->pipestatus);
b80f6443
JA
6642#endif
6643
6644 last_shell_builtin = ps->last_shell_builtin;
6645 this_shell_builtin = ps->this_shell_builtin;
6646
6647 expand_aliases = ps->expand_aliases;
6648 echo_input_at_read = ps->echo_input_at_read;
daefb2c5 6649 need_here_doc = ps->need_here_doc;
a0c0a00f
CR
6650 here_doc_first_line = ps->here_doc_first_line;
6651
6652#if 0
6653 for (i = 0; i < HEREDOC_MAX; i++)
6654 redir_stack[i] = ps->redir_stack[i];
6655#else
6656 if (need_here_doc == 0)
6657 redir_stack[0] = 0;
6658 else
6659 memcpy (redir_stack, ps->redir_stack, sizeof (redir_stack[0]) * HEREDOC_MAX);
6660#endif
b4839c27
CR
6661
6662 FREE (token);
6663 token = ps->token;
6664 token_buffer_size = ps->token_buffer_size;
6665}
6666
6667sh_input_line_state_t *
6668save_input_line_state (ls)
6669 sh_input_line_state_t *ls;
6670{
6671 if (ls == 0)
6672 ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
6673 if (ls == 0)
6674 return ((sh_input_line_state_t *)NULL);
6675
6676 ls->input_line = shell_input_line;
6677 ls->input_line_size = shell_input_line_size;
6678 ls->input_line_len = shell_input_line_len;
6679 ls->input_line_index = shell_input_line_index;
6680
6681 /* force reallocation */
6682 shell_input_line = 0;
6683 shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
ac50fbac
CR
6684
6685 return ls;
b4839c27
CR
6686}
6687
6688void
6689restore_input_line_state (ls)
6690 sh_input_line_state_t *ls;
6691{
6692 FREE (shell_input_line);
6693 shell_input_line = ls->input_line;
6694 shell_input_line_size = ls->input_line_size;
6695 shell_input_line_len = ls->input_line_len;
6696 shell_input_line_index = ls->input_line_index;
6697
6698 set_line_mbstate ();
b80f6443
JA
6699}
6700
7117c2d2
JA
6701/************************************************
6702 * *
6703 * MULTIBYTE CHARACTER HANDLING *
6704 * *
6705 ************************************************/
6706
6707#if defined (HANDLE_MULTIBYTE)
d233b485
CR
6708
6709/* We don't let the property buffer get larger than this unless the line is */
6710#define MAX_PROPSIZE 32768
6711
7117c2d2
JA
6712static void
6713set_line_mbstate ()
6714{
ac50fbac
CR
6715 int c;
6716 size_t i, previ, len;
7117c2d2
JA
6717 mbstate_t mbs, prevs;
6718 size_t mbclen;
6719
6720 if (shell_input_line == NULL)
6721 return;
6722 len = strlen (shell_input_line); /* XXX - shell_input_line_len ? */
d233b485
CR
6723 if (len == 0)
6724 return;
6725 if (shell_input_line_propsize >= MAX_PROPSIZE && len < MAX_PROPSIZE>>1)
6726 {
6727 free (shell_input_line_property);
6728 shell_input_line_property = 0;
6729 shell_input_line_propsize = 0;
6730 }
6731 if (len+1 > shell_input_line_propsize)
6732 {
6733 shell_input_line_propsize = len + 1;
6734 shell_input_line_property = (char *)xrealloc (shell_input_line_property, shell_input_line_propsize);
6735 }
7117c2d2 6736
d233b485
CR
6737 /* XXX - use whether or not we are in a UTF-8 locale to avoid calls to
6738 mbrlen */
7117c2d2
JA
6739 memset (&prevs, '\0', sizeof (mbstate_t));
6740 for (i = previ = 0; i < len; i++)
6741 {
6742 mbs = prevs;
6743
b80f6443
JA
6744 c = shell_input_line[i];
6745 if (c == EOF)
7117c2d2 6746 {
ac50fbac 6747 size_t j;
7117c2d2
JA
6748 for (j = i; j < len; j++)
6749 shell_input_line_property[j] = 1;
6750 break;
6751 }
6752
d233b485
CR
6753 /* I'd love to take more advantage of UTF-8's properties in a UTF-8
6754 locale, but mbrlen changes the mbstate_t on every call even when
6755 presented with single-byte characters. */
7117c2d2
JA
6756 mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
6757 if (mbclen == 1 || mbclen == (size_t)-1)
6758 {
6759 mbclen = 1;
6760 previ = i + 1;
6761 }
6762 else if (mbclen == (size_t)-2)
6763 mbclen = 0;
6764 else if (mbclen > 1)
6765 {
6766 mbclen = 0;
6767 previ = i + 1;
6768 prevs = mbs;
6769 }
6770 else
6771 {
b80f6443 6772 /* XXX - what to do if mbrlen returns 0? (null wide character) */
ac50fbac 6773 size_t j;
b80f6443
JA
6774 for (j = i; j < len; j++)
6775 shell_input_line_property[j] = 1;
6776 break;
7117c2d2
JA
6777 }
6778
6779 shell_input_line_property[i] = mbclen;
6780 }
6781}
6782#endif /* HANDLE_MULTIBYTE */