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

Last change on this file since 3275 was 3247, checked in by bird, 18 years ago

Applied bash31-012

  • Property svn:eol-style set to native
File size: 128.6 KB
Line 
1/* Yacc grammar for bash. */
2
3/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file LICENSE. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21%{
22#include "config.h"
23
24#include "bashtypes.h"
25#include "bashansi.h"
26
27#include "filecntl.h"
28
29#if defined (HAVE_UNISTD_H)
30# include <unistd.h>
31#endif
32
33#if defined (HAVE_LOCALE_H)
34# include <locale.h>
35#endif
36
37#include <stdio.h>
38#include "chartypes.h"
39#include <signal.h>
40
41#include "memalloc.h"
42
43#include "bashintl.h"
44
45#define NEED_STRFTIME_DECL /* used in externs.h */
46
47#include "shell.h"
48#include "trap.h"
49#include "flags.h"
50#include "parser.h"
51#include "mailcheck.h"
52#include "test.h"
53#include "builtins.h"
54#include "builtins/common.h"
55#include "builtins/builtext.h"
56
57#include "shmbutil.h"
58
59#if defined (READLINE)
60# include "bashline.h"
61# include <readline/readline.h>
62#endif /* READLINE */
63
64#if defined (HISTORY)
65# include "bashhist.h"
66# include <readline/history.h>
67#endif /* HISTORY */
68
69#if defined (JOB_CONTROL)
70# include "jobs.h"
71#endif /* JOB_CONTROL */
72
73#if defined (ALIAS)
74# include "alias.h"
75#else
76typedef void *alias_t;
77#endif /* ALIAS */
78
79#if defined (PROMPT_STRING_DECODE)
80# ifndef _MINIX
81# include <sys/param.h>
82# endif
83# include <time.h>
84# if defined (TM_IN_SYS_TIME)
85# include <sys/types.h>
86# include <sys/time.h>
87# endif /* TM_IN_SYS_TIME */
88# include "maxpath.h"
89#endif /* PROMPT_STRING_DECODE */
90
91#define RE_READ_TOKEN -99
92#define NO_EXPANSION -100
93
94#ifdef DEBUG
95# define YYDEBUG 1
96#else
97# define YYDEBUG 0
98#endif
99
100#if defined (HANDLE_MULTIBYTE)
101# define last_shell_getc_is_singlebyte \
102 ((shell_input_line_index > 1) \
103 ? shell_input_line_property[shell_input_line_index - 1] \
104 : 1)
105# define MBTEST(x) ((x) && last_shell_getc_is_singlebyte)
106#else
107# define last_shell_getc_is_singlebyte 1
108# define MBTEST(x) ((x))
109#endif
110
111#if defined (EXTENDED_GLOB)
112extern int extended_glob;
113#endif
114
115extern int eof_encountered;
116extern int no_line_editing, running_under_emacs;
117extern int current_command_number;
118extern int sourcelevel;
119extern int posixly_correct;
120extern int last_command_exit_value;
121extern int interrupt_immediately;
122extern char *shell_name, *current_host_name;
123extern char *dist_version;
124extern int patch_level;
125extern int dump_translatable_strings, dump_po_strings;
126extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
127#if defined (BUFFERED_INPUT)
128extern int bash_input_fd_changed;
129#endif
130
131extern int errno;
132/* **************************************************************** */
133/* */
134/* "Forward" declarations */
135/* */
136/* **************************************************************** */
137
138#ifdef DEBUG
139static void debug_parser __P((int));
140#endif
141
142static int yy_getc __P((void));
143static int yy_ungetc __P((int));
144
145#if defined (READLINE)
146static int yy_readline_get __P((void));
147static int yy_readline_unget __P((int));
148#endif
149
150static int yy_string_get __P((void));
151static int yy_string_unget __P((int));
152static int yy_stream_get __P((void));
153static int yy_stream_unget __P((int));
154
155static int shell_getc __P((int));
156static void shell_ungetc __P((int));
157static void discard_until __P((int));
158
159#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
160static void push_string __P((char *, int, alias_t *));
161static void pop_string __P((void));
162static void free_string_list __P((void));
163#endif
164
165static char *read_a_line __P((int));
166
167static int reserved_word_acceptable __P((int));
168static int yylex __P((void));
169static int alias_expand_token __P((char *));
170static int time_command_acceptable __P((void));
171static int special_case_tokens __P((char *));
172static int read_token __P((int));
173static char *parse_matched_pair __P((int, int, int, int *, int));
174#if defined (ARRAY_VARS)
175static char *parse_compound_assignment __P((int *));
176#endif
177#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
178static int parse_dparen __P((int));
179static int parse_arith_cmd __P((char **, int));
180#endif
181#if defined (COND_COMMAND)
182static void cond_error __P((void));
183static COND_COM *cond_expr __P((void));
184static COND_COM *cond_or __P((void));
185static COND_COM *cond_and __P((void));
186static COND_COM *cond_term __P((void));
187static int cond_skip_newlines __P((void));
188static COMMAND *parse_cond_command __P((void));
189#endif
190#if defined (ARRAY_VARS)
191static int token_is_assignment __P((char *, int));
192static int token_is_ident __P((char *, int));
193#endif
194static int read_token_word __P((int));
195static void discard_parser_constructs __P((int));
196
197static char *error_token_from_token __P((int));
198static char *error_token_from_text __P((void));
199static void print_offending_line __P((void));
200static void report_syntax_error __P((char *));
201
202static void handle_eof_input_unit __P((void));
203static void prompt_again __P((void));
204#if 0
205static void reset_readline_prompt __P((void));
206#endif
207static void print_prompt __P((void));
208
209#if defined (HISTORY)
210char *history_delimiting_chars __P((void));
211#endif
212
213#if defined (HANDLE_MULTIBYTE)
214static void set_line_mbstate __P((void));
215static char *shell_input_line_property = NULL;
216#else
217# define set_line_mbstate()
218#endif
219
220extern int yyerror __P((const char *));
221
222#ifdef DEBUG
223extern int yydebug;
224#endif
225
226/* Default prompt strings */
227char *primary_prompt = PPROMPT;
228char *secondary_prompt = SPROMPT;
229
230/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
231char *ps1_prompt, *ps2_prompt;
232
233/* Handle on the current prompt string. Indirectly points through
234 ps1_ or ps2_prompt. */
235char **prompt_string_pointer = (char **)NULL;
236char *current_prompt_string;
237
238/* Non-zero means we expand aliases in commands. */
239int expand_aliases = 0;
240
241/* If non-zero, the decoded prompt string undergoes parameter and
242 variable substitution, command substitution, arithmetic substitution,
243 string expansion, process substitution, and quote removal in
244 decode_prompt_string. */
245int promptvars = 1;
246
247/* If non-zero, $'...' and $"..." are expanded when they appear within
248 a ${...} expansion, even when the expansion appears within double
249 quotes. */
250int extended_quote = 1;
251
252/* The decoded prompt string. Used if READLINE is not defined or if
253 editing is turned off. Analogous to current_readline_prompt. */
254static char *current_decoded_prompt;
255
256/* The number of lines read from input while creating the current command. */
257int current_command_line_count;
258
259/* Variables to manage the task of reading here documents, because we need to
260 defer the reading until after a complete command has been collected. */
261static REDIRECT *redir_stack[10];
262int need_here_doc;
263
264/* Where shell input comes from. History expansion is performed on each
265 line when the shell is interactive. */
266static char *shell_input_line = (char *)NULL;
267static int shell_input_line_index;
268static int shell_input_line_size; /* Amount allocated for shell_input_line. */
269static int shell_input_line_len; /* strlen (shell_input_line) */
270
271/* Either zero or EOF. */
272static int shell_input_line_terminator;
273
274/* The line number in a script on which a function definition starts. */
275static int function_dstart;
276
277/* The line number in a script on which a function body starts. */
278static int function_bstart;
279
280/* The line number in a script at which an arithmetic for command starts. */
281static int arith_for_lineno;
282
283/* The line number in a script where the word in a `case WORD', `select WORD'
284 or `for WORD' begins. This is a nested command maximum, since the array
285 index is decremented after a case, select, or for command is parsed. */
286#define MAX_CASE_NEST 128
287static int word_lineno[MAX_CASE_NEST];
288static int word_top = -1;
289
290/* If non-zero, it is the token that we want read_token to return
291 regardless of what text is (or isn't) present to be read. This
292 is reset by read_token. If token_to_read == WORD or
293 ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */
294static int token_to_read;
295static WORD_DESC *word_desc_to_read;
296
297static REDIRECTEE redir;
298%}
299
300%union {
301 WORD_DESC *word; /* the word that we read. */
302 int number; /* the number that we read. */
303 WORD_LIST *word_list;
304 COMMAND *command;
305 REDIRECT *redirect;
306 ELEMENT element;
307 PATTERN_LIST *pattern;
308}
309
310/* Reserved words. Members of the first group are only recognized
311 in the case that they are preceded by a list_terminator. Members
312 of the second group are for [[...]] commands. Members of the
313 third group are recognized only under special circumstances. */
314%token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
315%token COND_START COND_END COND_ERROR
316%token IN BANG TIME TIMEOPT
317
318/* More general tokens. yylex () knows how to make these. */
319%token <word> WORD ASSIGNMENT_WORD
320%token <number> NUMBER
321%token <word_list> ARITH_CMD ARITH_FOR_EXPRS
322%token <command> COND_CMD
323%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
324%token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
325%token GREATER_BAR
326
327/* The types that the various syntactical units return. */
328
329%type <command> inputunit command pipeline pipeline_command
330%type <command> list list0 list1 compound_list simple_list simple_list1
331%type <command> simple_command shell_command
332%type <command> for_command select_command case_command group_command
333%type <command> arith_command
334%type <command> cond_command
335%type <command> arith_for_command
336%type <command> function_def function_body if_command elif_clause subshell
337%type <redirect> redirection redirection_list
338%type <element> simple_command_element
339%type <word_list> word_list pattern
340%type <pattern> pattern_list case_clause_sequence case_clause
341%type <number> timespec
342%type <number> list_terminator
343
344%start inputunit
345
346%left '&' ';' '\n' yacc_EOF
347%left AND_AND OR_OR
348%right '|'
349%%
350
351inputunit: simple_list simple_list_terminator
352 {
353 /* Case of regular command. Discard the error
354 safety net,and return the command just parsed. */
355 global_command = $1;
356 eof_encountered = 0;
357 /* discard_parser_constructs (0); */
358 YYACCEPT;
359 }
360 | '\n'
361 {
362 /* Case of regular command, but not a very
363 interesting one. Return a NULL command. */
364 global_command = (COMMAND *)NULL;
365 YYACCEPT;
366 }
367 | error '\n'
368 {
369 /* Error during parsing. Return NULL command. */
370 global_command = (COMMAND *)NULL;
371 eof_encountered = 0;
372 /* discard_parser_constructs (1); */
373 if (interactive)
374 {
375 YYACCEPT;
376 }
377 else
378 {
379 YYABORT;
380 }
381 }
382 | yacc_EOF
383 {
384 /* Case of EOF seen by itself. Do ignoreeof or
385 not. */
386 global_command = (COMMAND *)NULL;
387 handle_eof_input_unit ();
388 YYACCEPT;
389 }
390 ;
391
392word_list:
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#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
2722
2723static char matched_pair_error;
2724static char *
2725parse_matched_pair (qc, open, close, lenp, flags)
2726 int qc; /* `"' if this construct is within double quotes */
2727 int open, close;
2728 int *lenp, flags;
2729{
2730 int count, ch, was_dollar, in_comment, check_comment;
2731 int pass_next_character, backq_backslash, nestlen, ttranslen, start_lineno;
2732 char *ret, *nestret, *ttrans;
2733 int retind, retsize, rflags;
2734
2735 count = 1;
2736 pass_next_character = backq_backslash = was_dollar = in_comment = 0;
2737 check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
2738
2739 /* RFLAGS is the set of flags we want to pass to recursive calls. */
2740 rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
2741
2742 ret = (char *)xmalloc (retsize = 64);
2743 retind = 0;
2744
2745 start_lineno = line_number;
2746 while (count)
2747 {
2748 ch = shell_getc (qc != '\'' && pass_next_character == 0 && backq_backslash == 0);
2749
2750 if (ch == EOF)
2751 {
2752 free (ret);
2753 parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
2754 EOF_Reached = 1; /* XXX */
2755 return (&matched_pair_error);
2756 }
2757
2758 /* Possible reprompting. */
2759 if (ch == '\n' && SHOULD_PROMPT ())
2760 prompt_again ();
2761
2762 if (in_comment)
2763 {
2764 /* Add this character. */
2765 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
2766 ret[retind++] = ch;
2767
2768 if (ch == '\n')
2769 in_comment = 0;
2770
2771 continue;
2772 }
2773 /* Not exactly right yet */
2774 else if MBTEST(check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
2775 in_comment = 1;
2776
2777 /* last char was backslash inside backquoted command substitution */
2778 if (backq_backslash)
2779 {
2780 backq_backslash = 0;
2781 /* Placeholder for adding special characters */
2782 }
2783
2784 if (pass_next_character) /* last char was backslash */
2785 {
2786 pass_next_character = 0;
2787 if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
2788 {
2789 if (retind > 0) retind--; /* swallow previously-added backslash */
2790 continue;
2791 }
2792
2793 RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
2794 if MBTEST(ch == CTLESC || ch == CTLNUL)
2795 ret[retind++] = CTLESC;
2796 ret[retind++] = ch;
2797 continue;
2798 }
2799 else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
2800 {
2801 RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
2802 ret[retind++] = CTLESC;
2803 ret[retind++] = ch;
2804 continue;
2805 }
2806 else if MBTEST(ch == close) /* ending delimiter */
2807 count--;
2808#if 1
2809 /* handle nested ${...} specially. */
2810 else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
2811 count++;
2812#endif
2813 else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
2814 count++;
2815
2816 /* Add this character. */
2817 RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
2818 ret[retind++] = ch;
2819
2820 if (open == '\'') /* '' inside grouping construct */
2821 {
2822 if MBTEST((flags & P_ALLOWESC) && ch == '\\')
2823 pass_next_character++;
2824 else if MBTEST((flags & P_BACKQUOTE) && ch == '\\')
2825 backq_backslash++;
2826 continue;
2827 }
2828
2829 if MBTEST(ch == '\\') /* backslashes */
2830 pass_next_character++;
2831
2832 if (open != close) /* a grouping construct */
2833 {
2834 if MBTEST(shellquote (ch))
2835 {
2836 /* '', ``, or "" inside $(...) or other grouping construct. */
2837 push_delimiter (dstack, ch);
2838 if MBTEST(was_dollar && ch == '\'') /* $'...' inside group */
2839 nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
2840 else
2841 nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
2842 pop_delimiter (dstack);
2843 if (nestret == &matched_pair_error)
2844 {
2845 free (ret);
2846 return &matched_pair_error;
2847 }
2848 if MBTEST(was_dollar && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
2849 {
2850 /* Translate $'...' here. */
2851 ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
2852 xfree (nestret);
2853
2854 if ((rflags & P_DQUOTE) == 0)
2855 {
2856 nestret = sh_single_quote (ttrans);
2857 free (ttrans);
2858 nestlen = strlen (nestret);
2859 }
2860 else
2861 {
2862 nestret = ttrans;
2863 nestlen = ttranslen;
2864 }
2865 retind -= 2; /* back up before the $' */
2866 }
2867 else if MBTEST(was_dollar && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
2868 {
2869 /* Locale expand $"..." here. */
2870 ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
2871 xfree (nestret);
2872
2873 nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
2874 free (ttrans);
2875 nestlen = ttranslen + 2;
2876 retind -= 2; /* back up before the $" */
2877 }
2878
2879 if (nestlen)
2880 {
2881 RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
2882 strcpy (ret + retind, nestret);
2883 retind += nestlen;
2884 }
2885 FREE (nestret);
2886 }
2887 }
2888 /* Parse an old-style command substitution within double quotes as a
2889 single word. */
2890 /* XXX - sh and ksh93 don't do this - XXX */
2891 else if MBTEST(open == '"' && ch == '`')
2892 {
2893 nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags);
2894add_nestret:
2895 if (nestret == &matched_pair_error)
2896 {
2897 free (ret);
2898 return &matched_pair_error;
2899 }
2900 if (nestlen)
2901 {
2902 RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
2903 strcpy (ret + retind, nestret);
2904 retind += nestlen;
2905 }
2906 FREE (nestret);
2907 }
2908 else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
2909 {
2910 /* Add P_BACKQUOTE so backslash quotes the next character and
2911 shell_getc does the right thing with \<newline>. We do this for
2912 a measure of backwards compatibility -- it's not strictly the
2913 right POSIX thing. */
2914 nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_BACKQUOTE);
2915 goto add_nestret;
2916 }
2917 else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
2918 /* check for $(), $[], or ${} inside quoted string. */
2919 {
2920 if (open == ch) /* undo previous increment */
2921 count--;
2922 if (ch == '(') /* ) */
2923 nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
2924 else if (ch == '{') /* } */
2925 nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
2926 else if (ch == '[') /* ] */
2927 nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
2928
2929 goto add_nestret;
2930 }
2931 was_dollar = MBTEST(ch == '$');
2932 }
2933
2934 ret[retind] = '\0';
2935 if (lenp)
2936 *lenp = retind;
2937 return ret;
2938}
2939
2940#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
2941/* Parse a double-paren construct. It can be either an arithmetic
2942 command, an arithmetic `for' command, or a nested subshell. Returns
2943 the parsed token, -1 on error, or -2 if we didn't do anything and
2944 should just go on. */
2945static int
2946parse_dparen (c)
2947 int c;
2948{
2949 int cmdtyp, len, sline;
2950 char *wval, *wv2;
2951 WORD_DESC *wd;
2952
2953#if defined (ARITH_FOR_COMMAND)
2954 if (last_read_token == FOR)
2955 {
2956 arith_for_lineno = line_number;
2957 cmdtyp = parse_arith_cmd (&wval, 0);
2958 if (cmdtyp == 1)
2959 {
2960 wd = alloc_word_desc ();
2961 wd->word = wval;
2962 wd = make_word (wval);
2963 yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
2964 return (ARITH_FOR_EXPRS);
2965 }
2966 else
2967 return -1; /* ERROR */
2968 }
2969#endif
2970
2971#if defined (DPAREN_ARITHMETIC)
2972 if (reserved_word_acceptable (last_read_token))
2973 {
2974 sline = line_number;
2975
2976 cmdtyp = parse_arith_cmd (&wval, 0);
2977 if (cmdtyp == 1) /* arithmetic command */
2978 {
2979 wd = alloc_word_desc ();
2980 wd->word = wval;
2981 wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
2982 yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
2983 return (ARITH_CMD);
2984 }
2985 else if (cmdtyp == 0) /* nested subshell */
2986 {
2987 push_string (wval, 0, (alias_t *)NULL);
2988 if ((parser_state & PST_CASEPAT) == 0)
2989 parser_state |= PST_SUBSHELL;
2990 return (c);
2991 }
2992 else /* ERROR */
2993 return -1;
2994 }
2995#endif
2996
2997 return -2; /* XXX */
2998}
2999
3000/* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
3001 If not, assume it's a nested subshell for backwards compatibility and
3002 return 0. In any case, put the characters we've consumed into a locally-
3003 allocated buffer and make *ep point to that buffer. Return -1 on an
3004 error, for example EOF. */
3005static int
3006parse_arith_cmd (ep, adddq)
3007 char **ep;
3008 int adddq;
3009{
3010 int exp_lineno, rval, c;
3011 char *ttok, *tokstr;
3012 int ttoklen;
3013
3014 exp_lineno = line_number;
3015 ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
3016 rval = 1;
3017 if (ttok == &matched_pair_error)
3018 return -1;
3019 /* Check that the next character is the closing right paren. If
3020 not, this is a syntax error. ( */
3021 c = shell_getc (0);
3022 if MBTEST(c != ')')
3023 rval = 0;
3024
3025 tokstr = (char *)xmalloc (ttoklen + 4);
3026
3027 /* if ADDDQ != 0 then (( ... )) -> "..." */
3028 if (rval == 1 && adddq) /* arith cmd, add double quotes */
3029 {
3030 tokstr[0] = '"';
3031 strncpy (tokstr + 1, ttok, ttoklen - 1);
3032 tokstr[ttoklen] = '"';
3033 tokstr[ttoklen+1] = '\0';
3034 }
3035 else if (rval == 1) /* arith cmd, don't add double quotes */
3036 {
3037 strncpy (tokstr, ttok, ttoklen - 1);
3038 tokstr[ttoklen-1] = '\0';
3039 }
3040 else /* nested subshell */
3041 {
3042 tokstr[0] = '(';
3043 strncpy (tokstr + 1, ttok, ttoklen - 1);
3044 tokstr[ttoklen] = ')';
3045 tokstr[ttoklen+1] = c;
3046 tokstr[ttoklen+2] = '\0';
3047 }
3048
3049 *ep = tokstr;
3050 FREE (ttok);
3051 return rval;
3052}
3053#endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
3054
3055#if defined (COND_COMMAND)
3056static void
3057cond_error ()
3058{
3059 char *etext;
3060
3061 if (EOF_Reached && cond_token != COND_ERROR) /* [[ */
3062 parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
3063 else if (cond_token != COND_ERROR)
3064 {
3065 if (etext = error_token_from_token (cond_token))
3066 {
3067 parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
3068 free (etext);
3069 }
3070 else
3071 parser_error (cond_lineno, _("syntax error in conditional expression"));
3072 }
3073}
3074
3075static COND_COM *
3076cond_expr ()
3077{
3078 return (cond_or ());
3079}
3080
3081static COND_COM *
3082cond_or ()
3083{
3084 COND_COM *l, *r;
3085
3086 l = cond_and ();
3087 if (cond_token == OR_OR)
3088 {
3089 r = cond_or ();
3090 l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
3091 }
3092 return l;
3093}
3094
3095static COND_COM *
3096cond_and ()
3097{
3098 COND_COM *l, *r;
3099
3100 l = cond_term ();
3101 if (cond_token == AND_AND)
3102 {
3103 r = cond_and ();
3104 l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
3105 }
3106 return l;
3107}
3108
3109static int
3110cond_skip_newlines ()
3111{
3112 while ((cond_token = read_token (READ)) == '\n')
3113 {
3114 if (SHOULD_PROMPT ())
3115 prompt_again ();
3116 }
3117 return (cond_token);
3118}
3119
3120#define COND_RETURN_ERROR() \
3121 do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
3122
3123static COND_COM *
3124cond_term ()
3125{
3126 WORD_DESC *op;
3127 COND_COM *term, *tleft, *tright;
3128 int tok, lineno;
3129 char *etext;
3130
3131 /* Read a token. It can be a left paren, a `!', a unary operator, or a
3132 word that should be the first argument of a binary operator. Start by
3133 skipping newlines, since this is a compound command. */
3134 tok = cond_skip_newlines ();
3135 lineno = line_number;
3136 if (tok == COND_END)
3137 {
3138 COND_RETURN_ERROR ();
3139 }
3140 else if (tok == '(')
3141 {
3142 term = cond_expr ();
3143 if (cond_token != ')')
3144 {
3145 if (term)
3146 dispose_cond_node (term); /* ( */
3147 if (etext = error_token_from_token (cond_token))
3148 {
3149 parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
3150 free (etext);
3151 }
3152 else
3153 parser_error (lineno, _("expected `)'"));
3154 COND_RETURN_ERROR ();
3155 }
3156 term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
3157 (void)cond_skip_newlines ();
3158 }
3159 else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
3160 {
3161 if (tok == WORD)
3162 dispose_word (yylval.word); /* not needed */
3163 term = cond_term ();
3164 if (term)
3165 term->flags |= CMD_INVERT_RETURN;
3166 }
3167 else if (tok == WORD && test_unop (yylval.word->word))
3168 {
3169 op = yylval.word;
3170 tok = read_token (READ);
3171 if (tok == WORD)
3172 {
3173 tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
3174 term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
3175 }
3176 else
3177 {
3178 dispose_word (op);
3179 if (etext = error_token_from_token (tok))
3180 {
3181 parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
3182 free (etext);
3183 }
3184 else
3185 parser_error (line_number, _("unexpected argument to conditional unary operator"));
3186 COND_RETURN_ERROR ();
3187 }
3188
3189 (void)cond_skip_newlines ();
3190 }
3191 else if (tok == WORD) /* left argument to binary operator */
3192 {
3193 /* lhs */
3194 tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
3195
3196 /* binop */
3197 tok = read_token (READ);
3198 if (tok == WORD && test_binop (yylval.word->word))
3199 op = yylval.word;
3200#if defined (COND_REGEXP)
3201 else if (tok == WORD && STREQ (yylval.word->word,"=~"))
3202 op = yylval.word;
3203#endif
3204 else if (tok == '<' || tok == '>')
3205 op = make_word_from_token (tok); /* ( */
3206 /* There should be a check before blindly accepting the `)' that we have
3207 seen the opening `('. */
3208 else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
3209 {
3210 /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
3211 the test command. Similarly for [[ x && expr ]] or
3212 [[ x || expr ]] or [[ (x) ]]. */
3213 op = make_word ("-n");
3214 term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
3215 cond_token = tok;
3216 return (term);
3217 }
3218 else
3219 {
3220 if (etext = error_token_from_token (tok))
3221 {
3222 parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
3223 free (etext);
3224 }
3225 else
3226 parser_error (line_number, _("conditional binary operator expected"));
3227 dispose_cond_node (tleft);
3228 COND_RETURN_ERROR ();
3229 }
3230
3231 /* rhs */
3232 tok = read_token (READ);
3233 if (tok == WORD)
3234 {
3235 tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
3236 term = make_cond_node (COND_BINARY, op, tleft, tright);
3237 }
3238 else
3239 {
3240 if (etext = error_token_from_token (tok))
3241 {
3242 parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
3243 free (etext);
3244 }
3245 else
3246 parser_error (line_number, _("unexpected argument to conditional binary operator"));
3247 dispose_cond_node (tleft);
3248 dispose_word (op);
3249 COND_RETURN_ERROR ();
3250 }
3251
3252 (void)cond_skip_newlines ();
3253 }
3254 else
3255 {
3256 if (tok < 256)
3257 parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
3258 else if (etext = error_token_from_token (tok))
3259 {
3260 parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
3261 free (etext);
3262 }
3263 else
3264 parser_error (line_number, _("unexpected token %d in conditional command"), tok);
3265 COND_RETURN_ERROR ();
3266 }
3267 return (term);
3268}
3269
3270/* This is kind of bogus -- we slip a mini recursive-descent parser in
3271 here to handle the conditional statement syntax. */
3272static COMMAND *
3273parse_cond_command ()
3274{
3275 COND_COM *cexp;
3276
3277 cexp = cond_expr ();
3278 return (make_cond_command (cexp));
3279}
3280#endif
3281
3282#if defined (ARRAY_VARS)
3283/* When this is called, it's guaranteed that we don't care about anything
3284 in t beyond i. We do save and restore the chars, though. */
3285static int
3286token_is_assignment (t, i)
3287 char *t;
3288 int i;
3289{
3290 unsigned char c, c1;
3291 int r;
3292
3293 c = t[i]; c1 = t[i+1];
3294 t[i] = '='; t[i+1] = '\0';
3295 r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
3296 t[i] = c; t[i+1] = c1;
3297 return r;
3298}
3299
3300/* XXX - possible changes here for `+=' */
3301static int
3302token_is_ident (t, i)
3303 char *t;
3304 int i;
3305{
3306 unsigned char c;
3307 int r;
3308
3309 c = t[i];
3310 t[i] = '\0';
3311 r = legal_identifier (t);
3312 t[i] = c;
3313 return r;
3314}
3315#endif
3316
3317static int
3318read_token_word (character)
3319 int character;
3320{
3321 /* The value for YYLVAL when a WORD is read. */
3322 WORD_DESC *the_word;
3323
3324 /* Index into the token that we are building. */
3325 int token_index;
3326
3327 /* ALL_DIGITS becomes zero when we see a non-digit. */
3328 int all_digit_token;
3329
3330 /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
3331 int dollar_present;
3332
3333 /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
3334 assignment. */
3335 int compound_assignment;
3336
3337 /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
3338 int quoted;
3339
3340 /* Non-zero means to ignore the value of the next character, and just
3341 to add it no matter what. */
3342 int pass_next_character;
3343
3344 /* The current delimiting character. */
3345 int cd;
3346 int result, peek_char;
3347 char *ttok, *ttrans;
3348 int ttoklen, ttranslen;
3349 intmax_t lvalue;
3350
3351 if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
3352 token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
3353
3354 token_index = 0;
3355 all_digit_token = DIGIT (character);
3356 dollar_present = quoted = pass_next_character = compound_assignment = 0;
3357
3358 for (;;)
3359 {
3360 if (character == EOF)
3361 goto got_token;
3362
3363 if (pass_next_character)
3364 {
3365 pass_next_character = 0;
3366 goto got_character;
3367 }
3368
3369 cd = current_delimiter (dstack);
3370
3371 /* Handle backslashes. Quote lots of things when not inside of
3372 double-quotes, quote some things inside of double-quotes. */
3373 if MBTEST(character == '\\')
3374 {
3375 peek_char = shell_getc (0);
3376
3377 /* Backslash-newline is ignored in all cases except
3378 when quoted with single quotes. */
3379 if (peek_char == '\n')
3380 {
3381 character = '\n';
3382 goto next_character;
3383 }
3384 else
3385 {
3386 shell_ungetc (peek_char);
3387
3388 /* If the next character is to be quoted, note it now. */
3389 if (cd == 0 || cd == '`' ||
3390 (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
3391 pass_next_character++;
3392
3393 quoted = 1;
3394 goto got_character;
3395 }
3396 }
3397
3398 /* Parse a matched pair of quote characters. */
3399 if MBTEST(shellquote (character))
3400 {
3401 push_delimiter (dstack, character);
3402 ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
3403 pop_delimiter (dstack);
3404 if (ttok == &matched_pair_error)
3405 return -1; /* Bail immediately. */
3406 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
3407 token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
3408 token[token_index++] = character;
3409 strcpy (token + token_index, ttok);
3410 token_index += ttoklen;
3411 all_digit_token = 0;
3412 quoted = 1;
3413 dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
3414 FREE (ttok);
3415 goto next_character;
3416 }
3417
3418#ifdef EXTENDED_GLOB
3419 /* Parse a ksh-style extended pattern matching specification. */
3420 if (extended_glob && PATTERN_CHAR (character))
3421 {
3422 peek_char = shell_getc (1);
3423 if MBTEST(peek_char == '(') /* ) */
3424 {
3425 push_delimiter (dstack, peek_char);
3426 ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
3427 pop_delimiter (dstack);
3428 if (ttok == &matched_pair_error)
3429 return -1; /* Bail immediately. */
3430 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
3431 token_buffer_size,
3432 TOKEN_DEFAULT_GROW_SIZE);
3433 token[token_index++] = character;
3434 token[token_index++] = peek_char;
3435 strcpy (token + token_index, ttok);
3436 token_index += ttoklen;
3437 FREE (ttok);
3438 dollar_present = all_digit_token = 0;
3439 goto next_character;
3440 }
3441 else
3442 shell_ungetc (peek_char);
3443 }
3444#endif /* EXTENDED_GLOB */
3445
3446 /* If the delimiter character is not single quote, parse some of
3447 the shell expansions that must be read as a single word. */
3448 if (shellexp (character))
3449 {
3450 peek_char = shell_getc (1);
3451 /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
3452 if MBTEST(peek_char == '(' || \
3453 ((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
3454 {
3455 if (peek_char == '{') /* } */
3456 ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
3457 else if (peek_char == '(') /* ) */
3458 {
3459 /* XXX - push and pop the `(' as a delimiter for use by
3460 the command-oriented-history code. This way newlines
3461 appearing in the $(...) string get added to the
3462 history literally rather than causing a possibly-
3463 incorrect `;' to be added. ) */
3464 push_delimiter (dstack, peek_char);
3465 ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND);
3466 pop_delimiter (dstack);
3467 }
3468 else
3469 ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
3470 if (ttok == &matched_pair_error)
3471 return -1; /* Bail immediately. */
3472 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
3473 token_buffer_size,
3474 TOKEN_DEFAULT_GROW_SIZE);
3475 token[token_index++] = character;
3476 token[token_index++] = peek_char;
3477 strcpy (token + token_index, ttok);
3478 token_index += ttoklen;
3479 FREE (ttok);
3480 dollar_present = 1;
3481 all_digit_token = 0;
3482 goto next_character;
3483 }
3484 /* This handles $'...' and $"..." new-style quoted strings. */
3485 else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
3486 {
3487 int first_line;
3488
3489 first_line = line_number;
3490 push_delimiter (dstack, peek_char);
3491 ttok = parse_matched_pair (peek_char, peek_char, peek_char,
3492 &ttoklen,
3493 (peek_char == '\'') ? P_ALLOWESC : 0);
3494 pop_delimiter (dstack);
3495 if (ttok == &matched_pair_error)
3496 return -1;
3497 if (peek_char == '\'')
3498 {
3499 ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
3500 free (ttok);
3501
3502 /* Insert the single quotes and correctly quote any
3503 embedded single quotes (allowed because P_ALLOWESC was
3504 passed to parse_matched_pair). */
3505 ttok = sh_single_quote (ttrans);
3506 free (ttrans);
3507 ttranslen = strlen (ttok);
3508 ttrans = ttok;
3509 }
3510 else
3511 {
3512 /* Try to locale)-expand the converted string. */
3513 ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
3514 free (ttok);
3515
3516 /* Add the double quotes back */
3517 ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
3518 free (ttrans);
3519 ttranslen += 2;
3520 ttrans = ttok;
3521 }
3522
3523 RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2,
3524 token_buffer_size,
3525 TOKEN_DEFAULT_GROW_SIZE);
3526 strcpy (token + token_index, ttrans);
3527 token_index += ttranslen;
3528 FREE (ttrans);
3529 quoted = 1;
3530 all_digit_token = 0;
3531 goto next_character;
3532 }
3533 /* This could eventually be extended to recognize all of the
3534 shell's single-character parameter expansions, and set flags.*/
3535 else if MBTEST(character == '$' && peek_char == '$')
3536 {
3537 ttok = (char *)xmalloc (3);
3538 ttok[0] = ttok[1] = '$';
3539 ttok[2] = '\0';
3540 RESIZE_MALLOCED_BUFFER (token, token_index, 3,
3541 token_buffer_size,
3542 TOKEN_DEFAULT_GROW_SIZE);
3543 strcpy (token + token_index, ttok);
3544 token_index += 2;
3545 dollar_present = 1;
3546 all_digit_token = 0;
3547 FREE (ttok);
3548 goto next_character;
3549 }
3550 else
3551 shell_ungetc (peek_char);
3552 }
3553
3554#if defined (ARRAY_VARS)
3555 /* Identify possible array subscript assignment; match [...] */
3556 else if MBTEST(character == '[' && token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) /* ] */
3557 {
3558 ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
3559 if (ttok == &matched_pair_error)
3560 return -1; /* Bail immediately. */
3561 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
3562 token_buffer_size,
3563 TOKEN_DEFAULT_GROW_SIZE);
3564 token[token_index++] = character;
3565 strcpy (token + token_index, ttok);
3566 token_index += ttoklen;
3567 FREE (ttok);
3568 all_digit_token = 0;
3569 goto next_character;
3570 }
3571 /* Identify possible compound array variable assignment. */
3572 else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
3573 {
3574 peek_char = shell_getc (1);
3575 if MBTEST(peek_char == '(') /* ) */
3576 {
3577 ttok = parse_compound_assignment (&ttoklen);
3578
3579 RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
3580 token_buffer_size,
3581 TOKEN_DEFAULT_GROW_SIZE);
3582
3583 token[token_index++] = '=';
3584 token[token_index++] = '(';
3585 if (ttok)
3586 {
3587 strcpy (token + token_index, ttok);
3588 token_index += ttoklen;
3589 }
3590 token[token_index++] = ')';
3591 FREE (ttok);
3592 all_digit_token = 0;
3593 compound_assignment = 1;
3594#if 1
3595 goto next_character;
3596#else
3597 goto got_token; /* ksh93 seems to do this */
3598#endif
3599 }
3600 else
3601 shell_ungetc (peek_char);
3602 }
3603#endif
3604
3605 /* When not parsing a multi-character word construct, shell meta-
3606 characters break words. */
3607 if MBTEST(shellbreak (character))
3608 {
3609 shell_ungetc (character);
3610 goto got_token;
3611 }
3612
3613 got_character:
3614
3615 all_digit_token &= DIGIT (character);
3616 dollar_present |= character == '$';
3617
3618 if (character == CTLESC || character == CTLNUL)
3619 token[token_index++] = CTLESC;
3620
3621 token[token_index++] = character;
3622
3623 RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
3624 TOKEN_DEFAULT_GROW_SIZE);
3625
3626 next_character:
3627 if (character == '\n' && SHOULD_PROMPT ())
3628 prompt_again ();
3629
3630 /* We want to remove quoted newlines (that is, a \<newline> pair)
3631 unless we are within single quotes or pass_next_character is
3632 set (the shell equivalent of literal-next). */
3633 cd = current_delimiter (dstack);
3634 character = shell_getc (cd != '\'' && pass_next_character == 0);
3635 } /* end for (;;) */
3636
3637got_token:
3638
3639 token[token_index] = '\0';
3640
3641 /* Check to see what thing we should return. If the last_read_token
3642 is a `<', or a `&', or the character which ended this token is
3643 a '>' or '<', then, and ONLY then, is this input token a NUMBER.
3644 Otherwise, it is just a word, and should be returned as such. */
3645 if MBTEST(all_digit_token && (character == '<' || character == '>' || \
3646 last_read_token == LESS_AND || \
3647 last_read_token == GREATER_AND))
3648 {
3649 if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
3650 yylval.number = lvalue;
3651 else
3652 yylval.number = -1;
3653 return (NUMBER);
3654 }
3655
3656 /* Check for special case tokens. */
3657 result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
3658 if (result >= 0)
3659 return result;
3660
3661#if defined (ALIAS)
3662 /* Posix.2 does not allow reserved words to be aliased, so check for all
3663 of them, including special cases, before expanding the current token
3664 as an alias. */
3665 if MBTEST(posixly_correct)
3666 CHECK_FOR_RESERVED_WORD (token);
3667
3668 /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
3669 inhibits alias expansion. */
3670 if (expand_aliases && quoted == 0)
3671 {
3672 result = alias_expand_token (token);
3673 if (result == RE_READ_TOKEN)
3674 return (RE_READ_TOKEN);
3675 else if (result == NO_EXPANSION)
3676 parser_state &= ~PST_ALEXPNEXT;
3677 }
3678
3679 /* If not in Posix.2 mode, check for reserved words after alias
3680 expansion. */
3681 if MBTEST(posixly_correct == 0)
3682#endif
3683 CHECK_FOR_RESERVED_WORD (token);
3684
3685 the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
3686 the_word->word = (char *)xmalloc (1 + token_index);
3687 the_word->flags = 0;
3688 strcpy (the_word->word, token);
3689 if (dollar_present)
3690 the_word->flags |= W_HASDOLLAR;
3691 if (quoted)
3692 the_word->flags |= W_QUOTED;
3693 if (compound_assignment)
3694 the_word->flags |= W_COMPASSIGN;
3695 /* A word is an assignment if it appears at the beginning of a
3696 simple command, or after another assignment word. This is
3697 context-dependent, so it cannot be handled in the grammar. */
3698 if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
3699 {
3700 the_word->flags |= W_ASSIGNMENT;
3701 /* Don't perform word splitting on assignment statements. */
3702 if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
3703 the_word->flags |= W_NOSPLIT;
3704 }
3705
3706 if (command_token_position (last_read_token))
3707 {
3708 struct builtin *b;
3709 b = builtin_address_internal (token, 0);
3710 if (b && (b->flags & ASSIGNMENT_BUILTIN))
3711 parser_state |= PST_ASSIGNOK;
3712 else if (STREQ (token, "eval") || STREQ (token, "let"))
3713 parser_state |= PST_ASSIGNOK;
3714 }
3715
3716 yylval.word = the_word;
3717
3718 result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
3719 ? ASSIGNMENT_WORD : WORD;
3720
3721 switch (last_read_token)
3722 {
3723 case FUNCTION:
3724 parser_state |= PST_ALLOWOPNBRC;
3725 function_dstart = line_number;
3726 break;
3727 case CASE:
3728 case SELECT:
3729 case FOR:
3730 if (word_top < MAX_CASE_NEST)
3731 word_top++;
3732 word_lineno[word_top] = line_number;
3733 break;
3734 }
3735
3736 return (result);
3737}
3738
3739/* Return 1 if TOKSYM is a token that after being read would allow
3740 a reserved word to be seen, else 0. */
3741static int
3742reserved_word_acceptable (toksym)
3743 int toksym;
3744{
3745 switch (toksym)
3746 {
3747 case '\n':
3748 case ';':
3749 case '(':
3750 case ')':
3751 case '|':
3752 case '&':
3753 case '{':
3754 case '}': /* XXX */
3755 case AND_AND:
3756 case BANG:
3757 case DO:
3758 case DONE:
3759 case ELIF:
3760 case ELSE:
3761 case ESAC:
3762 case FI:
3763 case IF:
3764 case OR_OR:
3765 case SEMI_SEMI:
3766 case THEN:
3767 case TIME:
3768 case TIMEOPT:
3769 case UNTIL:
3770 case WHILE:
3771 case 0:
3772 return 1;
3773 default:
3774 return 0;
3775 }
3776}
3777
3778/* Return the index of TOKEN in the alist of reserved words, or -1 if
3779 TOKEN is not a shell reserved word. */
3780int
3781find_reserved_word (tokstr)
3782 char *tokstr;
3783{
3784 int i;
3785 for (i = 0; word_token_alist[i].word; i++)
3786 if (STREQ (tokstr, word_token_alist[i].word))
3787 return i;
3788 return -1;
3789}
3790
3791#if 0
3792#if defined (READLINE)
3793/* Called after each time readline is called. This insures that whatever
3794 the new prompt string is gets propagated to readline's local prompt
3795 variable. */
3796static void
3797reset_readline_prompt ()
3798{
3799 char *temp_prompt;
3800
3801 if (prompt_string_pointer)
3802 {
3803 temp_prompt = (*prompt_string_pointer)
3804 ? decode_prompt_string (*prompt_string_pointer)
3805 : (char *)NULL;
3806
3807 if (temp_prompt == 0)
3808 {
3809 temp_prompt = (char *)xmalloc (1);
3810 temp_prompt[0] = '\0';
3811 }
3812
3813 FREE (current_readline_prompt);
3814 current_readline_prompt = temp_prompt;
3815 }
3816}
3817#endif /* READLINE */
3818#endif /* 0 */
3819
3820#if defined (HISTORY)
3821/* A list of tokens which can be followed by newlines, but not by
3822 semi-colons. When concatenating multiple lines of history, the
3823 newline separator for such tokens is replaced with a space. */
3824static int no_semi_successors[] = {
3825 '\n', '{', '(', ')', ';', '&', '|',
3826 CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN,
3827 0
3828};
3829
3830/* If we are not within a delimited expression, try to be smart
3831 about which separators can be semi-colons and which must be
3832 newlines. Returns the string that should be added into the
3833 history entry. */
3834char *
3835history_delimiting_chars ()
3836{
3837 register int i;
3838
3839 if (dstack.delimiter_depth != 0)
3840 return ("\n");
3841
3842 /* First, handle some special cases. */
3843 /*(*/
3844 /* If we just read `()', assume it's a function definition, and don't
3845 add a semicolon. If the token before the `)' was not `(', and we're
3846 not in the midst of parsing a case statement, assume it's a
3847 parenthesized command and add the semicolon. */
3848 /*)(*/
3849 if (token_before_that == ')')
3850 {
3851 if (two_tokens_ago == '(') /*)*/ /* function def */
3852 return " ";
3853 /* This does not work for subshells inside case statement
3854 command lists. It's a suboptimal solution. */
3855 else if (parser_state & PST_CASESTMT) /* case statement pattern */
3856 return " ";
3857 else
3858 return "; "; /* (...) subshell */
3859 }
3860 else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
3861 return " "; /* function def using `function name' without `()' */
3862
3863 else if (token_before_that == WORD && two_tokens_ago == FOR)
3864 {
3865 /* Tricky. `for i\nin ...' should not have a semicolon, but
3866 `for i\ndo ...' should. We do what we can. */
3867 for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
3868 ;
3869 if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
3870 return " ";
3871 return ";";
3872 }
3873 else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
3874 return " ";
3875
3876 for (i = 0; no_semi_successors[i]; i++)
3877 {
3878 if (token_before_that == no_semi_successors[i])
3879 return (" ");
3880 }
3881
3882 return ("; ");
3883}
3884#endif /* HISTORY */
3885
3886/* Issue a prompt, or prepare to issue a prompt when the next character
3887 is read. */
3888static void
3889prompt_again ()
3890{
3891 char *temp_prompt;
3892
3893 if (interactive == 0 || expanding_alias()) /* XXX */
3894 return;
3895
3896 ps1_prompt = get_string_value ("PS1");
3897 ps2_prompt = get_string_value ("PS2");
3898
3899 if (!prompt_string_pointer)
3900 prompt_string_pointer = &ps1_prompt;
3901
3902 temp_prompt = *prompt_string_pointer
3903 ? decode_prompt_string (*prompt_string_pointer)
3904 : (char *)NULL;
3905
3906 if (temp_prompt == 0)
3907 {
3908 temp_prompt = (char *)xmalloc (1);
3909 temp_prompt[0] = '\0';
3910 }
3911
3912 current_prompt_string = *prompt_string_pointer;
3913 prompt_string_pointer = &ps2_prompt;
3914
3915#if defined (READLINE)
3916 if (!no_line_editing)
3917 {
3918 FREE (current_readline_prompt);
3919 current_readline_prompt = temp_prompt;
3920 }
3921 else
3922#endif /* READLINE */
3923 {
3924 FREE (current_decoded_prompt);
3925 current_decoded_prompt = temp_prompt;
3926 }
3927}
3928
3929int
3930get_current_prompt_level ()
3931{
3932 return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
3933}
3934
3935void
3936set_current_prompt_level (x)
3937 int x;
3938{
3939 prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
3940 current_prompt_string = *prompt_string_pointer;
3941}
3942
3943static void
3944print_prompt ()
3945{
3946 fprintf (stderr, "%s", current_decoded_prompt);
3947 fflush (stderr);
3948}
3949
3950/* Return a string which will be printed as a prompt. The string
3951 may contain special characters which are decoded as follows:
3952
3953 \a bell (ascii 07)
3954 \d the date in Day Mon Date format
3955 \e escape (ascii 033)
3956 \h the hostname up to the first `.'
3957 \H the hostname
3958 \j the number of active jobs
3959 \l the basename of the shell's tty device name
3960 \n CRLF
3961 \r CR
3962 \s the name of the shell
3963 \t the time in 24-hour hh:mm:ss format
3964 \T the time in 12-hour hh:mm:ss format
3965 \@ the time in 12-hour hh:mm am/pm format
3966 \A the time in 24-hour hh:mm format
3967 \D{fmt} the result of passing FMT to strftime(3)
3968 \u your username
3969 \v the version of bash (e.g., 2.00)
3970 \V the release of bash, version + patchlevel (e.g., 2.00.0)
3971 \w the current working directory
3972 \W the last element of $PWD
3973 \! the history number of this command
3974 \# the command number of this command
3975 \$ a $ or a # if you are root
3976 \nnn character code nnn in octal
3977 \\ a backslash
3978 \[ begin a sequence of non-printing chars
3979 \] end a sequence of non-printing chars
3980*/
3981#define PROMPT_GROWTH 48
3982char *
3983decode_prompt_string (string)
3984 char *string;
3985{
3986 WORD_LIST *list;
3987 char *result, *t;
3988 struct dstack save_dstack;
3989 int last_exit_value;
3990#if defined (PROMPT_STRING_DECODE)
3991 int result_size, result_index;
3992 int c, n;
3993 char *temp, octal_string[4];
3994 struct tm *tm;
3995 time_t the_time;
3996 char timebuf[128];
3997 char *timefmt;
3998
3999 result = (char *)xmalloc (result_size = PROMPT_GROWTH);
4000 result[result_index = 0] = 0;
4001 temp = (char *)NULL;
4002
4003 while (c = *string++)
4004 {
4005 if (posixly_correct && c == '!')
4006 {
4007 if (*string == '!')
4008 {
4009 temp = savestring ("!");
4010 goto add_string;
4011 }
4012 else
4013 {
4014#if !defined (HISTORY)
4015 temp = savestring ("1");
4016#else /* HISTORY */
4017 temp = itos (history_number ());
4018#endif /* HISTORY */
4019 string--; /* add_string increments string again. */
4020 goto add_string;
4021 }
4022 }
4023 if (c == '\\')
4024 {
4025 c = *string;
4026
4027 switch (c)
4028 {
4029 case '0':
4030 case '1':
4031 case '2':
4032 case '3':
4033 case '4':
4034 case '5':
4035 case '6':
4036 case '7':
4037 strncpy (octal_string, string, 3);
4038 octal_string[3] = '\0';
4039
4040 n = read_octal (octal_string);
4041 temp = (char *)xmalloc (3);
4042
4043 if (n == CTLESC || n == CTLNUL)
4044 {
4045 temp[0] = CTLESC;
4046 temp[1] = n;
4047 temp[2] = '\0';
4048 }
4049 else if (n == -1)
4050 {
4051 temp[0] = '\\';
4052 temp[1] = '\0';
4053 }
4054 else
4055 {
4056 temp[0] = n;
4057 temp[1] = '\0';
4058 }
4059
4060 for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
4061 string++;
4062
4063 c = 0; /* tested at add_string: */
4064 goto add_string;
4065
4066 case 'd':
4067 case 't':
4068 case 'T':
4069 case '@':
4070 case 'A':
4071 /* Make the current time/date into a string. */
4072 (void) time (&the_time);
4073 tm = localtime (&the_time);
4074
4075 if (c == 'd')
4076 n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
4077 else if (c == 't')
4078 n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
4079 else if (c == 'T')
4080 n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
4081 else if (c == '@')
4082 n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
4083 else if (c == 'A')
4084 n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
4085
4086 if (n == 0)
4087 timebuf[0] = '\0';
4088 else
4089 timebuf[sizeof(timebuf) - 1] = '\0';
4090
4091 temp = savestring (timebuf);
4092 goto add_string;
4093
4094 case 'D': /* strftime format */
4095 if (string[1] != '{') /* } */
4096 goto not_escape;
4097
4098 (void) time (&the_time);
4099 tm = localtime (&the_time);
4100 string += 2; /* skip { */
4101 timefmt = xmalloc (strlen (string) + 3);
4102 for (t = timefmt; *string && *string != '}'; )
4103 *t++ = *string++;
4104 *t = '\0';
4105 c = *string; /* tested at add_string */
4106 if (timefmt[0] == '\0')
4107 {
4108 timefmt[0] = '%';
4109 timefmt[1] = 'X'; /* locale-specific current time */
4110 timefmt[2] = '\0';
4111 }
4112 n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
4113 free (timefmt);
4114
4115 if (n == 0)
4116 timebuf[0] = '\0';
4117 else
4118 timebuf[sizeof(timebuf) - 1] = '\0';
4119
4120 if (promptvars || posixly_correct)
4121 /* Make sure that expand_prompt_string is called with a
4122 second argument of Q_DOUBLE_QUOTES if we use this
4123 function here. */
4124 temp = sh_backslash_quote_for_double_quotes (timebuf);
4125 else
4126 temp = savestring (timebuf);
4127 goto add_string;
4128
4129 case 'n':
4130 temp = (char *)xmalloc (3);
4131 temp[0] = no_line_editing ? '\n' : '\r';
4132 temp[1] = no_line_editing ? '\0' : '\n';
4133 temp[2] = '\0';
4134 goto add_string;
4135
4136 case 's':
4137 temp = base_pathname (shell_name);
4138 temp = savestring (temp);
4139 goto add_string;
4140
4141 case 'v':
4142 case 'V':
4143 temp = (char *)xmalloc (16);
4144 if (c == 'v')
4145 strcpy (temp, dist_version);
4146 else
4147 sprintf (temp, "%s.%d", dist_version, patch_level);
4148 goto add_string;
4149
4150 case 'w':
4151 case 'W':
4152 {
4153 /* Use the value of PWD because it is much more efficient. */
4154 char t_string[PATH_MAX], *t;
4155 int tlen;
4156
4157 temp = get_string_value ("PWD");
4158
4159 if (temp == 0)
4160 {
4161 if (getcwd (t_string, sizeof(t_string)) == 0)
4162 {
4163 t_string[0] = '.';
4164 tlen = 1;
4165 }
4166 else
4167 tlen = strlen (t_string);
4168 }
4169 else
4170 {
4171 tlen = sizeof (t_string) - 1;
4172 strncpy (t_string, temp, tlen);
4173 }
4174 t_string[tlen] = '\0';
4175
4176#define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0)
4177#define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
4178 /* Abbreviate \W as ~ if $PWD == $HOME */
4179 if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
4180 {
4181 if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
4182 {
4183 t = strrchr (t_string, '/');
4184 if (t)
4185 strcpy (t_string, t + 1);
4186 }
4187 }
4188#undef ROOT_PATH
4189#undef DOUBLE_SLASH_ROOT
4190 else
4191 /* polite_directory_format is guaranteed to return a string
4192 no longer than PATH_MAX - 1 characters. */
4193 strcpy (t_string, polite_directory_format (t_string));
4194
4195 /* If we're going to be expanding the prompt string later,
4196 quote the directory name. */
4197 if (promptvars || posixly_correct)
4198 /* Make sure that expand_prompt_string is called with a
4199 second argument of Q_DOUBLE_QUOTES if we use this
4200 function here. */
4201 temp = sh_backslash_quote_for_double_quotes (t_string);
4202 else
4203 temp = savestring (t_string);
4204
4205 goto add_string;
4206 }
4207
4208 case 'u':
4209 if (current_user.user_name == 0)
4210 get_current_user_info ();
4211 temp = savestring (current_user.user_name);
4212 goto add_string;
4213
4214 case 'h':
4215 case 'H':
4216 temp = savestring (current_host_name);
4217 if (c == 'h' && (t = (char *)strchr (temp, '.')))
4218 *t = '\0';
4219 goto add_string;
4220
4221 case '#':
4222 temp = itos (current_command_number);
4223 goto add_string;
4224
4225 case '!':
4226#if !defined (HISTORY)
4227 temp = savestring ("1");
4228#else /* HISTORY */
4229 temp = itos (history_number ());
4230#endif /* HISTORY */
4231 goto add_string;
4232
4233 case '$':
4234 t = temp = (char *)xmalloc (3);
4235 if ((promptvars || posixly_correct) && (current_user.euid != 0))
4236 *t++ = '\\';
4237 *t++ = current_user.euid == 0 ? '#' : '$';
4238 *t = '\0';
4239 goto add_string;
4240
4241 case 'j':
4242 temp = itos (count_all_jobs ());
4243 goto add_string;
4244
4245 case 'l':
4246#if defined (HAVE_TTYNAME)
4247 temp = (char *)ttyname (fileno (stdin));
4248 t = temp ? base_pathname (temp) : "tty";
4249 temp = savestring (t);
4250#else
4251 temp = savestring ("tty");
4252#endif /* !HAVE_TTYNAME */
4253 goto add_string;
4254
4255#if defined (READLINE)
4256 case '[':
4257 case ']':
4258 if (no_line_editing)
4259 {
4260 string++;
4261 break;
4262 }
4263 temp = (char *)xmalloc (3);
4264 temp[0] = '\001';
4265 temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
4266 temp[2] = '\0';
4267 goto add_string;
4268#endif /* READLINE */
4269
4270 case '\\':
4271 case 'a':
4272 case 'e':
4273 case 'r':
4274 temp = (char *)xmalloc (2);
4275 if (c == 'a')
4276 temp[0] = '\07';
4277 else if (c == 'e')
4278 temp[0] = '\033';
4279 else if (c == 'r')
4280 temp[0] = '\r';
4281 else /* (c == '\\') */
4282 temp[0] = c;
4283 temp[1] = '\0';
4284 goto add_string;
4285
4286 default:
4287not_escape:
4288 temp = (char *)xmalloc (3);
4289 temp[0] = '\\';
4290 temp[1] = c;
4291 temp[2] = '\0';
4292
4293 add_string:
4294 if (c)
4295 string++;
4296 result =
4297 sub_append_string (temp, result, &result_index, &result_size);
4298 temp = (char *)NULL; /* Freed in sub_append_string (). */
4299 result[result_index] = '\0';
4300 break;
4301 }
4302 }
4303 else
4304 {
4305 RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
4306 result[result_index++] = c;
4307 result[result_index] = '\0';
4308 }
4309 }
4310#else /* !PROMPT_STRING_DECODE */
4311 result = savestring (string);
4312#endif /* !PROMPT_STRING_DECODE */
4313
4314 /* Save the delimiter stack and point `dstack' to temp space so any
4315 command substitutions in the prompt string won't result in screwing
4316 up the parser's quoting state. */
4317 save_dstack = dstack;
4318 dstack = temp_dstack;
4319 dstack.delimiter_depth = 0;
4320
4321 /* Perform variable and parameter expansion and command substitution on
4322 the prompt string. */
4323 if (promptvars || posixly_correct)
4324 {
4325 last_exit_value = last_command_exit_value;
4326 list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
4327 free (result);
4328 result = string_list (list);
4329 dispose_words (list);
4330 last_command_exit_value = last_exit_value;
4331 }
4332 else
4333 {
4334 t = dequote_string (result);
4335 free (result);
4336 result = t;
4337 }
4338
4339 dstack = save_dstack;
4340
4341 return (result);
4342}
4343
4344/************************************************
4345 * *
4346 * ERROR HANDLING *
4347 * *
4348 ************************************************/
4349
4350/* Report a syntax error, and restart the parser. Call here for fatal
4351 errors. */
4352int
4353yyerror (msg)
4354 const char *msg;
4355{
4356 report_syntax_error ((char *)NULL);
4357 reset_parser ();
4358 return (0);
4359}
4360
4361static char *
4362error_token_from_token (token)
4363 int token;
4364{
4365 char *t;
4366
4367 if (t = find_token_in_alist (token, word_token_alist, 0))
4368 return t;
4369
4370 if (t = find_token_in_alist (token, other_token_alist, 0))
4371 return t;
4372
4373 t = (char *)NULL;
4374 /* This stuff is dicy and needs closer inspection */
4375 switch (current_token)
4376 {
4377 case WORD:
4378 case ASSIGNMENT_WORD:
4379 if (yylval.word)
4380 t = savestring (yylval.word->word);
4381 break;
4382 case NUMBER:
4383 t = itos (yylval.number);
4384 break;
4385 case ARITH_CMD:
4386 if (yylval.word_list)
4387 t = string_list (yylval.word_list);
4388 break;
4389 case ARITH_FOR_EXPRS:
4390 if (yylval.word_list)
4391 t = string_list_internal (yylval.word_list, " ; ");
4392 break;
4393 case COND_CMD:
4394 t = (char *)NULL; /* punt */
4395 break;
4396 }
4397
4398 return t;
4399}
4400
4401static char *
4402error_token_from_text ()
4403{
4404 char *msg, *t;
4405 int token_end, i;
4406
4407 t = shell_input_line;
4408 i = shell_input_line_index;
4409 token_end = 0;
4410 msg = (char *)NULL;
4411
4412 if (i && t[i] == '\0')
4413 i--;
4414
4415 while (i && (whitespace (t[i]) || t[i] == '\n'))
4416 i--;
4417
4418 if (i)
4419 token_end = i + 1;
4420
4421 while (i && (member (t[i], " \n\t;|&") == 0))
4422 i--;
4423
4424 while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
4425 i++;
4426
4427 /* Return our idea of the offending token. */
4428 if (token_end || (i == 0 && token_end == 0))
4429 {
4430 if (token_end)
4431 msg = substring (t, i, token_end);
4432 else /* one-character token */
4433 {
4434 msg = (char *)xmalloc (2);
4435 msg[0] = t[i];
4436 msg[1] = '\0';
4437 }
4438 }
4439
4440 return (msg);
4441}
4442
4443static void
4444print_offending_line ()
4445{
4446 char *msg;
4447 int token_end;
4448
4449 msg = savestring (shell_input_line);
4450 token_end = strlen (msg);
4451 while (token_end && msg[token_end - 1] == '\n')
4452 msg[--token_end] = '\0';
4453
4454 parser_error (line_number, "`%s'", msg);
4455 free (msg);
4456}
4457
4458/* Report a syntax error with line numbers, etc.
4459 Call here for recoverable errors. If you have a message to print,
4460 then place it in MESSAGE, otherwise pass NULL and this will figure
4461 out an appropriate message for you. */
4462static void
4463report_syntax_error (message)
4464 char *message;
4465{
4466 char *msg;
4467
4468 if (message)
4469 {
4470 parser_error (line_number, "%s", message);
4471 if (interactive && EOF_Reached)
4472 EOF_Reached = 0;
4473 last_command_exit_value = EX_USAGE;
4474 return;
4475 }
4476
4477 /* If the line of input we're reading is not null, try to find the
4478 objectionable token. First, try to figure out what token the
4479 parser's complaining about by looking at current_token. */
4480 if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
4481 {
4482 parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
4483 free (msg);
4484
4485 if (interactive == 0)
4486 print_offending_line ();
4487
4488 last_command_exit_value = EX_USAGE;
4489 return;
4490 }
4491
4492 /* If looking at the current token doesn't prove fruitful, try to find the
4493 offending token by analyzing the text of the input line near the current
4494 input line index and report what we find. */
4495 if (shell_input_line && *shell_input_line)
4496 {
4497 msg = error_token_from_text ();
4498 if (msg)
4499 {
4500 parser_error (line_number, _("syntax error near `%s'"), msg);
4501 free (msg);
4502 }
4503
4504 /* If not interactive, print the line containing the error. */
4505 if (interactive == 0)
4506 print_offending_line ();
4507 }
4508 else
4509 {
4510 msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
4511 parser_error (line_number, "%s", msg);
4512 /* When the shell is interactive, this file uses EOF_Reached
4513 only for error reporting. Other mechanisms are used to
4514 decide whether or not to exit. */
4515 if (interactive && EOF_Reached)
4516 EOF_Reached = 0;
4517 }
4518
4519 last_command_exit_value = EX_USAGE;
4520}
4521
4522/* ??? Needed function. ??? We have to be able to discard the constructs
4523 created during parsing. In the case of error, we want to return
4524 allocated objects to the memory pool. In the case of no error, we want
4525 to throw away the information about where the allocated objects live.
4526 (dispose_command () will actually free the command.) */
4527static void
4528discard_parser_constructs (error_p)
4529 int error_p;
4530{
4531}
4532
4533/************************************************
4534 * *
4535 * EOF HANDLING *
4536 * *
4537 ************************************************/
4538
4539/* Do that silly `type "bye" to exit' stuff. You know, "ignoreeof". */
4540
4541/* A flag denoting whether or not ignoreeof is set. */
4542int ignoreeof = 0;
4543
4544/* The number of times that we have encountered an EOF character without
4545 another character intervening. When this gets above the limit, the
4546 shell terminates. */
4547int eof_encountered = 0;
4548
4549/* The limit for eof_encountered. */
4550int eof_encountered_limit = 10;
4551
4552/* If we have EOF as the only input unit, this user wants to leave
4553 the shell. If the shell is not interactive, then just leave.
4554 Otherwise, if ignoreeof is set, and we haven't done this the
4555 required number of times in a row, print a message. */
4556static void
4557handle_eof_input_unit ()
4558{
4559 if (interactive)
4560 {
4561 /* shell.c may use this to decide whether or not to write out the
4562 history, among other things. We use it only for error reporting
4563 in this file. */
4564 if (EOF_Reached)
4565 EOF_Reached = 0;
4566
4567 /* If the user wants to "ignore" eof, then let her do so, kind of. */
4568 if (ignoreeof)
4569 {
4570 if (eof_encountered < eof_encountered_limit)
4571 {
4572 fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
4573 login_shell ? "logout" : "exit");
4574 eof_encountered++;
4575 /* Reset the parsing state. */
4576 last_read_token = current_token = '\n';
4577 /* Reset the prompt string to be $PS1. */
4578 prompt_string_pointer = (char **)NULL;
4579 prompt_again ();
4580 return;
4581 }
4582 }
4583
4584 /* In this case EOF should exit the shell. Do it now. */
4585 reset_parser ();
4586 exit_builtin ((WORD_LIST *)NULL);
4587 }
4588 else
4589 {
4590 /* We don't write history files, etc., for non-interactive shells. */
4591 EOF_Reached = 1;
4592 }
4593}
4594
4595/************************************************
4596 * *
4597 * STRING PARSING FUNCTIONS *
4598 * *
4599 ************************************************/
4600
4601/* It's very important that these two functions treat the characters
4602 between ( and ) identically. */
4603
4604static WORD_LIST parse_string_error;
4605
4606/* Take a string and run it through the shell parser, returning the
4607 resultant word list. Used by compound array assignment. */
4608WORD_LIST *
4609parse_string_to_word_list (s, flags, whom)
4610 char *s;
4611 int flags;
4612 const char *whom;
4613{
4614 WORD_LIST *wl;
4615 int tok, orig_current_token, orig_line_number, orig_input_terminator;
4616 int orig_line_count;
4617 int old_echo_input, old_expand_aliases;
4618#if defined (HISTORY)
4619 int old_remember_on_history, old_history_expansion_inhibited;
4620#endif
4621
4622#if defined (HISTORY)
4623 old_remember_on_history = remember_on_history;
4624# if defined (BANG_HISTORY)
4625 old_history_expansion_inhibited = history_expansion_inhibited;
4626# endif
4627 bash_history_disable ();
4628#endif
4629
4630 orig_line_number = line_number;
4631 orig_line_count = current_command_line_count;
4632 orig_input_terminator = shell_input_line_terminator;
4633 old_echo_input = echo_input_at_read;
4634 old_expand_aliases = expand_aliases;
4635
4636 push_stream (1);
4637 last_read_token = WORD; /* WORD to allow reserved words here */
4638 current_command_line_count = 0;
4639 echo_input_at_read = expand_aliases = 0;
4640
4641 with_input_from_string (s, whom);
4642 wl = (WORD_LIST *)NULL;
4643
4644 if (flags & 1)
4645 parser_state |= PST_COMPASSIGN;
4646
4647 while ((tok = read_token (READ)) != yacc_EOF)
4648 {
4649 if (tok == '\n' && *bash_input.location.string == '\0')
4650 break;
4651 if (tok == '\n') /* Allow newlines in compound assignments */
4652 continue;
4653 if (tok != WORD && tok != ASSIGNMENT_WORD)
4654 {
4655 line_number = orig_line_number + line_number - 1;
4656 orig_current_token = current_token;
4657 current_token = tok;
4658 yyerror (NULL); /* does the right thing */
4659 current_token = orig_current_token;
4660 if (wl)
4661 dispose_words (wl);
4662 wl = &parse_string_error;
4663 break;
4664 }
4665 wl = make_word_list (yylval.word, wl);
4666 }
4667
4668 last_read_token = '\n';
4669 pop_stream ();
4670
4671#if defined (HISTORY)
4672 remember_on_history = old_remember_on_history;
4673# if defined (BANG_HISTORY)
4674 history_expansion_inhibited = old_history_expansion_inhibited;
4675# endif /* BANG_HISTORY */
4676#endif /* HISTORY */
4677
4678 echo_input_at_read = old_echo_input;
4679 expand_aliases = old_expand_aliases;
4680
4681 current_command_line_count = orig_line_count;
4682 shell_input_line_terminator = orig_input_terminator;
4683
4684 if (flags & 1)
4685 parser_state &= ~PST_COMPASSIGN;
4686
4687 if (wl == &parse_string_error)
4688 {
4689 last_command_exit_value = EXECUTION_FAILURE;
4690 if (interactive_shell == 0 && posixly_correct)
4691 jump_to_top_level (FORCE_EOF);
4692 else
4693 jump_to_top_level (DISCARD);
4694 }
4695
4696 return (REVERSE_LIST (wl, WORD_LIST *));
4697}
4698
4699static char *
4700parse_compound_assignment (retlenp)
4701 int *retlenp;
4702{
4703 WORD_LIST *wl, *rl;
4704 int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
4705 char *saved_token, *ret;
4706
4707 saved_token = token;
4708 orig_token_size = token_buffer_size;
4709 orig_line_number = line_number;
4710 orig_last_token = last_read_token;
4711
4712 last_read_token = WORD; /* WORD to allow reserved words here */
4713
4714 token = (char *)NULL;
4715 token_buffer_size = 0;
4716
4717 assignok = parser_state&PST_ASSIGNOK; /* XXX */
4718
4719 wl = (WORD_LIST *)NULL; /* ( */
4720 parser_state |= PST_COMPASSIGN;
4721
4722 while ((tok = read_token (READ)) != ')')
4723 {
4724 if (tok == '\n') /* Allow newlines in compound assignments */
4725 {
4726 if (SHOULD_PROMPT ())
4727 prompt_again ();
4728 continue;
4729 }
4730 if (tok != WORD && tok != ASSIGNMENT_WORD)
4731 {
4732 current_token = tok; /* for error reporting */
4733 if (tok == yacc_EOF) /* ( */
4734 parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
4735 else
4736 yyerror(NULL); /* does the right thing */
4737 if (wl)
4738 dispose_words (wl);
4739 wl = &parse_string_error;
4740 break;
4741 }
4742 wl = make_word_list (yylval.word, wl);
4743 }
4744
4745 FREE (token);
4746 token = saved_token;
4747 token_buffer_size = orig_token_size;
4748
4749 parser_state &= ~PST_COMPASSIGN;
4750
4751 if (wl == &parse_string_error)
4752 {
4753 last_command_exit_value = EXECUTION_FAILURE;
4754 last_read_token = '\n'; /* XXX */
4755 if (interactive_shell == 0 && posixly_correct)
4756 jump_to_top_level (FORCE_EOF);
4757 else
4758 jump_to_top_level (DISCARD);
4759 }
4760
4761 last_read_token = orig_last_token; /* XXX - was WORD? */
4762 if (wl)
4763 {
4764 rl = REVERSE_LIST (wl, WORD_LIST *);
4765 ret = string_list (rl);
4766 dispose_words (rl);
4767 }
4768 else
4769 ret = (char *)NULL;
4770
4771 if (retlenp)
4772 *retlenp = (ret && *ret) ? strlen (ret) : 0;
4773
4774 if (assignok)
4775 parser_state |= PST_ASSIGNOK;
4776
4777 return ret;
4778}
4779
4780/************************************************
4781 * *
4782 * SAVING AND RESTORING PARTIAL PARSE STATE *
4783 * *
4784 ************************************************/
4785
4786sh_parser_state_t *
4787save_parser_state (ps)
4788 sh_parser_state_t *ps;
4789{
4790#if defined (ARRAY_VARS)
4791 SHELL_VAR *v;
4792#endif
4793
4794 if (ps == 0)
4795 ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
4796 if (ps == 0)
4797 return ((sh_parser_state_t *)NULL);
4798
4799 ps->parser_state = parser_state;
4800 ps->token_state = save_token_state ();
4801
4802 ps->input_line_terminator = shell_input_line_terminator;
4803 ps->eof_encountered = eof_encountered;
4804
4805 ps->current_command_line_count = current_command_line_count;
4806
4807#if defined (HISTORY)
4808 ps->remember_on_history = remember_on_history;
4809# if defined (BANG_HISTORY)
4810 ps->history_expansion_inhibited = history_expansion_inhibited;
4811# endif
4812#endif
4813
4814 ps->last_command_exit_value = last_command_exit_value;
4815#if defined (ARRAY_VARS)
4816 v = find_variable ("PIPESTATUS");
4817 if (v && array_p (v) && array_cell (v))
4818 ps->pipestatus = array_copy (array_cell (v));
4819 else
4820 ps->pipestatus = (ARRAY *)NULL;
4821#endif
4822
4823 ps->last_shell_builtin = last_shell_builtin;
4824 ps->this_shell_builtin = this_shell_builtin;
4825
4826 ps->expand_aliases = expand_aliases;
4827 ps->echo_input_at_read = echo_input_at_read;
4828
4829 return (ps);
4830}
4831
4832void
4833restore_parser_state (ps)
4834 sh_parser_state_t *ps;
4835{
4836#if defined (ARRAY_VARS)
4837 SHELL_VAR *v;
4838#endif
4839
4840 if (ps == 0)
4841 return;
4842
4843 parser_state = ps->parser_state;
4844 if (ps->token_state)
4845 {
4846 restore_token_state (ps->token_state);
4847 free (ps->token_state);
4848 }
4849
4850 shell_input_line_terminator = ps->input_line_terminator;
4851 eof_encountered = ps->eof_encountered;
4852
4853 current_command_line_count = ps->current_command_line_count;
4854
4855#if defined (HISTORY)
4856 remember_on_history = ps->remember_on_history;
4857# if defined (BANG_HISTORY)
4858 history_expansion_inhibited = ps->history_expansion_inhibited;
4859# endif
4860#endif
4861
4862 last_command_exit_value = ps->last_command_exit_value;
4863#if defined (ARRAY_VARS)
4864 v = find_variable ("PIPESTATUS");
4865 if (v && array_p (v) && array_cell (v))
4866 {
4867 array_dispose (array_cell (v));
4868 var_setarray (v, ps->pipestatus);
4869 }
4870#endif
4871
4872 last_shell_builtin = ps->last_shell_builtin;
4873 this_shell_builtin = ps->this_shell_builtin;
4874
4875 expand_aliases = ps->expand_aliases;
4876 echo_input_at_read = ps->echo_input_at_read;
4877}
4878
4879/************************************************
4880 * *
4881 * MULTIBYTE CHARACTER HANDLING *
4882 * *
4883 ************************************************/
4884
4885#if defined (HANDLE_MULTIBYTE)
4886static void
4887set_line_mbstate ()
4888{
4889 int i, previ, len, c;
4890 mbstate_t mbs, prevs;
4891 size_t mbclen;
4892
4893 if (shell_input_line == NULL)
4894 return;
4895 len = strlen (shell_input_line); /* XXX - shell_input_line_len ? */
4896 FREE (shell_input_line_property);
4897 shell_input_line_property = (char *)xmalloc (len + 1);
4898
4899 memset (&prevs, '\0', sizeof (mbstate_t));
4900 for (i = previ = 0; i < len; i++)
4901 {
4902 mbs = prevs;
4903
4904 c = shell_input_line[i];
4905 if (c == EOF)
4906 {
4907 int j;
4908 for (j = i; j < len; j++)
4909 shell_input_line_property[j] = 1;
4910 break;
4911 }
4912
4913 mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
4914 if (mbclen == 1 || mbclen == (size_t)-1)
4915 {
4916 mbclen = 1;
4917 previ = i + 1;
4918 }
4919 else if (mbclen == (size_t)-2)
4920 mbclen = 0;
4921 else if (mbclen > 1)
4922 {
4923 mbclen = 0;
4924 previ = i + 1;
4925 prevs = mbs;
4926 }
4927 else
4928 {
4929 /* XXX - what to do if mbrlen returns 0? (null wide character) */
4930 int j;
4931 for (j = i; j < len; j++)
4932 shell_input_line_property[j] = 1;
4933 break;
4934 }
4935
4936 shell_input_line_property[i] = mbclen;
4937 }
4938}
4939#endif /* HANDLE_MULTIBYTE */
Note: See TracBrowser for help on using the repository browser.