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