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