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