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