source: trunk/essentials/app-shells/bash/parse.y@ 3243

Last change on this file since 3243 was 3236, checked in by bird, 18 years ago

Applied bash31-001

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