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