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