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