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