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