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