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