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