source: vendor/bash/3.1-p17/parse.y

Last change on this file was 3276, checked in by bird, 18 years ago

Backed out bash-3.1-gentoo.patch, bash-3.1-fix-dash-login-shell.patch and bash-3.1-bash-logger.patch (gentoo patches).

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