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