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