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