Bash-4.2 patch 12
[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   sh_input_line_state_t ls;
3846   int orig_ind, nc, sflags;
3847   char *ret, *s, *ep, *ostring;
3848
3849   /*yydebug = 1;*/
3850   orig_ind = *indp;
3851   ostring = string;
3852
3853 /*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/
3854   sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
3855   if (flags & SX_NOLONGJMP)
3856     sflags |= SEVAL_NOLONGJMP;
3857   save_parser_state (&ps);
3858   save_input_line_state (&ls);
3859
3860   /*(*/
3861   parser_state |= PST_CMDSUBST|PST_EOFTOKEN;    /* allow instant ')' */ /*(*/
3862   shell_eof_token = ')';
3863   parse_string (string, "command substitution", sflags, &ep);
3864
3865   restore_parser_state (&ps);
3866   reset_parser ();
3867   /* reset_parser clears shell_input_line and associated variables */
3868   restore_input_line_state (&ls);
3869   if (interactive)
3870     token_to_read = 0;
3871
3872   /* Need to find how many characters parse_and_execute consumed, update
3873      *indp, if flags != 0, copy the portion of the string parsed into RET
3874      and return it.  If flags & 1 (EX_NOALLOC) we can return NULL. */
3875
3876   /*(*/
3877   if (ep[-1] != ')')
3878     {
3879 #if DEBUG
3880       if (ep[-1] != '\n')
3881         itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
3882 #endif
3883       while (ep > ostring && ep[-1] == '\n') ep--;
3884     }
3885
3886   nc = ep - ostring;
3887   *indp = ep - base - 1;
3888
3889   /*(*/
3890 #if DEBUG
3891   if (base[*indp] != ')')
3892     itrace("xparse_dolparen:%d: base[%d] != RPAREN (%d), base = `%s'", line_number, *indp, base[*indp], base);
3893 #endif
3894
3895   if (flags & SX_NOALLOC) 
3896     return (char *)NULL;
3897
3898   if (nc == 0)
3899     {
3900       ret = xmalloc (1);
3901       ret[0] = '\0';
3902     }
3903   else
3904     ret = substring (ostring, 0, nc - 1);
3905
3906   return ret;
3907 }
3908
3909 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
3910 /* Parse a double-paren construct.  It can be either an arithmetic
3911    command, an arithmetic `for' command, or a nested subshell.  Returns
3912    the parsed token, -1 on error, or -2 if we didn't do anything and
3913    should just go on. */
3914 static int
3915 parse_dparen (c)
3916      int c;
3917 {
3918   int cmdtyp, sline;
3919   char *wval;
3920   WORD_DESC *wd;
3921
3922 #if defined (ARITH_FOR_COMMAND)
3923   if (last_read_token == FOR)
3924     {
3925       arith_for_lineno = line_number;
3926       cmdtyp = parse_arith_cmd (&wval, 0);
3927       if (cmdtyp == 1)
3928         {
3929           wd = alloc_word_desc ();
3930           wd->word = wval;
3931           yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
3932           return (ARITH_FOR_EXPRS);
3933         }
3934       else
3935         return -1;              /* ERROR */
3936     }
3937 #endif
3938
3939 #if defined (DPAREN_ARITHMETIC)
3940   if (reserved_word_acceptable (last_read_token))
3941     {
3942       sline = line_number;
3943
3944       cmdtyp = parse_arith_cmd (&wval, 0);
3945       if (cmdtyp == 1)  /* arithmetic command */
3946         {
3947           wd = alloc_word_desc ();
3948           wd->word = wval;
3949           wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
3950           yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
3951           return (ARITH_CMD);
3952         }
3953       else if (cmdtyp == 0)     /* nested subshell */
3954         {
3955           push_string (wval, 0, (alias_t *)NULL);
3956           if ((parser_state & PST_CASEPAT) == 0)
3957             parser_state |= PST_SUBSHELL;
3958           return (c);
3959         }
3960       else                      /* ERROR */
3961         return -1;
3962     }
3963 #endif
3964
3965   return -2;                    /* XXX */
3966 }
3967
3968 /* We've seen a `(('.  Look for the matching `))'.  If we get it, return 1.
3969    If not, assume it's a nested subshell for backwards compatibility and
3970    return 0.  In any case, put the characters we've consumed into a locally-
3971    allocated buffer and make *ep point to that buffer.  Return -1 on an
3972    error, for example EOF. */
3973 static int
3974 parse_arith_cmd (ep, adddq)
3975      char **ep;
3976      int adddq;
3977 {
3978   int exp_lineno, rval, c;
3979   char *ttok, *tokstr;
3980   int ttoklen;
3981
3982   exp_lineno = line_number;
3983   ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
3984   rval = 1;
3985   if (ttok == &matched_pair_error)
3986     return -1;
3987   /* Check that the next character is the closing right paren.  If
3988      not, this is a syntax error. ( */
3989   c = shell_getc (0);
3990   if MBTEST(c != ')')
3991     rval = 0;
3992
3993   tokstr = (char *)xmalloc (ttoklen + 4);
3994
3995   /* if ADDDQ != 0 then (( ... )) -> "..." */
3996   if (rval == 1 && adddq)       /* arith cmd, add double quotes */
3997     {
3998       tokstr[0] = '"';
3999       strncpy (tokstr + 1, ttok, ttoklen - 1);
4000       tokstr[ttoklen] = '"';
4001       tokstr[ttoklen+1] = '\0';
4002     }
4003   else if (rval == 1)           /* arith cmd, don't add double quotes */
4004     {
4005       strncpy (tokstr, ttok, ttoklen - 1);
4006       tokstr[ttoklen-1] = '\0';
4007     }
4008   else                          /* nested subshell */
4009     {
4010       tokstr[0] = '(';
4011       strncpy (tokstr + 1, ttok, ttoklen - 1);
4012       tokstr[ttoklen] = ')';
4013       tokstr[ttoklen+1] = c;
4014       tokstr[ttoklen+2] = '\0';
4015     }
4016
4017   *ep = tokstr;
4018   FREE (ttok);
4019   return rval;
4020 }
4021 #endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
4022
4023 #if defined (COND_COMMAND)
4024 static void
4025 cond_error ()
4026 {
4027   char *etext;
4028
4029   if (EOF_Reached && cond_token != COND_ERROR)          /* [[ */
4030     parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
4031   else if (cond_token != COND_ERROR)
4032     {
4033       if (etext = error_token_from_token (cond_token))
4034         {
4035           parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
4036           free (etext);
4037         }
4038       else
4039         parser_error (cond_lineno, _("syntax error in conditional expression"));
4040     }
4041 }
4042
4043 static COND_COM *
4044 cond_expr ()
4045 {
4046   return (cond_or ());  
4047 }
4048
4049 static COND_COM *
4050 cond_or ()
4051 {
4052   COND_COM *l, *r;
4053
4054   l = cond_and ();
4055   if (cond_token == OR_OR)
4056     {
4057       r = cond_or ();
4058       l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
4059     }
4060   return l;
4061 }
4062
4063 static COND_COM *
4064 cond_and ()
4065 {
4066   COND_COM *l, *r;
4067
4068   l = cond_term ();
4069   if (cond_token == AND_AND)
4070     {
4071       r = cond_and ();
4072       l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
4073     }
4074   return l;
4075 }
4076
4077 static int
4078 cond_skip_newlines ()
4079 {
4080   while ((cond_token = read_token (READ)) == '\n')
4081     {
4082       if (SHOULD_PROMPT ())
4083         prompt_again ();
4084     }
4085   return (cond_token);
4086 }
4087
4088 #define COND_RETURN_ERROR() \
4089   do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
4090
4091 static COND_COM *
4092 cond_term ()
4093 {
4094   WORD_DESC *op;
4095   COND_COM *term, *tleft, *tright;
4096   int tok, lineno;
4097   char *etext;
4098
4099   /* Read a token.  It can be a left paren, a `!', a unary operator, or a
4100      word that should be the first argument of a binary operator.  Start by
4101      skipping newlines, since this is a compound command. */
4102   tok = cond_skip_newlines ();
4103   lineno = line_number;
4104   if (tok == COND_END)
4105     {
4106       COND_RETURN_ERROR ();
4107     }
4108   else if (tok == '(')
4109     {
4110       term = cond_expr ();
4111       if (cond_token != ')')
4112         {
4113           if (term)
4114             dispose_cond_node (term);           /* ( */
4115           if (etext = error_token_from_token (cond_token))
4116             {
4117               parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
4118               free (etext);
4119             }
4120           else
4121             parser_error (lineno, _("expected `)'"));
4122           COND_RETURN_ERROR ();
4123         }
4124       term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
4125       (void)cond_skip_newlines ();
4126     }
4127   else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
4128     {
4129       if (tok == WORD)
4130         dispose_word (yylval.word);     /* not needed */
4131       term = cond_term ();
4132       if (term)
4133         term->flags |= CMD_INVERT_RETURN;
4134     }
4135   else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
4136     {
4137       op = yylval.word;
4138       tok = read_token (READ);
4139       if (tok == WORD)
4140         {
4141           tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4142           term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
4143         }
4144       else
4145         {
4146           dispose_word (op);
4147           if (etext = error_token_from_token (tok))
4148             {
4149               parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
4150               free (etext);
4151             }
4152           else
4153             parser_error (line_number, _("unexpected argument to conditional unary operator"));
4154           COND_RETURN_ERROR ();
4155         }
4156
4157       (void)cond_skip_newlines ();
4158     }
4159   else if (tok == WORD)         /* left argument to binary operator */
4160     {
4161       /* lhs */
4162       tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4163
4164       /* binop */
4165       tok = read_token (READ);
4166       if (tok == WORD && test_binop (yylval.word->word))
4167         {
4168           op = yylval.word;
4169           if (op->word[0] == '=' && (op->word[1] == '\0' || (op->word[1] == '=' && op->word[2] == '\0')))
4170             parser_state |= PST_EXTPAT;
4171           else if (op->word[0] == '!' && op->word[1] == '=' && op->word[2] == '\0')
4172             parser_state |= PST_EXTPAT;
4173         }
4174 #if defined (COND_REGEXP)
4175       else if (tok == WORD && STREQ (yylval.word->word, "=~"))
4176         {
4177           op = yylval.word;
4178           parser_state |= PST_REGEXP;
4179         }
4180 #endif
4181       else if (tok == '<' || tok == '>')
4182         op = make_word_from_token (tok);  /* ( */
4183       /* There should be a check before blindly accepting the `)' that we have
4184          seen the opening `('. */
4185       else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
4186         {
4187           /* Special case.  [[ x ]] is equivalent to [[ -n x ]], just like
4188              the test command.  Similarly for [[ x && expr ]] or
4189              [[ x || expr ]] or [[ (x) ]]. */
4190           op = make_word ("-n");
4191           term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
4192           cond_token = tok;
4193           return (term);
4194         }
4195       else
4196         {
4197           if (etext = error_token_from_token (tok))
4198             {
4199               parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
4200               free (etext);
4201             }
4202           else
4203             parser_error (line_number, _("conditional binary operator expected"));
4204           dispose_cond_node (tleft);
4205           COND_RETURN_ERROR ();
4206         }
4207
4208       /* rhs */
4209       if (parser_state & PST_EXTPAT)
4210         extended_glob = 1;
4211       tok = read_token (READ);
4212       if (parser_state & PST_EXTPAT)
4213         extended_glob = global_extglob;
4214       parser_state &= ~(PST_REGEXP|PST_EXTPAT);
4215
4216       if (tok == WORD)
4217         {
4218           tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4219           term = make_cond_node (COND_BINARY, op, tleft, tright);
4220         }
4221       else
4222         {
4223           if (etext = error_token_from_token (tok))
4224             {
4225               parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
4226               free (etext);
4227             }
4228           else
4229             parser_error (line_number, _("unexpected argument to conditional binary operator"));
4230           dispose_cond_node (tleft);
4231           dispose_word (op);
4232           COND_RETURN_ERROR ();
4233         }
4234
4235       (void)cond_skip_newlines ();
4236     }
4237   else
4238     {
4239       if (tok < 256)
4240         parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
4241       else if (etext = error_token_from_token (tok))
4242         {
4243           parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
4244           free (etext);
4245         }
4246       else
4247         parser_error (line_number, _("unexpected token %d in conditional command"), tok);
4248       COND_RETURN_ERROR ();
4249     }
4250   return (term);
4251 }      
4252
4253 /* This is kind of bogus -- we slip a mini recursive-descent parser in
4254    here to handle the conditional statement syntax. */
4255 static COMMAND *
4256 parse_cond_command ()
4257 {
4258   COND_COM *cexp;
4259
4260   global_extglob = extended_glob;
4261   cexp = cond_expr ();
4262   return (make_cond_command (cexp));
4263 }
4264 #endif
4265
4266 #if defined (ARRAY_VARS)
4267 /* When this is called, it's guaranteed that we don't care about anything
4268    in t beyond i.  We do save and restore the chars, though. */
4269 static int
4270 token_is_assignment (t, i)
4271      char *t;
4272      int i;
4273 {
4274   unsigned char c, c1;
4275   int r;
4276
4277   c = t[i]; c1 = t[i+1];
4278   t[i] = '='; t[i+1] = '\0';
4279   r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
4280   t[i] = c; t[i+1] = c1;
4281   return r;
4282 }
4283
4284 /* XXX - possible changes here for `+=' */
4285 static int
4286 token_is_ident (t, i)
4287      char *t;
4288      int i;
4289 {
4290   unsigned char c;
4291   int r;
4292
4293   c = t[i];
4294   t[i] = '\0';
4295   r = legal_identifier (t);
4296   t[i] = c;
4297   return r;
4298 }
4299 #endif
4300
4301 static int
4302 read_token_word (character)
4303      int character;
4304 {
4305   /* The value for YYLVAL when a WORD is read. */
4306   WORD_DESC *the_word;
4307
4308   /* Index into the token that we are building. */
4309   int token_index;
4310
4311   /* ALL_DIGITS becomes zero when we see a non-digit. */
4312   int all_digit_token;
4313
4314   /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
4315   int dollar_present;
4316
4317   /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
4318      assignment. */
4319   int compound_assignment;
4320
4321   /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
4322   int quoted;
4323
4324   /* Non-zero means to ignore the value of the next character, and just
4325      to add it no matter what. */
4326  int pass_next_character;
4327
4328   /* The current delimiting character. */
4329   int cd;
4330   int result, peek_char;
4331   char *ttok, *ttrans;
4332   int ttoklen, ttranslen;
4333   intmax_t lvalue;
4334
4335   if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
4336     token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
4337
4338   token_index = 0;
4339   all_digit_token = DIGIT (character);
4340   dollar_present = quoted = pass_next_character = compound_assignment = 0;
4341
4342   for (;;)
4343     {
4344       if (character == EOF)
4345         goto got_token;
4346
4347       if (pass_next_character)
4348         {
4349           pass_next_character = 0;
4350           goto got_escaped_character;
4351         }
4352
4353       cd = current_delimiter (dstack);
4354
4355       /* Handle backslashes.  Quote lots of things when not inside of
4356          double-quotes, quote some things inside of double-quotes. */
4357       if MBTEST(character == '\\')
4358         {
4359           peek_char = shell_getc (0);
4360
4361           /* Backslash-newline is ignored in all cases except
4362              when quoted with single quotes. */
4363           if (peek_char == '\n')
4364             {
4365               character = '\n';
4366               goto next_character;
4367             }
4368           else
4369             {
4370               shell_ungetc (peek_char);
4371
4372               /* If the next character is to be quoted, note it now. */
4373               if (cd == 0 || cd == '`' ||
4374                   (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
4375                 pass_next_character++;
4376
4377               quoted = 1;
4378               goto got_character;
4379             }
4380         }
4381
4382       /* Parse a matched pair of quote characters. */
4383       if MBTEST(shellquote (character))
4384         {
4385           push_delimiter (dstack, character);
4386           ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
4387           pop_delimiter (dstack);
4388           if (ttok == &matched_pair_error)
4389             return -1;          /* Bail immediately. */
4390           RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4391                                   token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
4392           token[token_index++] = character;
4393           strcpy (token + token_index, ttok);
4394           token_index += ttoklen;
4395           all_digit_token = 0;
4396           quoted = 1;
4397           dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
4398           FREE (ttok);
4399           goto next_character;
4400         }
4401
4402 #ifdef COND_REGEXP
4403       /* When parsing a regexp as a single word inside a conditional command,
4404          we need to special-case characters special to both the shell and
4405          regular expressions.  Right now, that is only '(' and '|'. */ /*)*/
4406       if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|'))          /*)*/
4407         {
4408           if (character == '|')
4409             goto got_character;
4410
4411           push_delimiter (dstack, character);
4412           ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
4413           pop_delimiter (dstack);
4414           if (ttok == &matched_pair_error)
4415             return -1;          /* Bail immediately. */
4416           RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4417                                   token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
4418           token[token_index++] = character;
4419           strcpy (token + token_index, ttok);
4420           token_index += ttoklen;
4421           FREE (ttok);
4422           dollar_present = all_digit_token = 0;
4423           goto next_character;
4424         }
4425 #endif /* COND_REGEXP */
4426
4427 #ifdef EXTENDED_GLOB
4428       /* Parse a ksh-style extended pattern matching specification. */
4429       if MBTEST(extended_glob && PATTERN_CHAR (character))
4430         {
4431           peek_char = shell_getc (1);
4432           if MBTEST(peek_char == '(')           /* ) */
4433             {
4434               push_delimiter (dstack, peek_char);
4435               ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
4436               pop_delimiter (dstack);
4437               if (ttok == &matched_pair_error)
4438                 return -1;              /* Bail immediately. */
4439               RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4440                                       token_buffer_size,
4441                                       TOKEN_DEFAULT_GROW_SIZE);
4442               token[token_index++] = character;
4443               token[token_index++] = peek_char;
4444               strcpy (token + token_index, ttok);
4445               token_index += ttoklen;
4446               FREE (ttok);
4447               dollar_present = all_digit_token = 0;
4448               goto next_character;
4449             }
4450           else
4451             shell_ungetc (peek_char);
4452         }
4453 #endif /* EXTENDED_GLOB */
4454
4455       /* If the delimiter character is not single quote, parse some of
4456          the shell expansions that must be read as a single word. */
4457       if (shellexp (character))
4458         {
4459           peek_char = shell_getc (1);
4460           /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
4461           if MBTEST(peek_char == '(' || \
4462                 ((peek_char == '{' || peek_char == '[') && character == '$'))   /* ) ] } */
4463             {
4464               if (peek_char == '{')             /* } */
4465                 ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE|P_DOLBRACE);
4466               else if (peek_char == '(')                /* ) */
4467                 {
4468                   /* XXX - push and pop the `(' as a delimiter for use by
4469                      the command-oriented-history code.  This way newlines
4470                      appearing in the $(...) string get added to the
4471                      history literally rather than causing a possibly-
4472                      incorrect `;' to be added. ) */
4473                   push_delimiter (dstack, peek_char);
4474                   ttok = parse_comsub (cd, '(', ')', &ttoklen, P_COMMAND);
4475                   pop_delimiter (dstack);
4476                 }
4477               else
4478                 ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
4479               if (ttok == &matched_pair_error)
4480                 return -1;              /* Bail immediately. */
4481               RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4482                                       token_buffer_size,
4483                                       TOKEN_DEFAULT_GROW_SIZE);
4484               token[token_index++] = character;
4485               token[token_index++] = peek_char;
4486               strcpy (token + token_index, ttok);
4487               token_index += ttoklen;
4488               FREE (ttok);
4489               dollar_present = 1;
4490               all_digit_token = 0;
4491               goto next_character;
4492             }
4493           /* This handles $'...' and $"..." new-style quoted strings. */
4494           else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
4495             {
4496               int first_line;
4497
4498               first_line = line_number;
4499               push_delimiter (dstack, peek_char);
4500               ttok = parse_matched_pair (peek_char, peek_char, peek_char,
4501                                          &ttoklen,
4502                                          (peek_char == '\'') ? P_ALLOWESC : 0);
4503               pop_delimiter (dstack);
4504               if (ttok == &matched_pair_error)
4505                 return -1;
4506               if (peek_char == '\'')
4507                 {
4508                   ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
4509                   free (ttok);
4510
4511                   /* Insert the single quotes and correctly quote any
4512                      embedded single quotes (allowed because P_ALLOWESC was
4513                      passed to parse_matched_pair). */
4514                   ttok = sh_single_quote (ttrans);
4515                   free (ttrans);
4516                   ttranslen = strlen (ttok);
4517                   ttrans = ttok;
4518                 }
4519               else
4520                 {
4521                   /* Try to locale-expand the converted string. */
4522                   ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
4523                   free (ttok);
4524
4525                   /* Add the double quotes back */
4526                   ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
4527                   free (ttrans);
4528                   ttranslen += 2;
4529                   ttrans = ttok;
4530                 }
4531
4532               RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2,
4533                                       token_buffer_size,
4534                                       TOKEN_DEFAULT_GROW_SIZE);
4535               strcpy (token + token_index, ttrans);
4536               token_index += ttranslen;
4537               FREE (ttrans);
4538               quoted = 1;
4539               all_digit_token = 0;
4540               goto next_character;
4541             }
4542           /* This could eventually be extended to recognize all of the
4543              shell's single-character parameter expansions, and set flags.*/
4544           else if MBTEST(character == '$' && peek_char == '$')
4545             {
4546               ttok = (char *)xmalloc (3);
4547               ttok[0] = ttok[1] = '$';
4548               ttok[2] = '\0';
4549               RESIZE_MALLOCED_BUFFER (token, token_index, 3,
4550                                       token_buffer_size,
4551                                       TOKEN_DEFAULT_GROW_SIZE);
4552               strcpy (token + token_index, ttok);
4553               token_index += 2;
4554               dollar_present = 1;
4555               all_digit_token = 0;
4556               FREE (ttok);
4557               goto next_character;
4558             }
4559           else
4560             shell_ungetc (peek_char);
4561         }
4562
4563 #if defined (ARRAY_VARS)
4564       /* Identify possible array subscript assignment; match [...].  If
4565          parser_state&PST_COMPASSIGN, we need to parse [sub]=words treating
4566          `sub' as if it were enclosed in double quotes. */
4567       else if MBTEST(character == '[' &&                /* ] */
4568                      ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
4569                       (token_index == 0 && (parser_state&PST_COMPASSIGN))))
4570         {
4571           ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
4572           if (ttok == &matched_pair_error)
4573             return -1;          /* Bail immediately. */
4574           RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4575                                   token_buffer_size,
4576                                   TOKEN_DEFAULT_GROW_SIZE);
4577           token[token_index++] = character;
4578           strcpy (token + token_index, ttok);
4579           token_index += ttoklen;
4580           FREE (ttok);
4581           all_digit_token = 0;
4582           goto next_character;
4583         }
4584       /* Identify possible compound array variable assignment. */
4585       else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
4586         {
4587           peek_char = shell_getc (1);
4588           if MBTEST(peek_char == '(')           /* ) */
4589             {
4590               ttok = parse_compound_assignment (&ttoklen);
4591
4592               RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
4593                                       token_buffer_size,
4594                                       TOKEN_DEFAULT_GROW_SIZE);
4595
4596               token[token_index++] = '=';
4597               token[token_index++] = '(';
4598               if (ttok)
4599                 {
4600                   strcpy (token + token_index, ttok);
4601                   token_index += ttoklen;
4602                 }
4603               token[token_index++] = ')';
4604               FREE (ttok);
4605               all_digit_token = 0;
4606               compound_assignment = 1;
4607 #if 1
4608               goto next_character;
4609 #else
4610               goto got_token;           /* ksh93 seems to do this */
4611 #endif
4612             }
4613           else
4614             shell_ungetc (peek_char);
4615         }
4616 #endif
4617
4618       /* When not parsing a multi-character word construct, shell meta-
4619          characters break words. */
4620       if MBTEST(shellbreak (character))
4621         {
4622           shell_ungetc (character);
4623           goto got_token;
4624         }
4625
4626     got_character:
4627
4628       if (character == CTLESC || character == CTLNUL)
4629         token[token_index++] = CTLESC;
4630
4631     got_escaped_character:
4632
4633       all_digit_token &= DIGIT (character);
4634       dollar_present |= character == '$';
4635
4636       token[token_index++] = character;
4637
4638       RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
4639                               TOKEN_DEFAULT_GROW_SIZE);
4640
4641     next_character:
4642       if (character == '\n' && SHOULD_PROMPT ())
4643         prompt_again ();
4644
4645       /* We want to remove quoted newlines (that is, a \<newline> pair)
4646          unless we are within single quotes or pass_next_character is
4647          set (the shell equivalent of literal-next). */
4648       cd = current_delimiter (dstack);
4649       character = shell_getc (cd != '\'' && pass_next_character == 0);
4650     }   /* end for (;;) */
4651
4652 got_token:
4653
4654   token[token_index] = '\0';
4655
4656   /* Check to see what thing we should return.  If the last_read_token
4657      is a `<', or a `&', or the character which ended this token is
4658      a '>' or '<', then, and ONLY then, is this input token a NUMBER.
4659      Otherwise, it is just a word, and should be returned as such. */
4660   if MBTEST(all_digit_token && (character == '<' || character == '>' || \
4661                     last_read_token == LESS_AND || \
4662                     last_read_token == GREATER_AND))
4663       {
4664         if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
4665           yylval.number = lvalue;
4666         else
4667           yylval.number = -1;
4668         return (NUMBER);
4669       }
4670
4671   /* Check for special case tokens. */
4672   result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
4673   if (result >= 0)
4674     return result;
4675
4676 #if defined (ALIAS)
4677   /* Posix.2 does not allow reserved words to be aliased, so check for all
4678      of them, including special cases, before expanding the current token
4679      as an alias. */
4680   if MBTEST(posixly_correct)
4681     CHECK_FOR_RESERVED_WORD (token);
4682
4683   /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
4684      inhibits alias expansion. */
4685   if (expand_aliases && quoted == 0)
4686     {
4687       result = alias_expand_token (token);
4688       if (result == RE_READ_TOKEN)
4689         return (RE_READ_TOKEN);
4690       else if (result == NO_EXPANSION)
4691         parser_state &= ~PST_ALEXPNEXT;
4692     }
4693
4694   /* If not in Posix.2 mode, check for reserved words after alias
4695      expansion. */
4696   if MBTEST(posixly_correct == 0)
4697 #endif
4698     CHECK_FOR_RESERVED_WORD (token);
4699
4700   the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
4701   the_word->word = (char *)xmalloc (1 + token_index);
4702   the_word->flags = 0;
4703   strcpy (the_word->word, token);
4704   if (dollar_present)
4705     the_word->flags |= W_HASDOLLAR;
4706   if (quoted)
4707     the_word->flags |= W_QUOTED;                /*(*/
4708   if (compound_assignment && token[token_index-1] == ')')
4709     the_word->flags |= W_COMPASSIGN;
4710   /* A word is an assignment if it appears at the beginning of a
4711      simple command, or after another assignment word.  This is
4712      context-dependent, so it cannot be handled in the grammar. */
4713   if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
4714     {
4715       the_word->flags |= W_ASSIGNMENT;
4716       /* Don't perform word splitting on assignment statements. */
4717       if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
4718         the_word->flags |= W_NOSPLIT;
4719     }
4720
4721   if (command_token_position (last_read_token))
4722     {
4723       struct builtin *b;
4724       b = builtin_address_internal (token, 0);
4725       if (b && (b->flags & ASSIGNMENT_BUILTIN))
4726         parser_state |= PST_ASSIGNOK;
4727       else if (STREQ (token, "eval") || STREQ (token, "let"))
4728         parser_state |= PST_ASSIGNOK;
4729     }
4730
4731   yylval.word = the_word;
4732
4733   if (token[0] == '{' && token[token_index-1] == '}' &&
4734       (character == '<' || character == '>'))
4735     {
4736       /* can use token; already copied to the_word */
4737       token[token_index-1] = '\0';
4738       if (legal_identifier (token+1))
4739         {
4740           strcpy (the_word->word, token+1);
4741 /*itrace("read_token_word: returning REDIR_WORD for %s", the_word->word);*/
4742           return (REDIR_WORD);
4743         }
4744     }
4745
4746   result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
4747                 ? ASSIGNMENT_WORD : WORD;
4748
4749   switch (last_read_token)
4750     {
4751     case FUNCTION:
4752       parser_state |= PST_ALLOWOPNBRC;
4753       function_dstart = line_number;
4754       break;
4755     case CASE:
4756     case SELECT:
4757     case FOR:
4758       if (word_top < MAX_CASE_NEST)
4759         word_top++;
4760       word_lineno[word_top] = line_number;
4761       break;
4762     }
4763
4764   return (result);
4765 }
4766
4767 /* Return 1 if TOKSYM is a token that after being read would allow
4768    a reserved word to be seen, else 0. */
4769 static int
4770 reserved_word_acceptable (toksym)
4771      int toksym;
4772 {
4773   switch (toksym)
4774     {
4775     case '\n':
4776     case ';':
4777     case '(':
4778     case ')':
4779     case '|':
4780     case '&':
4781     case '{':
4782     case '}':           /* XXX */
4783     case AND_AND:
4784     case BANG:
4785     case BAR_AND:
4786     case DO:
4787     case DONE:
4788     case ELIF:
4789     case ELSE:
4790     case ESAC:
4791     case FI:
4792     case IF:
4793     case OR_OR:
4794     case SEMI_SEMI:
4795     case SEMI_AND:
4796     case SEMI_SEMI_AND:
4797     case THEN:
4798     case TIME:
4799     case TIMEOPT:
4800     case TIMEIGN:
4801     case COPROC:
4802     case UNTIL:
4803     case WHILE:
4804     case 0:
4805       return 1;
4806     default:
4807 #if defined (COPROCESS_SUPPORT)
4808       if (last_read_token == WORD && token_before_that == COPROC)
4809         return 1;
4810 #endif
4811       if (last_read_token == WORD && token_before_that == FUNCTION)
4812         return 1;
4813       return 0;
4814     }
4815 }
4816     
4817 /* Return the index of TOKEN in the alist of reserved words, or -1 if
4818    TOKEN is not a shell reserved word. */
4819 int
4820 find_reserved_word (tokstr)
4821      char *tokstr;
4822 {
4823   int i;
4824   for (i = 0; word_token_alist[i].word; i++)
4825     if (STREQ (tokstr, word_token_alist[i].word))
4826       return i;
4827   return -1;
4828 }
4829
4830 #if 0
4831 #if defined (READLINE)
4832 /* Called after each time readline is called.  This insures that whatever
4833    the new prompt string is gets propagated to readline's local prompt
4834    variable. */
4835 static void
4836 reset_readline_prompt ()
4837 {
4838   char *temp_prompt;
4839
4840   if (prompt_string_pointer)
4841     {
4842       temp_prompt = (*prompt_string_pointer)
4843                         ? decode_prompt_string (*prompt_string_pointer)
4844                         : (char *)NULL;
4845
4846       if (temp_prompt == 0)
4847         {
4848           temp_prompt = (char *)xmalloc (1);
4849           temp_prompt[0] = '\0';
4850         }
4851
4852       FREE (current_readline_prompt);
4853       current_readline_prompt = temp_prompt;
4854     }
4855 }
4856 #endif /* READLINE */
4857 #endif /* 0 */
4858
4859 #if defined (HISTORY)
4860 /* A list of tokens which can be followed by newlines, but not by
4861    semi-colons.  When concatenating multiple lines of history, the
4862    newline separator for such tokens is replaced with a space. */
4863 static const int no_semi_successors[] = {
4864   '\n', '{', '(', ')', ';', '&', '|',
4865   CASE, DO, ELSE, IF, SEMI_SEMI, SEMI_AND, SEMI_SEMI_AND, THEN, UNTIL,
4866   WHILE, AND_AND, OR_OR, IN,
4867   0
4868 };
4869
4870 /* If we are not within a delimited expression, try to be smart
4871    about which separators can be semi-colons and which must be
4872    newlines.  Returns the string that should be added into the
4873    history entry.  LINE is the line we're about to add; it helps
4874    make some more intelligent decisions in certain cases. */
4875 char *
4876 history_delimiting_chars (line)
4877      const char *line;
4878 {
4879   static int last_was_heredoc = 0;      /* was the last entry the start of a here document? */
4880   register int i;
4881
4882   if ((parser_state & PST_HEREDOC) == 0)
4883     last_was_heredoc = 0;
4884
4885   if (dstack.delimiter_depth != 0)
4886     return ("\n");
4887
4888   /* We look for current_command_line_count == 2 because we are looking to
4889      add the first line of the body of the here document (the second line
4890      of the command).  We also keep LAST_WAS_HEREDOC as a private sentinel
4891      variable to note when we think we added the first line of a here doc
4892      (the one with a "<<" somewhere in it) */
4893   if (parser_state & PST_HEREDOC)
4894     {
4895       if (last_was_heredoc)
4896         {
4897           last_was_heredoc = 0;
4898           return "\n";
4899         }
4900       return (current_command_line_count == 2 ? "\n" : "");
4901     }
4902
4903   /* First, handle some special cases. */
4904   /*(*/
4905   /* If we just read `()', assume it's a function definition, and don't
4906      add a semicolon.  If the token before the `)' was not `(', and we're
4907      not in the midst of parsing a case statement, assume it's a
4908      parenthesized command and add the semicolon. */
4909   /*)(*/
4910   if (token_before_that == ')')
4911     {
4912       if (two_tokens_ago == '(')        /*)*/   /* function def */
4913         return " ";
4914       /* This does not work for subshells inside case statement
4915          command lists.  It's a suboptimal solution. */
4916       else if (parser_state & PST_CASESTMT)     /* case statement pattern */
4917         return " ";
4918       else      
4919         return "; ";                            /* (...) subshell */
4920     }
4921   else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
4922     return " ";         /* function def using `function name' without `()' */
4923
4924   /* If we're not in a here document, but we think we're about to parse one,
4925      and we would otherwise return a `;', return a newline to delimit the
4926      line with the here-doc delimiter */
4927   else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
4928     {
4929       last_was_heredoc = 1;
4930       return "\n";
4931     }
4932
4933   else if (token_before_that == WORD && two_tokens_ago == FOR)
4934     {
4935       /* Tricky.  `for i\nin ...' should not have a semicolon, but
4936          `for i\ndo ...' should.  We do what we can. */
4937       for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
4938         ;
4939       if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
4940         return " ";
4941       return ";";
4942     }
4943   else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
4944     return " ";
4945
4946   for (i = 0; no_semi_successors[i]; i++)
4947     {
4948       if (token_before_that == no_semi_successors[i])
4949         return (" ");
4950     }
4951
4952   return ("; ");
4953 }
4954 #endif /* HISTORY */
4955
4956 /* Issue a prompt, or prepare to issue a prompt when the next character
4957    is read. */
4958 static void
4959 prompt_again ()
4960 {
4961   char *temp_prompt;
4962
4963   if (interactive == 0 || expanding_alias ())   /* XXX */
4964     return;
4965
4966   ps1_prompt = get_string_value ("PS1");
4967   ps2_prompt = get_string_value ("PS2");
4968
4969   if (!prompt_string_pointer)
4970     prompt_string_pointer = &ps1_prompt;
4971
4972   temp_prompt = *prompt_string_pointer
4973                         ? decode_prompt_string (*prompt_string_pointer)
4974                         : (char *)NULL;
4975
4976   if (temp_prompt == 0)
4977     {
4978       temp_prompt = (char *)xmalloc (1);
4979       temp_prompt[0] = '\0';
4980     }
4981
4982   current_prompt_string = *prompt_string_pointer;
4983   prompt_string_pointer = &ps2_prompt;
4984
4985 #if defined (READLINE)
4986   if (!no_line_editing)
4987     {
4988       FREE (current_readline_prompt);
4989       current_readline_prompt = temp_prompt;
4990     }
4991   else
4992 #endif  /* READLINE */
4993     {
4994       FREE (current_decoded_prompt);
4995       current_decoded_prompt = temp_prompt;
4996     }
4997 }
4998
4999 int
5000 get_current_prompt_level ()
5001 {
5002   return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
5003 }
5004
5005 void
5006 set_current_prompt_level (x)
5007      int x;
5008 {
5009   prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
5010   current_prompt_string = *prompt_string_pointer;
5011 }
5012       
5013 static void
5014 print_prompt ()
5015 {
5016   fprintf (stderr, "%s", current_decoded_prompt);
5017   fflush (stderr);
5018 }
5019
5020 /* Return a string which will be printed as a prompt.  The string
5021    may contain special characters which are decoded as follows:
5022
5023         \a      bell (ascii 07)
5024         \d      the date in Day Mon Date format
5025         \e      escape (ascii 033)
5026         \h      the hostname up to the first `.'
5027         \H      the hostname
5028         \j      the number of active jobs
5029         \l      the basename of the shell's tty device name
5030         \n      CRLF
5031         \r      CR
5032         \s      the name of the shell
5033         \t      the time in 24-hour hh:mm:ss format
5034         \T      the time in 12-hour hh:mm:ss format
5035         \@      the time in 12-hour hh:mm am/pm format
5036         \A      the time in 24-hour hh:mm format
5037         \D{fmt} the result of passing FMT to strftime(3)
5038         \u      your username
5039         \v      the version of bash (e.g., 2.00)
5040         \V      the release of bash, version + patchlevel (e.g., 2.00.0)
5041         \w      the current working directory
5042         \W      the last element of $PWD
5043         \!      the history number of this command
5044         \#      the command number of this command
5045         \$      a $ or a # if you are root
5046         \nnn    character code nnn in octal
5047         \\      a backslash
5048         \[      begin a sequence of non-printing chars
5049         \]      end a sequence of non-printing chars
5050 */
5051 #define PROMPT_GROWTH 48
5052 char *
5053 decode_prompt_string (string)
5054      char *string;
5055 {
5056   WORD_LIST *list;
5057   char *result, *t;
5058   struct dstack save_dstack;
5059   int last_exit_value, last_comsub_pid;
5060 #if defined (PROMPT_STRING_DECODE)
5061   int result_size, result_index;
5062   int c, n, i;
5063   char *temp, octal_string[4];
5064   struct tm *tm;  
5065   time_t the_time;
5066   char timebuf[128];
5067   char *timefmt;
5068
5069   result = (char *)xmalloc (result_size = PROMPT_GROWTH);
5070   result[result_index = 0] = 0;
5071   temp = (char *)NULL;
5072
5073   while (c = *string++)
5074     {
5075       if (posixly_correct && c == '!')
5076         {
5077           if (*string == '!')
5078             {
5079               temp = savestring ("!");
5080               goto add_string;
5081             }
5082           else
5083             {
5084 #if !defined (HISTORY)
5085                 temp = savestring ("1");
5086 #else /* HISTORY */
5087                 temp = itos (history_number ());
5088 #endif /* HISTORY */
5089                 string--;       /* add_string increments string again. */
5090                 goto add_string;
5091             }
5092         }
5093       if (c == '\\')
5094         {
5095           c = *string;
5096
5097           switch (c)
5098             {
5099             case '0':
5100             case '1':
5101             case '2':
5102             case '3':
5103             case '4':
5104             case '5':
5105             case '6':
5106             case '7':
5107               strncpy (octal_string, string, 3);
5108               octal_string[3] = '\0';
5109
5110               n = read_octal (octal_string);
5111               temp = (char *)xmalloc (3);
5112
5113               if (n == CTLESC || n == CTLNUL)
5114                 {
5115                   temp[0] = CTLESC;
5116                   temp[1] = n;
5117                   temp[2] = '\0';
5118                 }
5119               else if (n == -1)
5120                 {
5121                   temp[0] = '\\';
5122                   temp[1] = '\0';
5123                 }
5124               else
5125                 {
5126                   temp[0] = n;
5127                   temp[1] = '\0';
5128                 }
5129
5130               for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
5131                 string++;
5132
5133               c = 0;            /* tested at add_string: */
5134               goto add_string;
5135
5136             case 'd':
5137             case 't':
5138             case 'T':
5139             case '@':
5140             case 'A':
5141               /* Make the current time/date into a string. */
5142               (void) time (&the_time);
5143 #if defined (HAVE_TZSET)
5144               sv_tz ("TZ");             /* XXX -- just make sure */
5145 #endif
5146               tm = localtime (&the_time);
5147
5148               if (c == 'd')
5149                 n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
5150               else if (c == 't')
5151                 n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
5152               else if (c == 'T')
5153                 n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
5154               else if (c == '@')
5155                 n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
5156               else if (c == 'A')
5157                 n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
5158
5159               if (n == 0)
5160                 timebuf[0] = '\0';
5161               else
5162                 timebuf[sizeof(timebuf) - 1] = '\0';
5163
5164               temp = savestring (timebuf);
5165               goto add_string;
5166
5167             case 'D':           /* strftime format */
5168               if (string[1] != '{')             /* } */
5169                 goto not_escape;
5170
5171               (void) time (&the_time);
5172               tm = localtime (&the_time);
5173               string += 2;                      /* skip { */
5174               timefmt = xmalloc (strlen (string) + 3);
5175               for (t = timefmt; *string && *string != '}'; )
5176                 *t++ = *string++;
5177               *t = '\0';
5178               c = *string;      /* tested at add_string */
5179               if (timefmt[0] == '\0')
5180                 {
5181                   timefmt[0] = '%';
5182                   timefmt[1] = 'X';     /* locale-specific current time */
5183                   timefmt[2] = '\0';
5184                 }
5185               n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
5186               free (timefmt);
5187
5188               if (n == 0)
5189                 timebuf[0] = '\0';
5190               else
5191                 timebuf[sizeof(timebuf) - 1] = '\0';
5192
5193               if (promptvars || posixly_correct)
5194                 /* Make sure that expand_prompt_string is called with a
5195                    second argument of Q_DOUBLE_QUOTES if we use this
5196                    function here. */
5197                 temp = sh_backslash_quote_for_double_quotes (timebuf);
5198               else
5199                 temp = savestring (timebuf);
5200               goto add_string;
5201               
5202             case 'n':
5203               temp = (char *)xmalloc (3);
5204               temp[0] = no_line_editing ? '\n' : '\r';
5205               temp[1] = no_line_editing ? '\0' : '\n';
5206               temp[2] = '\0';
5207               goto add_string;
5208
5209             case 's':
5210               temp = base_pathname (shell_name);
5211               temp = savestring (temp);
5212               goto add_string;
5213
5214             case 'v':
5215             case 'V':
5216               temp = (char *)xmalloc (16);
5217               if (c == 'v')
5218                 strcpy (temp, dist_version);
5219               else
5220                 sprintf (temp, "%s.%d", dist_version, patch_level);
5221               goto add_string;
5222
5223             case 'w':
5224             case 'W':
5225               {
5226                 /* Use the value of PWD because it is much more efficient. */
5227                 char t_string[PATH_MAX];
5228                 int tlen;
5229
5230                 temp = get_string_value ("PWD");
5231
5232                 if (temp == 0)
5233                   {
5234                     if (getcwd (t_string, sizeof(t_string)) == 0)
5235                       {
5236                         t_string[0] = '.';
5237                         tlen = 1;
5238                       }
5239                     else
5240                       tlen = strlen (t_string);
5241                   }
5242                 else
5243                   {
5244                     tlen = sizeof (t_string) - 1;
5245                     strncpy (t_string, temp, tlen);
5246                   }
5247                 t_string[tlen] = '\0';
5248
5249 #if defined (MACOSX)
5250                 /* Convert from "fs" format to "input" format */
5251                 temp = fnx_fromfs (t_string, strlen (t_string));
5252                 if (temp != t_string)
5253                   strcpy (t_string, temp);
5254 #endif
5255
5256 #define ROOT_PATH(x)    ((x)[0] == '/' && (x)[1] == 0)
5257 #define DOUBLE_SLASH_ROOT(x)    ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
5258                 /* Abbreviate \W as ~ if $PWD == $HOME */
5259                 if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
5260                   {
5261                     if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
5262                       {
5263                         t = strrchr (t_string, '/');
5264                         if (t)
5265                           memmove (t_string, t + 1, strlen (t));        /* strlen(t) to copy NULL */
5266                       }
5267                   }
5268 #undef ROOT_PATH
5269 #undef DOUBLE_SLASH_ROOT
5270                 else
5271                   /* polite_directory_format is guaranteed to return a string
5272                      no longer than PATH_MAX - 1 characters. */
5273                   strcpy (t_string, polite_directory_format (t_string));
5274
5275                 temp = trim_pathname (t_string, PATH_MAX - 1);
5276                 /* If we're going to be expanding the prompt string later,
5277                    quote the directory name. */
5278                 if (promptvars || posixly_correct)
5279                   /* Make sure that expand_prompt_string is called with a
5280                      second argument of Q_DOUBLE_QUOTES if we use this
5281                      function here. */
5282                   temp = sh_backslash_quote_for_double_quotes (t_string);
5283                 else
5284                   temp = savestring (t_string);
5285
5286                 goto add_string;
5287               }
5288
5289             case 'u':
5290               if (current_user.user_name == 0)
5291                 get_current_user_info ();
5292               temp = savestring (current_user.user_name);
5293               goto add_string;
5294
5295             case 'h':
5296             case 'H':
5297               temp = savestring (current_host_name);
5298               if (c == 'h' && (t = (char *)strchr (temp, '.')))
5299                 *t = '\0';
5300               goto add_string;
5301
5302             case '#':
5303               temp = itos (current_command_number);
5304               goto add_string;
5305
5306             case '!':
5307 #if !defined (HISTORY)
5308               temp = savestring ("1");
5309 #else /* HISTORY */
5310               temp = itos (history_number ());
5311 #endif /* HISTORY */
5312               goto add_string;
5313
5314             case '$':
5315               t = temp = (char *)xmalloc (3);
5316               if ((promptvars || posixly_correct) && (current_user.euid != 0))
5317                 *t++ = '\\';
5318               *t++ = current_user.euid == 0 ? '#' : '$';
5319               *t = '\0';
5320               goto add_string;
5321
5322             case 'j':
5323               temp = itos (count_all_jobs ());
5324               goto add_string;
5325
5326             case 'l':
5327 #if defined (HAVE_TTYNAME)
5328               temp = (char *)ttyname (fileno (stdin));
5329               t = temp ? base_pathname (temp) : "tty";
5330               temp = savestring (t);
5331 #else
5332               temp = savestring ("tty");
5333 #endif /* !HAVE_TTYNAME */
5334               goto add_string;
5335
5336 #if defined (READLINE)
5337             case '[':
5338             case ']':
5339               if (no_line_editing)
5340                 {
5341                   string++;
5342                   break;
5343                 }
5344               temp = (char *)xmalloc (3);
5345               n = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
5346               i = 0;
5347               if (n == CTLESC || n == CTLNUL)
5348                 temp[i++] = CTLESC;
5349               temp[i++] = n;
5350               temp[i] = '\0';
5351               goto add_string;
5352 #endif /* READLINE */
5353
5354             case '\\':
5355             case 'a':
5356             case 'e':
5357             case 'r':
5358               temp = (char *)xmalloc (2);
5359               if (c == 'a')
5360                 temp[0] = '\07';
5361               else if (c == 'e')
5362                 temp[0] = '\033';
5363               else if (c == 'r')
5364                 temp[0] = '\r';
5365               else                      /* (c == '\\') */
5366                 temp[0] = c;
5367               temp[1] = '\0';
5368               goto add_string;
5369
5370             default:
5371 not_escape:
5372               temp = (char *)xmalloc (3);
5373               temp[0] = '\\';
5374               temp[1] = c;
5375               temp[2] = '\0';
5376
5377             add_string:
5378               if (c)
5379                 string++;
5380               result =
5381                 sub_append_string (temp, result, &result_index, &result_size);
5382               temp = (char *)NULL; /* Freed in sub_append_string (). */
5383               result[result_index] = '\0';
5384               break;
5385             }
5386         }
5387       else
5388         {
5389           RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
5390           result[result_index++] = c;
5391           result[result_index] = '\0';
5392         }
5393     }
5394 #else /* !PROMPT_STRING_DECODE */
5395   result = savestring (string);
5396 #endif /* !PROMPT_STRING_DECODE */
5397
5398   /* Save the delimiter stack and point `dstack' to temp space so any
5399      command substitutions in the prompt string won't result in screwing
5400      up the parser's quoting state. */
5401   save_dstack = dstack;
5402   dstack = temp_dstack;
5403   dstack.delimiter_depth = 0;
5404
5405   /* Perform variable and parameter expansion and command substitution on
5406      the prompt string. */
5407   if (promptvars || posixly_correct)
5408     {
5409       last_exit_value = last_command_exit_value;
5410       last_comsub_pid = last_command_subst_pid;
5411       list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
5412       free (result);
5413       result = string_list (list);
5414       dispose_words (list);
5415       last_command_exit_value = last_exit_value;
5416       last_command_subst_pid = last_comsub_pid;
5417     }
5418   else
5419     {
5420       t = dequote_string (result);
5421       free (result);
5422       result = t;
5423     }
5424
5425   dstack = save_dstack;
5426
5427   return (result);
5428 }
5429
5430 /************************************************
5431  *                                              *
5432  *              ERROR HANDLING                  *
5433  *                                              *
5434  ************************************************/
5435
5436 /* Report a syntax error, and restart the parser.  Call here for fatal
5437    errors. */
5438 int
5439 yyerror (msg)
5440      const char *msg;
5441 {
5442   report_syntax_error ((char *)NULL);
5443   reset_parser ();
5444   return (0);
5445 }
5446
5447 static char *
5448 error_token_from_token (tok)
5449      int tok;
5450 {
5451   char *t;
5452
5453   if (t = find_token_in_alist (tok, word_token_alist, 0))
5454     return t;
5455
5456   if (t = find_token_in_alist (tok, other_token_alist, 0))
5457     return t;
5458
5459   t = (char *)NULL;
5460   /* This stuff is dicy and needs closer inspection */
5461   switch (current_token)
5462     {
5463     case WORD:
5464     case ASSIGNMENT_WORD:
5465       if (yylval.word)
5466         t = savestring (yylval.word->word);
5467       break;
5468     case NUMBER:
5469       t = itos (yylval.number);
5470       break;
5471     case ARITH_CMD:
5472       if (yylval.word_list)
5473         t = string_list (yylval.word_list);
5474       break;
5475     case ARITH_FOR_EXPRS:
5476       if (yylval.word_list)
5477         t = string_list_internal (yylval.word_list, " ; ");
5478       break;
5479     case COND_CMD:
5480       t = (char *)NULL;         /* punt */
5481       break;
5482     }
5483
5484   return t;
5485 }
5486
5487 static char *
5488 error_token_from_text ()
5489 {
5490   char *msg, *t;
5491   int token_end, i;
5492
5493   t = shell_input_line;
5494   i = shell_input_line_index;
5495   token_end = 0;
5496   msg = (char *)NULL;
5497
5498   if (i && t[i] == '\0')
5499     i--;
5500
5501   while (i && (whitespace (t[i]) || t[i] == '\n'))
5502     i--;
5503
5504   if (i)
5505     token_end = i + 1;
5506
5507   while (i && (member (t[i], " \n\t;|&") == 0))
5508     i--;
5509
5510   while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
5511     i++;
5512
5513   /* Return our idea of the offending token. */
5514   if (token_end || (i == 0 && token_end == 0))
5515     {
5516       if (token_end)
5517         msg = substring (t, i, token_end);
5518       else      /* one-character token */
5519         {
5520           msg = (char *)xmalloc (2);
5521           msg[0] = t[i];
5522           msg[1] = '\0';
5523         }
5524     }
5525
5526   return (msg);
5527 }
5528
5529 static void
5530 print_offending_line ()
5531 {
5532   char *msg;
5533   int token_end;
5534
5535   msg = savestring (shell_input_line);
5536   token_end = strlen (msg);
5537   while (token_end && msg[token_end - 1] == '\n')
5538     msg[--token_end] = '\0';
5539
5540   parser_error (line_number, "`%s'", msg);
5541   free (msg);
5542 }
5543
5544 /* Report a syntax error with line numbers, etc.
5545    Call here for recoverable errors.  If you have a message to print,
5546    then place it in MESSAGE, otherwise pass NULL and this will figure
5547    out an appropriate message for you. */
5548 static void
5549 report_syntax_error (message)
5550      char *message;
5551 {
5552   char *msg, *p;
5553
5554   if (message)
5555     {
5556       parser_error (line_number, "%s", message);
5557       if (interactive && EOF_Reached)
5558         EOF_Reached = 0;
5559       last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
5560       return;
5561     }
5562
5563   /* If the line of input we're reading is not null, try to find the
5564      objectionable token.  First, try to figure out what token the
5565      parser's complaining about by looking at current_token. */
5566   if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
5567     {
5568       if (ansic_shouldquote (msg))
5569         {
5570           p = ansic_quote (msg, 0, NULL);
5571           free (msg);
5572           msg = p;
5573         }
5574       parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
5575       free (msg);
5576
5577       if (interactive == 0)
5578         print_offending_line ();
5579
5580       last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
5581       return;
5582     }
5583
5584   /* If looking at the current token doesn't prove fruitful, try to find the
5585      offending token by analyzing the text of the input line near the current
5586      input line index and report what we find. */
5587   if (shell_input_line && *shell_input_line)
5588     {
5589       msg = error_token_from_text ();
5590       if (msg)
5591         {
5592           parser_error (line_number, _("syntax error near `%s'"), msg);
5593           free (msg);
5594         }
5595
5596       /* If not interactive, print the line containing the error. */
5597       if (interactive == 0)
5598         print_offending_line ();
5599     }
5600   else
5601     {
5602       msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
5603       parser_error (line_number, "%s", msg);
5604       /* When the shell is interactive, this file uses EOF_Reached
5605          only for error reporting.  Other mechanisms are used to
5606          decide whether or not to exit. */
5607       if (interactive && EOF_Reached)
5608         EOF_Reached = 0;
5609     }
5610
5611   last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
5612 }
5613
5614 /* ??? Needed function. ??? We have to be able to discard the constructs
5615    created during parsing.  In the case of error, we want to return
5616    allocated objects to the memory pool.  In the case of no error, we want
5617    to throw away the information about where the allocated objects live.
5618    (dispose_command () will actually free the command.) */
5619 static void
5620 discard_parser_constructs (error_p)
5621      int error_p;
5622 {
5623 }
5624
5625 /************************************************
5626  *                                              *
5627  *              EOF HANDLING                    *
5628  *                                              *
5629  ************************************************/
5630
5631 /* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
5632
5633 /* A flag denoting whether or not ignoreeof is set. */
5634 int ignoreeof = 0;
5635
5636 /* The number of times that we have encountered an EOF character without
5637    another character intervening.  When this gets above the limit, the
5638    shell terminates. */
5639 int eof_encountered = 0;
5640
5641 /* The limit for eof_encountered. */
5642 int eof_encountered_limit = 10;
5643
5644 /* If we have EOF as the only input unit, this user wants to leave
5645    the shell.  If the shell is not interactive, then just leave.
5646    Otherwise, if ignoreeof is set, and we haven't done this the
5647    required number of times in a row, print a message. */
5648 static void
5649 handle_eof_input_unit ()
5650 {
5651   if (interactive)
5652     {
5653       /* shell.c may use this to decide whether or not to write out the
5654          history, among other things.  We use it only for error reporting
5655          in this file. */
5656       if (EOF_Reached)
5657         EOF_Reached = 0;
5658
5659       /* If the user wants to "ignore" eof, then let her do so, kind of. */
5660       if (ignoreeof)
5661         {
5662           if (eof_encountered < eof_encountered_limit)
5663             {
5664               fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
5665                        login_shell ? "logout" : "exit");
5666               eof_encountered++;
5667               /* Reset the parsing state. */
5668               last_read_token = current_token = '\n';
5669               /* Reset the prompt string to be $PS1. */
5670               prompt_string_pointer = (char **)NULL;
5671               prompt_again ();
5672               return;
5673             }
5674         }
5675
5676       /* In this case EOF should exit the shell.  Do it now. */
5677       reset_parser ();
5678       exit_builtin ((WORD_LIST *)NULL);
5679     }
5680   else
5681     {
5682       /* We don't write history files, etc., for non-interactive shells. */
5683       EOF_Reached = 1;
5684     }
5685 }
5686
5687 /************************************************
5688  *                                              *
5689  *      STRING PARSING FUNCTIONS                *
5690  *                                              *
5691  ************************************************/
5692
5693 /* It's very important that these two functions treat the characters
5694    between ( and ) identically. */
5695
5696 static WORD_LIST parse_string_error;
5697
5698 /* Take a string and run it through the shell parser, returning the
5699    resultant word list.  Used by compound array assignment. */
5700 WORD_LIST *
5701 parse_string_to_word_list (s, flags, whom)
5702      char *s;
5703      int flags;
5704      const char *whom;
5705 {
5706   WORD_LIST *wl;
5707   int tok, orig_current_token, orig_line_number, orig_input_terminator;
5708   int orig_line_count;
5709   int old_echo_input, old_expand_aliases;
5710 #if defined (HISTORY)
5711   int old_remember_on_history, old_history_expansion_inhibited;
5712 #endif
5713
5714 #if defined (HISTORY)
5715   old_remember_on_history = remember_on_history;
5716 #  if defined (BANG_HISTORY)
5717   old_history_expansion_inhibited = history_expansion_inhibited;
5718 #  endif
5719   bash_history_disable ();
5720 #endif
5721
5722   orig_line_number = line_number;
5723   orig_line_count = current_command_line_count;
5724   orig_input_terminator = shell_input_line_terminator;
5725   old_echo_input = echo_input_at_read;
5726   old_expand_aliases = expand_aliases;
5727
5728   push_stream (1);
5729   last_read_token = WORD;               /* WORD to allow reserved words here */
5730   current_command_line_count = 0;
5731   echo_input_at_read = expand_aliases = 0;
5732
5733   with_input_from_string (s, whom);
5734   wl = (WORD_LIST *)NULL;
5735
5736   if (flags & 1)
5737     parser_state |= PST_COMPASSIGN|PST_REPARSE;
5738
5739   while ((tok = read_token (READ)) != yacc_EOF)
5740     {
5741       if (tok == '\n' && *bash_input.location.string == '\0')
5742         break;
5743       if (tok == '\n')          /* Allow newlines in compound assignments */
5744         continue;
5745       if (tok != WORD && tok != ASSIGNMENT_WORD)
5746         {
5747           line_number = orig_line_number + line_number - 1;
5748           orig_current_token = current_token;
5749           current_token = tok;
5750           yyerror (NULL);       /* does the right thing */
5751           current_token = orig_current_token;
5752           if (wl)
5753             dispose_words (wl);
5754           wl = &parse_string_error;
5755           break;
5756         }
5757       wl = make_word_list (yylval.word, wl);
5758     }
5759   
5760   last_read_token = '\n';
5761   pop_stream ();
5762
5763 #if defined (HISTORY)
5764   remember_on_history = old_remember_on_history;
5765 #  if defined (BANG_HISTORY)
5766   history_expansion_inhibited = old_history_expansion_inhibited;
5767 #  endif /* BANG_HISTORY */
5768 #endif /* HISTORY */
5769
5770   echo_input_at_read = old_echo_input;
5771   expand_aliases = old_expand_aliases;
5772
5773   current_command_line_count = orig_line_count;
5774   shell_input_line_terminator = orig_input_terminator;
5775
5776   if (flags & 1)
5777     parser_state &= ~(PST_COMPASSIGN|PST_REPARSE);
5778
5779   if (wl == &parse_string_error)
5780     {
5781       last_command_exit_value = EXECUTION_FAILURE;
5782       if (interactive_shell == 0 && posixly_correct)
5783         jump_to_top_level (FORCE_EOF);
5784       else
5785         jump_to_top_level (DISCARD);
5786     }
5787
5788   return (REVERSE_LIST (wl, WORD_LIST *));
5789 }
5790
5791 static char *
5792 parse_compound_assignment (retlenp)
5793      int *retlenp;
5794 {
5795   WORD_LIST *wl, *rl;
5796   int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
5797   char *saved_token, *ret;
5798
5799   saved_token = token;
5800   orig_token_size = token_buffer_size;
5801   orig_line_number = line_number;
5802   orig_last_token = last_read_token;
5803
5804   last_read_token = WORD;       /* WORD to allow reserved words here */
5805
5806   token = (char *)NULL;
5807   token_buffer_size = 0;
5808
5809   assignok = parser_state&PST_ASSIGNOK;         /* XXX */
5810
5811   wl = (WORD_LIST *)NULL;       /* ( */
5812   parser_state |= PST_COMPASSIGN;
5813
5814   while ((tok = read_token (READ)) != ')')
5815     {
5816       if (tok == '\n')                  /* Allow newlines in compound assignments */
5817         {
5818           if (SHOULD_PROMPT ())
5819             prompt_again ();
5820           continue;
5821         }
5822       if (tok != WORD && tok != ASSIGNMENT_WORD)
5823         {
5824           current_token = tok;  /* for error reporting */
5825           if (tok == yacc_EOF)  /* ( */
5826             parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
5827           else
5828             yyerror(NULL);      /* does the right thing */
5829           if (wl)
5830             dispose_words (wl);
5831           wl = &parse_string_error;
5832           break;
5833         }
5834       wl = make_word_list (yylval.word, wl);
5835     }
5836
5837   FREE (token);
5838   token = saved_token;
5839   token_buffer_size = orig_token_size;
5840
5841   parser_state &= ~PST_COMPASSIGN;
5842
5843   if (wl == &parse_string_error)
5844     {
5845       last_command_exit_value = EXECUTION_FAILURE;
5846       last_read_token = '\n';   /* XXX */
5847       if (interactive_shell == 0 && posixly_correct)
5848         jump_to_top_level (FORCE_EOF);
5849       else
5850         jump_to_top_level (DISCARD);
5851     }
5852
5853   last_read_token = orig_last_token;            /* XXX - was WORD? */
5854
5855   if (wl)
5856     {
5857       rl = REVERSE_LIST (wl, WORD_LIST *);
5858       ret = string_list (rl);
5859       dispose_words (rl);
5860     }
5861   else
5862     ret = (char *)NULL;
5863
5864   if (retlenp)
5865     *retlenp = (ret && *ret) ? strlen (ret) : 0;
5866
5867   if (assignok)
5868     parser_state |= PST_ASSIGNOK;
5869
5870   return ret;
5871 }
5872
5873 /************************************************
5874  *                                              *
5875  *   SAVING AND RESTORING PARTIAL PARSE STATE   *
5876  *                                              *
5877  ************************************************/
5878
5879 sh_parser_state_t *
5880 save_parser_state (ps)
5881      sh_parser_state_t *ps;
5882 {
5883   if (ps == 0)
5884     ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
5885   if (ps == 0)
5886     return ((sh_parser_state_t *)NULL);
5887
5888   ps->parser_state = parser_state;
5889   ps->token_state = save_token_state ();
5890
5891   ps->input_line_terminator = shell_input_line_terminator;
5892   ps->eof_encountered = eof_encountered;
5893
5894   ps->prompt_string_pointer = prompt_string_pointer;
5895
5896   ps->current_command_line_count = current_command_line_count;
5897
5898 #if defined (HISTORY)
5899   ps->remember_on_history = remember_on_history;
5900 #  if defined (BANG_HISTORY)
5901   ps->history_expansion_inhibited = history_expansion_inhibited;
5902 #  endif
5903 #endif
5904
5905   ps->last_command_exit_value = last_command_exit_value;
5906 #if defined (ARRAY_VARS)
5907   ps->pipestatus = save_pipestatus_array ();
5908 #endif
5909     
5910   ps->last_shell_builtin = last_shell_builtin;
5911   ps->this_shell_builtin = this_shell_builtin;
5912
5913   ps->expand_aliases = expand_aliases;
5914   ps->echo_input_at_read = echo_input_at_read;
5915
5916   ps->token = token;
5917   ps->token_buffer_size = token_buffer_size;
5918   /* Force reallocation on next call to read_token_word */
5919   token = 0;
5920   token_buffer_size = 0;
5921
5922   return (ps);
5923 }
5924
5925 void
5926 restore_parser_state (ps)
5927      sh_parser_state_t *ps;
5928 {
5929   if (ps == 0)
5930     return;
5931
5932   parser_state = ps->parser_state;
5933   if (ps->token_state)
5934     {
5935       restore_token_state (ps->token_state);
5936       free (ps->token_state);
5937     }
5938
5939   shell_input_line_terminator = ps->input_line_terminator;
5940   eof_encountered = ps->eof_encountered;
5941
5942   prompt_string_pointer = ps->prompt_string_pointer;
5943
5944   current_command_line_count = ps->current_command_line_count;
5945
5946 #if defined (HISTORY)
5947   remember_on_history = ps->remember_on_history;
5948 #  if defined (BANG_HISTORY)
5949   history_expansion_inhibited = ps->history_expansion_inhibited;
5950 #  endif
5951 #endif
5952
5953   last_command_exit_value = ps->last_command_exit_value;
5954 #if defined (ARRAY_VARS)
5955   restore_pipestatus_array (ps->pipestatus);
5956 #endif
5957
5958   last_shell_builtin = ps->last_shell_builtin;
5959   this_shell_builtin = ps->this_shell_builtin;
5960
5961   expand_aliases = ps->expand_aliases;
5962   echo_input_at_read = ps->echo_input_at_read;
5963
5964   FREE (token);
5965   token = ps->token;
5966   token_buffer_size = ps->token_buffer_size;
5967 }
5968
5969 sh_input_line_state_t *
5970 save_input_line_state (ls)
5971      sh_input_line_state_t *ls;
5972 {
5973   if (ls == 0)
5974     ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
5975   if (ls == 0)
5976     return ((sh_input_line_state_t *)NULL);
5977
5978   ls->input_line = shell_input_line;
5979   ls->input_line_size = shell_input_line_size;
5980   ls->input_line_len = shell_input_line_len;
5981   ls->input_line_index = shell_input_line_index;
5982
5983   /* force reallocation */
5984   shell_input_line = 0;
5985   shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
5986 }
5987
5988 void
5989 restore_input_line_state (ls)
5990      sh_input_line_state_t *ls;
5991 {
5992   FREE (shell_input_line);
5993   shell_input_line = ls->input_line;
5994   shell_input_line_size = ls->input_line_size;
5995   shell_input_line_len = ls->input_line_len;
5996   shell_input_line_index = ls->input_line_index;
5997
5998   set_line_mbstate ();
5999 }
6000
6001 /************************************************
6002  *                                              *
6003  *      MULTIBYTE CHARACTER HANDLING            *
6004  *                                              *
6005  ************************************************/
6006
6007 #if defined (HANDLE_MULTIBYTE)
6008 static void
6009 set_line_mbstate ()
6010 {
6011   int i, previ, len, c;
6012   mbstate_t mbs, prevs;
6013   size_t mbclen;
6014
6015   if (shell_input_line == NULL)
6016     return;
6017   len = strlen (shell_input_line);      /* XXX - shell_input_line_len ? */
6018   FREE (shell_input_line_property);
6019   shell_input_line_property = (char *)xmalloc (len + 1);
6020
6021   memset (&prevs, '\0', sizeof (mbstate_t));
6022   for (i = previ = 0; i < len; i++)
6023     {
6024       mbs = prevs;
6025
6026       c = shell_input_line[i];
6027       if (c == EOF)
6028         {
6029           int j;
6030           for (j = i; j < len; j++)
6031             shell_input_line_property[j] = 1;
6032           break;
6033         }
6034
6035       mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
6036       if (mbclen == 1 || mbclen == (size_t)-1)
6037         {
6038           mbclen = 1;
6039           previ = i + 1;
6040         }
6041       else if (mbclen == (size_t)-2)
6042         mbclen = 0;
6043       else if (mbclen > 1)
6044         {
6045           mbclen = 0;
6046           previ = i + 1;
6047           prevs = mbs;
6048         }
6049       else
6050         {
6051           /* XXX - what to do if mbrlen returns 0? (null wide character) */
6052           int j;
6053           for (j = i; j < len; j++)
6054             shell_input_line_property[j] = 1;
6055           break;
6056         }
6057
6058       shell_input_line_property[i] = mbclen;
6059     }
6060 }
6061 #endif /* HANDLE_MULTIBYTE */