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