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