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