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