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