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