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