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