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