Bash-4.3 patch 5
[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 && shell_input_line_len > shell_input_line_size - 3)
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)
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   current_token = '\n';         /* XXX */
2957   last_read_token = '\n';
2958   token_to_read = '\n';
2959 }
2960
2961 /* Read the next token.  Command can be READ (normal operation) or
2962    RESET (to normalize state). */
2963 static int
2964 read_token (command)
2965      int command;
2966 {
2967   int character;                /* Current character. */
2968   int peek_char;                /* Temporary look-ahead character. */
2969   int result;                   /* The thing to return. */
2970
2971   if (command == RESET)
2972     {
2973       reset_parser ();
2974       return ('\n');
2975     }
2976
2977   if (token_to_read)
2978     {
2979       result = token_to_read;
2980       if (token_to_read == WORD || token_to_read == ASSIGNMENT_WORD)
2981         {
2982           yylval.word = word_desc_to_read;
2983           word_desc_to_read = (WORD_DESC *)NULL;
2984         }
2985       token_to_read = 0;
2986       return (result);
2987     }
2988
2989 #if defined (COND_COMMAND)
2990   if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD)
2991     {
2992       cond_lineno = line_number;
2993       parser_state |= PST_CONDEXPR;
2994       yylval.command = parse_cond_command ();
2995       if (cond_token != COND_END)
2996         {
2997           cond_error ();
2998           return (-1);
2999         }
3000       token_to_read = COND_END;
3001       parser_state &= ~(PST_CONDEXPR|PST_CONDCMD);
3002       return (COND_CMD);
3003     }
3004 #endif
3005
3006 #if defined (ALIAS)
3007   /* This is a place to jump back to once we have successfully expanded a
3008      token with an alias and pushed the string with push_string () */
3009  re_read_token:
3010 #endif /* ALIAS */
3011
3012   /* Read a single word from input.  Start by skipping blanks. */
3013   while ((character = shell_getc (1)) != EOF && shellblank (character))
3014     ;
3015
3016   if (character == EOF)
3017     {
3018       EOF_Reached = 1;
3019       return (yacc_EOF);
3020     }
3021
3022   if MBTEST(character == '#' && (!interactive || interactive_comments))
3023     {
3024       /* A comment.  Discard until EOL or EOF, and then return a newline. */
3025       discard_until ('\n');
3026       shell_getc (0);
3027       character = '\n'; /* this will take the next if statement and return. */
3028     }
3029
3030   if (character == '\n')
3031     {
3032       /* If we're about to return an unquoted newline, we can go and collect
3033          the text of any pending here document. */
3034       if (need_here_doc)
3035         gather_here_documents ();
3036
3037 #if defined (ALIAS)
3038       parser_state &= ~PST_ALEXPNEXT;
3039 #endif /* ALIAS */
3040
3041       parser_state &= ~PST_ASSIGNOK;
3042
3043       return (character);
3044     }
3045
3046   if (parser_state & PST_REGEXP)
3047     goto tokword;
3048
3049   /* Shell meta-characters. */
3050   if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
3051     {
3052 #if defined (ALIAS)
3053       /* Turn off alias tokenization iff this character sequence would
3054          not leave us ready to read a command. */
3055       if (character == '<' || character == '>')
3056         parser_state &= ~PST_ALEXPNEXT;
3057 #endif /* ALIAS */
3058
3059       parser_state &= ~PST_ASSIGNOK;
3060
3061       peek_char = shell_getc (1);
3062       if (character == peek_char)
3063         {
3064           switch (character)
3065             {
3066             case '<':
3067               /* If '<' then we could be at "<<" or at "<<-".  We have to
3068                  look ahead one more character. */
3069               peek_char = shell_getc (1);
3070               if MBTEST(peek_char == '-')
3071                 return (LESS_LESS_MINUS);
3072               else if MBTEST(peek_char == '<')
3073                 return (LESS_LESS_LESS);
3074               else
3075                 {
3076                   shell_ungetc (peek_char);
3077                   return (LESS_LESS);
3078                 }
3079
3080             case '>':
3081               return (GREATER_GREATER);
3082
3083             case ';':
3084               parser_state |= PST_CASEPAT;
3085 #if defined (ALIAS)
3086               parser_state &= ~PST_ALEXPNEXT;
3087 #endif /* ALIAS */
3088
3089               peek_char = shell_getc (1);
3090               if MBTEST(peek_char == '&')
3091                 return (SEMI_SEMI_AND);
3092               else
3093                 {
3094                   shell_ungetc (peek_char);
3095                   return (SEMI_SEMI);
3096                 }
3097
3098             case '&':
3099               return (AND_AND);
3100
3101             case '|':
3102               return (OR_OR);
3103
3104 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
3105             case '(':           /* ) */
3106               result = parse_dparen (character);
3107               if (result == -2)
3108                 break;
3109               else
3110                 return result;
3111 #endif
3112             }
3113         }
3114       else if MBTEST(character == '<' && peek_char == '&')
3115         return (LESS_AND);
3116       else if MBTEST(character == '>' && peek_char == '&')
3117         return (GREATER_AND);
3118       else if MBTEST(character == '<' && peek_char == '>')
3119         return (LESS_GREATER);
3120       else if MBTEST(character == '>' && peek_char == '|')
3121         return (GREATER_BAR);
3122       else if MBTEST(character == '&' && peek_char == '>')
3123         {
3124           peek_char = shell_getc (1);
3125           if MBTEST(peek_char == '>')
3126             return (AND_GREATER_GREATER);
3127           else
3128             {
3129               shell_ungetc (peek_char);
3130               return (AND_GREATER);
3131             }
3132         }
3133       else if MBTEST(character == '|' && peek_char == '&')
3134         return (BAR_AND);
3135       else if MBTEST(character == ';' && peek_char == '&')
3136         {
3137           parser_state |= PST_CASEPAT;
3138 #if defined (ALIAS)
3139           parser_state &= ~PST_ALEXPNEXT;
3140 #endif /* ALIAS */
3141           return (SEMI_AND);
3142         }
3143
3144       shell_ungetc (peek_char);
3145
3146       /* If we look like we are reading the start of a function
3147          definition, then let the reader know about it so that
3148          we will do the right thing with `{'. */
3149       if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
3150         {
3151           parser_state |= PST_ALLOWOPNBRC;
3152 #if defined (ALIAS)
3153           parser_state &= ~PST_ALEXPNEXT;
3154 #endif /* ALIAS */
3155           function_dstart = line_number;
3156         }
3157
3158       /* case pattern lists may be preceded by an optional left paren.  If
3159          we're not trying to parse a case pattern list, the left paren
3160          indicates a subshell. */
3161       if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
3162         parser_state |= PST_SUBSHELL;
3163       /*(*/
3164       else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
3165         parser_state &= ~PST_CASEPAT;
3166       /*(*/
3167       else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
3168         parser_state &= ~PST_SUBSHELL;
3169
3170 #if defined (PROCESS_SUBSTITUTION)
3171       /* Check for the constructs which introduce process substitution.
3172          Shells running in `posix mode' don't do process substitution. */
3173       if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
3174 #endif /* PROCESS_SUBSTITUTION */
3175         return (character);
3176     }
3177
3178   /* Hack <&- (close stdin) case.  Also <&N- (dup and close). */
3179   if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
3180     return (character);
3181
3182 tokword:
3183   /* Okay, if we got this far, we have to read a word.  Read one,
3184      and then check it against the known ones. */
3185   result = read_token_word (character);
3186 #if defined (ALIAS)
3187   if (result == RE_READ_TOKEN)
3188     goto re_read_token;
3189 #endif
3190   return result;
3191 }
3192
3193 /*
3194  * Match a $(...) or other grouping construct.  This has to handle embedded
3195  * quoted strings ('', ``, "") and nested constructs.  It also must handle
3196  * reprompting the user, if necessary, after reading a newline, and returning
3197  * correct error values if it reads EOF.
3198  */
3199 #define P_FIRSTCLOSE    0x0001
3200 #define P_ALLOWESC      0x0002
3201 #define P_DQUOTE        0x0004
3202 #define P_COMMAND       0x0008  /* parsing a command, so look for comments */
3203 #define P_BACKQUOTE     0x0010  /* parsing a backquoted command substitution */
3204 #define P_ARRAYSUB      0x0020  /* parsing a [...] array subscript for assignment */
3205 #define P_DOLBRACE      0x0040  /* parsing a ${...} construct */
3206
3207 /* Lexical state while parsing a grouping construct or $(...). */
3208 #define LEX_WASDOL      0x001
3209 #define LEX_CKCOMMENT   0x002
3210 #define LEX_INCOMMENT   0x004
3211 #define LEX_PASSNEXT    0x008
3212 #define LEX_RESWDOK     0x010
3213 #define LEX_CKCASE      0x020
3214 #define LEX_INCASE      0x040
3215 #define LEX_INHEREDOC   0x080
3216 #define LEX_HEREDELIM   0x100           /* reading here-doc delimiter */
3217 #define LEX_STRIPDOC    0x200           /* <<- strip tabs from here doc delim */
3218 #define LEX_INWORD      0x400
3219
3220 #define COMSUB_META(ch)         ((ch) == ';' || (ch) == '&' || (ch) == '|')
3221
3222 #define CHECK_NESTRET_ERROR() \
3223   do { \
3224     if (nestret == &matched_pair_error) \
3225       { \
3226         free (ret); \
3227         return &matched_pair_error; \
3228       } \
3229   } while (0)
3230
3231 #define APPEND_NESTRET() \
3232   do { \
3233     if (nestlen) \
3234       { \
3235         RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64); \
3236         strcpy (ret + retind, nestret); \
3237         retind += nestlen; \
3238       } \
3239   } while (0)
3240
3241 static char matched_pair_error;
3242
3243 static char *
3244 parse_matched_pair (qc, open, close, lenp, flags)
3245      int qc;    /* `"' if this construct is within double quotes */
3246      int open, close;
3247      int *lenp, flags;
3248 {
3249   int count, ch, tflags;
3250   int nestlen, ttranslen, start_lineno;
3251   char *ret, *nestret, *ttrans;
3252   int retind, retsize, rflags;
3253   int dolbrace_state;
3254
3255   dolbrace_state = (flags & P_DOLBRACE) ? DOLBRACE_PARAM : 0;
3256
3257 /*itrace("parse_matched_pair[%d]: open = %c close = %c flags = %d", line_number, open, close, flags);*/
3258   count = 1;
3259   tflags = 0;
3260
3261   if ((flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
3262     tflags |= LEX_CKCOMMENT;
3263
3264   /* RFLAGS is the set of flags we want to pass to recursive calls. */
3265   rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
3266
3267   ret = (char *)xmalloc (retsize = 64);
3268   retind = 0;
3269
3270   start_lineno = line_number;
3271   while (count)
3272     {
3273       ch = shell_getc (qc != '\'' && (tflags & (LEX_PASSNEXT)) == 0);
3274
3275       if (ch == EOF)
3276         {
3277           free (ret);
3278           parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
3279           EOF_Reached = 1;      /* XXX */
3280           return (&matched_pair_error);
3281         }
3282
3283       /* Possible reprompting. */
3284       if (ch == '\n' && SHOULD_PROMPT ())
3285         prompt_again ();
3286
3287       /* Don't bother counting parens or doing anything else if in a comment
3288          or part of a case statement */
3289       if (tflags & LEX_INCOMMENT)
3290         {
3291           /* Add this character. */
3292           RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3293           ret[retind++] = ch;
3294
3295           if (ch == '\n')
3296             tflags &= ~LEX_INCOMMENT;
3297
3298           continue;
3299         }
3300
3301       /* Not exactly right yet, should handle shell metacharacters, too.  If
3302          any changes are made to this test, make analogous changes to subst.c:
3303          extract_delimited_string(). */
3304       else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
3305         tflags |= LEX_INCOMMENT;
3306
3307       if (tflags & LEX_PASSNEXT)                /* last char was backslash */
3308         {
3309           tflags &= ~LEX_PASSNEXT;
3310           if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
3311             {
3312               if (retind > 0)
3313                 retind--;       /* swallow previously-added backslash */
3314               continue;
3315             }
3316
3317           RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
3318           if MBTEST(ch == CTLESC)
3319             ret[retind++] = CTLESC;
3320           ret[retind++] = ch;
3321           continue;
3322         }
3323       /* If we're reparsing the input (e.g., from parse_string_to_word_list),
3324          we've already prepended CTLESC to single-quoted results of $'...'.
3325          We may want to do this for other CTLESC-quoted characters in
3326          reparse, too. */
3327       else if MBTEST((parser_state & PST_REPARSE) && open == '\'' && (ch == CTLESC || ch == CTLNUL))
3328         {
3329           RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3330           ret[retind++] = ch;
3331           continue;
3332         }
3333       else if MBTEST(ch == CTLESC || ch == CTLNUL)      /* special shell escapes */
3334         {
3335           RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
3336           ret[retind++] = CTLESC;
3337           ret[retind++] = ch;
3338           continue;
3339         }
3340       else if MBTEST(ch == close)               /* ending delimiter */
3341         count--;
3342       /* handle nested ${...} specially. */
3343       else if MBTEST(open != close && (tflags & LEX_WASDOL) && open == '{' && ch == open) /* } */
3344         count++;
3345       else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open)       /* nested begin */
3346         count++;
3347
3348       /* Add this character. */
3349       RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3350       ret[retind++] = ch;
3351
3352       /* If we just read the ending character, don't bother continuing. */
3353       if (count == 0)
3354         break;
3355
3356       if (open == '\'')                 /* '' inside grouping construct */
3357         {
3358           if MBTEST((flags & P_ALLOWESC) && ch == '\\')
3359             tflags |= LEX_PASSNEXT;
3360           continue;
3361         }
3362
3363       if MBTEST(ch == '\\')                     /* backslashes */
3364         tflags |= LEX_PASSNEXT;
3365
3366       /* Based on which dolstate is currently in (param, op, or word),
3367          decide what the op is.  We're really only concerned if it's % or
3368          #, so we can turn on a flag that says whether or not we should
3369          treat single quotes as special when inside a double-quoted
3370          ${...}. This logic must agree with subst.c:extract_dollar_brace_string
3371          since they share the same defines. */
3372       /* FLAG POSIX INTERP 221 */
3373       if (flags & P_DOLBRACE)
3374         {
3375           /* ${param%[%]word} */
3376           if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '%' && retind > 1)
3377             dolbrace_state = DOLBRACE_QUOTE;
3378           /* ${param#[#]word} */
3379           else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '#' && retind > 1)
3380             dolbrace_state = DOLBRACE_QUOTE;
3381           /* ${param/[/]pat/rep} */
3382           else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '/' && retind > 1)
3383             dolbrace_state = DOLBRACE_QUOTE2;   /* XXX */
3384           /* ${param^[^]pat} */
3385           else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '^' && retind > 1)
3386             dolbrace_state = DOLBRACE_QUOTE;
3387           /* ${param,[,]pat} */
3388           else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == ',' && retind > 1)
3389             dolbrace_state = DOLBRACE_QUOTE;
3390           else if MBTEST(dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", ch) != 0)
3391             dolbrace_state = DOLBRACE_OP;
3392           else if MBTEST(dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", ch) == 0)
3393             dolbrace_state = DOLBRACE_WORD;
3394         }
3395
3396       /* The big hammer.  Single quotes aren't special in double quotes.  The
3397          problem is that Posix used to say the single quotes are semi-special:
3398          within a double-quoted ${...} construct "an even number of
3399          unescaped double-quotes or single-quotes, if any, shall occur." */
3400       /* This was changed in Austin Group Interp 221 */
3401       if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && dolbrace_state != DOLBRACE_QUOTE2 && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'')
3402         continue;
3403
3404       /* Could also check open == '`' if we want to parse grouping constructs
3405          inside old-style command substitution. */
3406       if (open != close)                /* a grouping construct */
3407         {
3408           if MBTEST(shellquote (ch))
3409             {
3410               /* '', ``, or "" inside $(...) or other grouping construct. */
3411               push_delimiter (dstack, ch);
3412               if MBTEST((tflags & LEX_WASDOL) && ch == '\'')    /* $'...' inside group */
3413                 nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
3414               else
3415                 nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
3416               pop_delimiter (dstack);
3417               CHECK_NESTRET_ERROR ();
3418
3419               if MBTEST((tflags & LEX_WASDOL) && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
3420                 {
3421                   /* Translate $'...' here. */
3422                   ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
3423                   xfree (nestret);
3424
3425                   /* If we're parsing a double-quoted brace expansion and we are
3426                      not in a place where single quotes are treated specially,
3427                      make sure we single-quote the results of the ansi
3428                      expansion because quote removal should remove them later */
3429                   /* FLAG POSIX INTERP 221 */
3430                   if ((shell_compatibility_level > 42) && (rflags & P_DQUOTE) && (dolbrace_state == DOLBRACE_QUOTE2) && (flags & P_DOLBRACE))
3431                     {
3432                       nestret = sh_single_quote (ttrans);
3433                       free (ttrans);
3434                       nestlen = strlen (nestret);
3435                     }
3436                   else if ((rflags & P_DQUOTE) == 0)
3437                     {
3438                       nestret = sh_single_quote (ttrans);
3439                       free (ttrans);
3440                       nestlen = strlen (nestret);
3441                     }
3442                   else
3443                     {
3444                       nestret = ttrans;
3445                       nestlen = ttranslen;
3446                     }
3447                   retind -= 2;          /* back up before the $' */
3448                 }
3449               else if MBTEST((tflags & LEX_WASDOL) && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
3450                 {
3451                   /* Locale expand $"..." here. */
3452                   ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
3453                   xfree (nestret);
3454
3455                   nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
3456                   free (ttrans);
3457                   nestlen = ttranslen + 2;
3458                   retind -= 2;          /* back up before the $" */
3459                 }
3460
3461               APPEND_NESTRET ();
3462               FREE (nestret);
3463             }
3464           else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))      /* ) } ] */
3465             goto parse_dollar_word;
3466         }
3467       /* Parse an old-style command substitution within double quotes as a
3468          single word. */
3469       /* XXX - sh and ksh93 don't do this - XXX */
3470       else if MBTEST(open == '"' && ch == '`')
3471         {
3472           nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags);
3473
3474           CHECK_NESTRET_ERROR ();
3475           APPEND_NESTRET ();
3476
3477           FREE (nestret);
3478         }
3479       else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))     /* ) } ] */
3480         /* check for $(), $[], or ${} inside quoted string. */
3481         {
3482 parse_dollar_word:
3483           if (open == ch)       /* undo previous increment */
3484             count--;
3485           if (ch == '(')                /* ) */
3486             nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
3487           else if (ch == '{')           /* } */
3488             nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
3489           else if (ch == '[')           /* ] */
3490             nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
3491
3492           CHECK_NESTRET_ERROR ();
3493           APPEND_NESTRET ();
3494
3495           FREE (nestret);
3496         }
3497       if MBTEST(ch == '$')
3498         tflags |= LEX_WASDOL;
3499       else
3500         tflags &= ~LEX_WASDOL;
3501     }
3502
3503   ret[retind] = '\0';
3504   if (lenp)
3505     *lenp = retind;
3506 /*itrace("parse_matched_pair[%d]: returning %s", line_number, ret);*/
3507   return ret;
3508 }
3509
3510 /* Parse a $(...) command substitution.  This is messier than I'd like, and
3511    reproduces a lot more of the token-reading code than I'd like. */
3512 static char *
3513 parse_comsub (qc, open, close, lenp, flags)
3514      int qc;    /* `"' if this construct is within double quotes */
3515      int open, close;
3516      int *lenp, flags;
3517 {
3518   int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
3519   int nestlen, ttranslen, start_lineno;
3520   char *ret, *nestret, *ttrans, *heredelim;
3521   int retind, retsize, rflags, hdlen;
3522
3523   /* Posix interp 217 says arithmetic expressions have precedence, so
3524      assume $(( introduces arithmetic expansion and parse accordingly. */
3525   peekc = shell_getc (0);
3526   shell_ungetc (peekc);
3527   if (peekc == '(')
3528     return (parse_matched_pair (qc, open, close, lenp, 0));
3529
3530 /*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
3531   count = 1;
3532   tflags = LEX_RESWDOK;
3533
3534   if ((flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
3535     tflags |= LEX_CKCASE;
3536   if ((tflags & LEX_CKCASE) && (interactive == 0 || interactive_comments))
3537     tflags |= LEX_CKCOMMENT;
3538
3539   /* RFLAGS is the set of flags we want to pass to recursive calls. */
3540   rflags = (flags & P_DQUOTE);
3541
3542   ret = (char *)xmalloc (retsize = 64);
3543   retind = 0;
3544
3545   start_lineno = line_number;
3546   lex_rwlen = lex_wlen = 0;
3547
3548   heredelim = 0;
3549   lex_firstind = -1;
3550
3551   while (count)
3552     {
3553 comsub_readchar:
3554       ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT)) == 0);
3555
3556       if (ch == EOF)
3557         {
3558 eof_error:
3559           free (ret);
3560           FREE (heredelim);
3561           parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
3562           EOF_Reached = 1;      /* XXX */
3563           return (&matched_pair_error);
3564         }
3565
3566       /* If we hit the end of a line and are reading the contents of a here
3567          document, and it's not the same line that the document starts on,
3568          check for this line being the here doc delimiter.  Otherwise, if
3569          we're in a here document, mark the next character as the beginning
3570          of a line. */
3571       if (ch == '\n')
3572         {
3573           if ((tflags & LEX_HEREDELIM) && heredelim)
3574             {
3575               tflags &= ~LEX_HEREDELIM;
3576               tflags |= LEX_INHEREDOC;
3577               lex_firstind = retind + 1;
3578             }
3579           else if (tflags & LEX_INHEREDOC)
3580             {
3581               int tind;
3582               tind = lex_firstind;
3583               while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
3584                 tind++;
3585               if (STREQN (ret + tind, heredelim, hdlen))
3586                 {
3587                   tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC);
3588 /*itrace("parse_comsub:%d: found here doc end `%s'", line_number, ret + tind);*/
3589                   free (heredelim);
3590                   heredelim = 0;
3591                   lex_firstind = -1;
3592                 }
3593               else
3594                 lex_firstind = retind + 1;
3595             }
3596         }
3597
3598       /* Possible reprompting. */
3599       if (ch == '\n' && SHOULD_PROMPT ())
3600         prompt_again ();
3601
3602       /* XXX -- possibly allow here doc to be delimited by ending right
3603          paren. */
3604       if ((tflags & LEX_INHEREDOC) && ch == close && count == 1)
3605         {
3606           int tind;
3607 /*itrace("parse_comsub: in here doc, ch == close, retind - firstind = %d hdlen = %d retind = %d", retind-lex_firstind, hdlen, retind);*/
3608           tind = lex_firstind;
3609           while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
3610             tind++;
3611           if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen))
3612             {
3613               tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC);
3614 /*itrace("parse_comsub:%d: found here doc end `%s'", line_number, ret + tind);*/
3615               free (heredelim);
3616               heredelim = 0;
3617               lex_firstind = -1;
3618             }
3619         }
3620
3621       /* Don't bother counting parens or doing anything else if in a comment */
3622       if (tflags & (LEX_INCOMMENT|LEX_INHEREDOC))
3623         {
3624           /* Add this character. */
3625           RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3626           ret[retind++] = ch;
3627
3628           if ((tflags & LEX_INCOMMENT) && ch == '\n')
3629             {
3630 /*itrace("parse_comsub:%d: lex_incomment -> 0 ch = `%c'", line_number, ch);*/
3631               tflags &= ~LEX_INCOMMENT;
3632             }
3633
3634           continue;
3635         }
3636
3637       if (tflags & LEX_PASSNEXT)                /* last char was backslash */
3638         {
3639 /*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
3640           tflags &= ~LEX_PASSNEXT;
3641           if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
3642             {
3643               if (retind > 0)
3644                 retind--;       /* swallow previously-added backslash */
3645               continue;
3646             }
3647
3648           RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
3649           if MBTEST(ch == CTLESC)
3650             ret[retind++] = CTLESC;
3651           ret[retind++] = ch;
3652           continue;
3653         }
3654
3655       /* If this is a shell break character, we are not in a word.  If not,
3656          we either start or continue a word. */
3657       if MBTEST(shellbreak (ch))
3658         {
3659           tflags &= ~LEX_INWORD;
3660 /*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
3661         }
3662       else
3663         {
3664           if (tflags & LEX_INWORD)
3665             {
3666               lex_wlen++;
3667 /*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
3668             }         
3669           else
3670             {
3671 /*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
3672               tflags |= LEX_INWORD;
3673               lex_wlen = 0;
3674             }
3675         }
3676
3677       /* Skip whitespace */
3678       if MBTEST(shellblank (ch) && (tflags & LEX_HEREDELIM) == 0 && lex_rwlen == 0)
3679         {
3680           /* Add this character. */
3681           RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3682           ret[retind++] = ch;
3683           continue;
3684         }
3685
3686       /* Either we are looking for the start of the here-doc delimiter
3687          (lex_firstind == -1) or we are reading one (lex_firstind >= 0).
3688          If this character is a shell break character and we are reading
3689          the delimiter, save it and note that we are now reading a here
3690          document.  If we've found the start of the delimiter, note it by
3691          setting lex_firstind.  Backslashes can quote shell metacharacters
3692          in here-doc delimiters. */
3693       if (tflags & LEX_HEREDELIM)
3694         {
3695           if (lex_firstind == -1 && shellbreak (ch) == 0)
3696             lex_firstind = retind;
3697 #if 0
3698           else if (heredelim && (tflags & LEX_PASSNEXT) == 0 && ch == '\n')
3699             {
3700               tflags |= LEX_INHEREDOC;
3701               tflags &= ~LEX_HEREDELIM;
3702               lex_firstind = retind + 1;
3703             }
3704 #endif
3705           else if (lex_firstind >= 0 && (tflags & LEX_PASSNEXT) == 0 && shellbreak (ch))
3706             {
3707               if (heredelim == 0)
3708                 {
3709                   nestret = substring (ret, lex_firstind, retind);
3710                   heredelim = string_quote_removal (nestret, 0);
3711                   free (nestret);
3712                   hdlen = STRLEN(heredelim);
3713 /*itrace("parse_comsub:%d: found here doc delimiter `%s' (%d)", line_number, heredelim, hdlen);*/
3714                 }
3715               if (ch == '\n')
3716                 {
3717                   tflags |= LEX_INHEREDOC;
3718                   tflags &= ~LEX_HEREDELIM;
3719                   lex_firstind = retind + 1;
3720                 }
3721               else
3722                 lex_firstind = -1;
3723             }
3724         }
3725
3726       /* Meta-characters that can introduce a reserved word.  Not perfect yet. */
3727       if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && (shellmeta(ch) || ch == '\n'))
3728         {
3729           /* Add this character. */
3730           RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3731           ret[retind++] = ch;
3732           peekc = shell_getc (1);
3733           if (ch == peekc && (ch == '&' || ch == '|' || ch == ';'))     /* two-character tokens */
3734             {
3735               RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3736               ret[retind++] = peekc;
3737 /*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
3738               tflags |= LEX_RESWDOK;
3739               lex_rwlen = 0;
3740               continue;
3741             }
3742           else if (ch == '\n' || COMSUB_META(ch))
3743             {
3744               shell_ungetc (peekc);
3745 /*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
3746               tflags |= LEX_RESWDOK;
3747               lex_rwlen = 0;
3748               continue;
3749             }
3750           else if (ch == EOF)
3751             goto eof_error;
3752           else
3753             {
3754               /* `unget' the character we just added and fall through */
3755               retind--;
3756               shell_ungetc (peekc);
3757             }
3758         }
3759
3760       /* If we can read a reserved word, try to read one. */
3761       if (tflags & LEX_RESWDOK)
3762         {
3763           if MBTEST(islower (ch))
3764             {
3765               /* Add this character. */
3766               RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3767               ret[retind++] = ch;
3768               lex_rwlen++;
3769               continue;
3770             }
3771           else if MBTEST(lex_rwlen == 4 && shellbreak (ch))
3772             {
3773               if (STREQN (ret + retind - 4, "case", 4))
3774                 {
3775                   tflags |= LEX_INCASE;
3776 /*itrace("parse_comsub:%d: found `case', lex_incase -> 1 lex_reswdok -> 0", line_number);*/
3777                 }
3778               else if (STREQN (ret + retind - 4, "esac", 4))
3779                 {
3780                   tflags &= ~LEX_INCASE;
3781 /*itrace("parse_comsub:%d: found `esac', lex_incase -> 0 lex_reswdok -> 0", line_number);*/
3782                 }
3783               tflags &= ~LEX_RESWDOK;
3784             }
3785           else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
3786             ;   /* don't modify LEX_RESWDOK if we're starting a comment */
3787           /* Allow `do' followed by space, tab, or newline to preserve the
3788              RESWDOK flag, but reset the reserved word length counter so we
3789              can read another one. */
3790           else if MBTEST(((tflags & LEX_INCASE) == 0) &&
3791                           (isblank(ch) || ch == '\n') &&
3792                           lex_rwlen == 2 &&
3793                           STREQN (ret + retind - 2, "do", 2))
3794             {
3795 /*itrace("parse_comsub:%d: lex_incase == 1 found `%c', found \"do\"", line_number, ch);*/
3796               lex_rwlen = 0;
3797             }
3798           else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
3799             /* If we can read a reserved word and we're in case, we're at the
3800                point where we can read a new pattern list or an esac.  We
3801                handle the esac case above.  If we read a newline, we want to
3802                leave LEX_RESWDOK alone.  If we read anything else, we want to
3803                turn off LEX_RESWDOK, since we're going to read a pattern list. */
3804             {
3805               tflags &= ~LEX_RESWDOK;
3806 /*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
3807             }
3808           else if MBTEST(shellbreak (ch) == 0)
3809             {
3810               tflags &= ~LEX_RESWDOK;
3811 /*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
3812             }
3813 #if 0
3814           /* If we find a space or tab but have read something and it's not
3815              `do', turn off the reserved-word-ok flag */
3816           else if MBTEST(isblank (ch) && lex_rwlen > 0)
3817             {
3818               tflags &= ~LEX_RESWDOK;
3819 /*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
3820             }
3821 #endif
3822         }
3823
3824       /* Might be the start of a here-doc delimiter */
3825       if MBTEST((tflags & LEX_INCOMMENT) == 0 && (tflags & LEX_CKCASE) && ch == '<')
3826         {
3827           /* Add this character. */
3828           RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3829           ret[retind++] = ch;
3830           peekc = shell_getc (1);
3831           if (peekc == EOF)
3832             goto eof_error;
3833           if (peekc == ch)
3834             {
3835               RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3836               ret[retind++] = peekc;
3837               peekc = shell_getc (1);
3838               if (peekc == EOF)
3839                 goto eof_error;
3840               if (peekc == '-')
3841                 {
3842                   RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3843                   ret[retind++] = peekc;
3844                   tflags |= LEX_STRIPDOC;
3845                 }
3846               else
3847                 shell_ungetc (peekc);
3848               if (peekc != '<')
3849                 {
3850                   tflags |= LEX_HEREDELIM;
3851                   lex_firstind = -1;
3852                 }
3853               continue;
3854             }
3855           else
3856             ch = peekc;         /* fall through and continue XXX */
3857         }
3858       else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
3859         {
3860 /*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
3861           tflags |= LEX_INCOMMENT;
3862         }
3863
3864       if MBTEST(ch == CTLESC || ch == CTLNUL)   /* special shell escapes */
3865         {
3866           RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
3867           ret[retind++] = CTLESC;
3868           ret[retind++] = ch;
3869           continue;
3870         }
3871 #if 0
3872       else if MBTEST((tflags & LEX_INCASE) && ch == close && close == ')')
3873         tflags &= ~LEX_INCASE;          /* XXX */
3874 #endif
3875       else if MBTEST(ch == close && (tflags & LEX_INCASE) == 0)         /* ending delimiter */
3876         {
3877           count--;
3878 /*itrace("parse_comsub:%d: found close: count = %d", line_number, count);*/
3879         }
3880       else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && (tflags & LEX_INCASE) == 0 && ch == open) /* nested begin */
3881         {
3882           count++;
3883 /*itrace("parse_comsub:%d: found open: count = %d", line_number, count);*/
3884         }
3885
3886       /* Add this character. */
3887       RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
3888       ret[retind++] = ch;
3889
3890       /* If we just read the ending character, don't bother continuing. */
3891       if (count == 0)
3892         break;
3893
3894       if MBTEST(ch == '\\')                     /* backslashes */
3895         tflags |= LEX_PASSNEXT;
3896
3897       if MBTEST(shellquote (ch))
3898         {
3899           /* '', ``, or "" inside $(...). */
3900           push_delimiter (dstack, ch);
3901           if MBTEST((tflags & LEX_WASDOL) && ch == '\'')        /* $'...' inside group */
3902             nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
3903           else
3904             nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
3905           pop_delimiter (dstack);
3906           CHECK_NESTRET_ERROR ();
3907
3908           if MBTEST((tflags & LEX_WASDOL) && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
3909             {
3910               /* Translate $'...' here. */
3911               ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
3912               xfree (nestret);
3913
3914               if ((rflags & P_DQUOTE) == 0)
3915                 {
3916                   nestret = sh_single_quote (ttrans);
3917                   free (ttrans);
3918                   nestlen = strlen (nestret);
3919                 }
3920               else
3921                 {
3922                   nestret = ttrans;
3923                   nestlen = ttranslen;
3924                 }
3925               retind -= 2;              /* back up before the $' */
3926             }
3927           else if MBTEST((tflags & LEX_WASDOL) && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
3928             {
3929               /* Locale expand $"..." here. */
3930               ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
3931               xfree (nestret);
3932
3933               nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
3934               free (ttrans);
3935               nestlen = ttranslen + 2;
3936               retind -= 2;              /* back up before the $" */
3937             }
3938
3939           APPEND_NESTRET ();
3940           FREE (nestret);
3941         }
3942       else if MBTEST((tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))    /* ) } ] */
3943         /* check for $(), $[], or ${} inside command substitution. */
3944         {
3945           if ((tflags & LEX_INCASE) == 0 && open == ch) /* undo previous increment */
3946             count--;
3947           if (ch == '(')                /* ) */
3948             nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
3949           else if (ch == '{')           /* } */
3950             nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
3951           else if (ch == '[')           /* ] */
3952             nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
3953
3954           CHECK_NESTRET_ERROR ();
3955           APPEND_NESTRET ();
3956
3957           FREE (nestret);
3958         }
3959       if MBTEST(ch == '$')
3960         tflags |= LEX_WASDOL;
3961       else
3962         tflags &= ~LEX_WASDOL;
3963     }
3964
3965   FREE (heredelim);
3966   ret[retind] = '\0';
3967   if (lenp)
3968     *lenp = retind;
3969 /*itrace("parse_comsub:%d: returning `%s'", line_number, ret);*/
3970   return ret;
3971 }
3972
3973 /* Recursively call the parser to parse a $(...) command substitution. */
3974 char *
3975 xparse_dolparen (base, string, indp, flags)
3976      char *base;
3977      char *string;
3978      int *indp;
3979      int flags;
3980 {
3981   sh_parser_state_t ps;
3982   sh_input_line_state_t ls;
3983   int orig_ind, nc, sflags, orig_eof_token;
3984   char *ret, *s, *ep, *ostring;
3985
3986   /*yydebug = 1;*/
3987   orig_ind = *indp;
3988   ostring = string;
3989
3990 /*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/
3991   sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
3992   if (flags & SX_NOLONGJMP)
3993     sflags |= SEVAL_NOLONGJMP;
3994   save_parser_state (&ps);
3995   save_input_line_state (&ls);
3996   orig_eof_token = shell_eof_token;
3997
3998   /*(*/
3999   parser_state |= PST_CMDSUBST|PST_EOFTOKEN;    /* allow instant ')' */ /*(*/
4000   shell_eof_token = ')';
4001   parse_string (string, "command substitution", sflags, &ep);
4002
4003   shell_eof_token = orig_eof_token;
4004   restore_parser_state (&ps);
4005   reset_parser ();
4006   /* reset_parser clears shell_input_line and associated variables */
4007   restore_input_line_state (&ls);
4008   if (interactive)
4009     token_to_read = 0;
4010
4011   /* Need to find how many characters parse_and_execute consumed, update
4012      *indp, if flags != 0, copy the portion of the string parsed into RET
4013      and return it.  If flags & 1 (EX_NOALLOC) we can return NULL. */
4014
4015   /*(*/
4016   if (ep[-1] != ')')
4017     {
4018 #if DEBUG
4019       if (ep[-1] != '\n')
4020         itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
4021 #endif
4022       while (ep > ostring && ep[-1] == '\n') ep--;
4023     }
4024
4025   nc = ep - ostring;
4026   *indp = ep - base - 1;
4027
4028   /*(*/
4029 #if DEBUG
4030   if (base[*indp] != ')')
4031     itrace("xparse_dolparen:%d: base[%d] != RPAREN (%d), base = `%s'", line_number, *indp, base[*indp], base);
4032 #endif
4033
4034   if (flags & SX_NOALLOC) 
4035     return (char *)NULL;
4036
4037   if (nc == 0)
4038     {
4039       ret = xmalloc (1);
4040       ret[0] = '\0';
4041     }
4042   else
4043     ret = substring (ostring, 0, nc - 1);
4044
4045   return ret;
4046 }
4047
4048 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
4049 /* Parse a double-paren construct.  It can be either an arithmetic
4050    command, an arithmetic `for' command, or a nested subshell.  Returns
4051    the parsed token, -1 on error, or -2 if we didn't do anything and
4052    should just go on. */
4053 static int
4054 parse_dparen (c)
4055      int c;
4056 {
4057   int cmdtyp, sline;
4058   char *wval;
4059   WORD_DESC *wd;
4060
4061 #if defined (ARITH_FOR_COMMAND)
4062   if (last_read_token == FOR)
4063     {
4064       arith_for_lineno = line_number;
4065       cmdtyp = parse_arith_cmd (&wval, 0);
4066       if (cmdtyp == 1)
4067         {
4068           wd = alloc_word_desc ();
4069           wd->word = wval;
4070           yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
4071           return (ARITH_FOR_EXPRS);
4072         }
4073       else
4074         return -1;              /* ERROR */
4075     }
4076 #endif
4077
4078 #if defined (DPAREN_ARITHMETIC)
4079   if (reserved_word_acceptable (last_read_token))
4080     {
4081       sline = line_number;
4082
4083       cmdtyp = parse_arith_cmd (&wval, 0);
4084       if (cmdtyp == 1)  /* arithmetic command */
4085         {
4086           wd = alloc_word_desc ();
4087           wd->word = wval;
4088           wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
4089           yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
4090           return (ARITH_CMD);
4091         }
4092       else if (cmdtyp == 0)     /* nested subshell */
4093         {
4094           push_string (wval, 0, (alias_t *)NULL);
4095           pushed_string_list->flags = PSH_DPAREN;
4096           if ((parser_state & PST_CASEPAT) == 0)
4097             parser_state |= PST_SUBSHELL;
4098           return (c);
4099         }
4100       else                      /* ERROR */
4101         return -1;
4102     }
4103 #endif
4104
4105   return -2;                    /* XXX */
4106 }
4107
4108 /* We've seen a `(('.  Look for the matching `))'.  If we get it, return 1.
4109    If not, assume it's a nested subshell for backwards compatibility and
4110    return 0.  In any case, put the characters we've consumed into a locally-
4111    allocated buffer and make *ep point to that buffer.  Return -1 on an
4112    error, for example EOF. */
4113 static int
4114 parse_arith_cmd (ep, adddq)
4115      char **ep;
4116      int adddq;
4117 {
4118   int exp_lineno, rval, c;
4119   char *ttok, *tokstr;
4120   int ttoklen;
4121
4122   exp_lineno = line_number;
4123   ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
4124   rval = 1;
4125   if (ttok == &matched_pair_error)
4126     return -1;
4127   /* Check that the next character is the closing right paren.  If
4128      not, this is a syntax error. ( */
4129   c = shell_getc (0);
4130   if MBTEST(c != ')')
4131     rval = 0;
4132
4133   tokstr = (char *)xmalloc (ttoklen + 4);
4134
4135   /* if ADDDQ != 0 then (( ... )) -> "..." */
4136   if (rval == 1 && adddq)       /* arith cmd, add double quotes */
4137     {
4138       tokstr[0] = '"';
4139       strncpy (tokstr + 1, ttok, ttoklen - 1);
4140       tokstr[ttoklen] = '"';
4141       tokstr[ttoklen+1] = '\0';
4142     }
4143   else if (rval == 1)           /* arith cmd, don't add double quotes */
4144     {
4145       strncpy (tokstr, ttok, ttoklen - 1);
4146       tokstr[ttoklen-1] = '\0';
4147     }
4148   else                          /* nested subshell */
4149     {
4150       tokstr[0] = '(';
4151       strncpy (tokstr + 1, ttok, ttoklen - 1);
4152       tokstr[ttoklen] = ')';
4153       tokstr[ttoklen+1] = c;
4154       tokstr[ttoklen+2] = '\0';
4155     }
4156
4157   *ep = tokstr;
4158   FREE (ttok);
4159   return rval;
4160 }
4161 #endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
4162
4163 #if defined (COND_COMMAND)
4164 static void
4165 cond_error ()
4166 {
4167   char *etext;
4168
4169   if (EOF_Reached && cond_token != COND_ERROR)          /* [[ */
4170     parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
4171   else if (cond_token != COND_ERROR)
4172     {
4173       if (etext = error_token_from_token (cond_token))
4174         {
4175           parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
4176           free (etext);
4177         }
4178       else
4179         parser_error (cond_lineno, _("syntax error in conditional expression"));
4180     }
4181 }
4182
4183 static COND_COM *
4184 cond_expr ()
4185 {
4186   return (cond_or ());  
4187 }
4188
4189 static COND_COM *
4190 cond_or ()
4191 {
4192   COND_COM *l, *r;
4193
4194   l = cond_and ();
4195   if (cond_token == OR_OR)
4196     {
4197       r = cond_or ();
4198       l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
4199     }
4200   return l;
4201 }
4202
4203 static COND_COM *
4204 cond_and ()
4205 {
4206   COND_COM *l, *r;
4207
4208   l = cond_term ();
4209   if (cond_token == AND_AND)
4210     {
4211       r = cond_and ();
4212       l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
4213     }
4214   return l;
4215 }
4216
4217 static int
4218 cond_skip_newlines ()
4219 {
4220   while ((cond_token = read_token (READ)) == '\n')
4221     {
4222       if (SHOULD_PROMPT ())
4223         prompt_again ();
4224     }
4225   return (cond_token);
4226 }
4227
4228 #define COND_RETURN_ERROR() \
4229   do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
4230
4231 static COND_COM *
4232 cond_term ()
4233 {
4234   WORD_DESC *op;
4235   COND_COM *term, *tleft, *tright;
4236   int tok, lineno;
4237   char *etext;
4238
4239   /* Read a token.  It can be a left paren, a `!', a unary operator, or a
4240      word that should be the first argument of a binary operator.  Start by
4241      skipping newlines, since this is a compound command. */
4242   tok = cond_skip_newlines ();
4243   lineno = line_number;
4244   if (tok == COND_END)
4245     {
4246       COND_RETURN_ERROR ();
4247     }
4248   else if (tok == '(')
4249     {
4250       term = cond_expr ();
4251       if (cond_token != ')')
4252         {
4253           if (term)
4254             dispose_cond_node (term);           /* ( */
4255           if (etext = error_token_from_token (cond_token))
4256             {
4257               parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
4258               free (etext);
4259             }
4260           else
4261             parser_error (lineno, _("expected `)'"));
4262           COND_RETURN_ERROR ();
4263         }
4264       term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
4265       (void)cond_skip_newlines ();
4266     }
4267   else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
4268     {
4269       if (tok == WORD)
4270         dispose_word (yylval.word);     /* not needed */
4271       term = cond_term ();
4272       if (term)
4273         term->flags |= CMD_INVERT_RETURN;
4274     }
4275   else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
4276     {
4277       op = yylval.word;
4278       tok = read_token (READ);
4279       if (tok == WORD)
4280         {
4281           tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4282           term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
4283         }
4284       else
4285         {
4286           dispose_word (op);
4287           if (etext = error_token_from_token (tok))
4288             {
4289               parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
4290               free (etext);
4291             }
4292           else
4293             parser_error (line_number, _("unexpected argument to conditional unary operator"));
4294           COND_RETURN_ERROR ();
4295         }
4296
4297       (void)cond_skip_newlines ();
4298     }
4299   else if (tok == WORD)         /* left argument to binary operator */
4300     {
4301       /* lhs */
4302       tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4303
4304       /* binop */
4305       tok = read_token (READ);
4306       if (tok == WORD && test_binop (yylval.word->word))
4307         {
4308           op = yylval.word;
4309           if (op->word[0] == '=' && (op->word[1] == '\0' || (op->word[1] == '=' && op->word[2] == '\0')))
4310             parser_state |= PST_EXTPAT;
4311           else if (op->word[0] == '!' && op->word[1] == '=' && op->word[2] == '\0')
4312             parser_state |= PST_EXTPAT;
4313         }
4314 #if defined (COND_REGEXP)
4315       else if (tok == WORD && STREQ (yylval.word->word, "=~"))
4316         {
4317           op = yylval.word;
4318           parser_state |= PST_REGEXP;
4319         }
4320 #endif
4321       else if (tok == '<' || tok == '>')
4322         op = make_word_from_token (tok);  /* ( */
4323       /* There should be a check before blindly accepting the `)' that we have
4324          seen the opening `('. */
4325       else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
4326         {
4327           /* Special case.  [[ x ]] is equivalent to [[ -n x ]], just like
4328              the test command.  Similarly for [[ x && expr ]] or
4329              [[ x || expr ]] or [[ (x) ]]. */
4330           op = make_word ("-n");
4331           term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
4332           cond_token = tok;
4333           return (term);
4334         }
4335       else
4336         {
4337           if (etext = error_token_from_token (tok))
4338             {
4339               parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
4340               free (etext);
4341             }
4342           else
4343             parser_error (line_number, _("conditional binary operator expected"));
4344           dispose_cond_node (tleft);
4345           COND_RETURN_ERROR ();
4346         }
4347
4348       /* rhs */
4349       if (parser_state & PST_EXTPAT)
4350         extended_glob = 1;
4351       tok = read_token (READ);
4352       if (parser_state & PST_EXTPAT)
4353         extended_glob = global_extglob;
4354       parser_state &= ~(PST_REGEXP|PST_EXTPAT);
4355
4356       if (tok == WORD)
4357         {
4358           tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
4359           term = make_cond_node (COND_BINARY, op, tleft, tright);
4360         }
4361       else
4362         {
4363           if (etext = error_token_from_token (tok))
4364             {
4365               parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
4366               free (etext);
4367             }
4368           else
4369             parser_error (line_number, _("unexpected argument to conditional binary operator"));
4370           dispose_cond_node (tleft);
4371           dispose_word (op);
4372           COND_RETURN_ERROR ();
4373         }
4374
4375       (void)cond_skip_newlines ();
4376     }
4377   else
4378     {
4379       if (tok < 256)
4380         parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
4381       else if (etext = error_token_from_token (tok))
4382         {
4383           parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
4384           free (etext);
4385         }
4386       else
4387         parser_error (line_number, _("unexpected token %d in conditional command"), tok);
4388       COND_RETURN_ERROR ();
4389     }
4390   return (term);
4391 }      
4392
4393 /* This is kind of bogus -- we slip a mini recursive-descent parser in
4394    here to handle the conditional statement syntax. */
4395 static COMMAND *
4396 parse_cond_command ()
4397 {
4398   COND_COM *cexp;
4399
4400   global_extglob = extended_glob;
4401   cexp = cond_expr ();
4402   return (make_cond_command (cexp));
4403 }
4404 #endif
4405
4406 #if defined (ARRAY_VARS)
4407 /* When this is called, it's guaranteed that we don't care about anything
4408    in t beyond i.  We do save and restore the chars, though. */
4409 static int
4410 token_is_assignment (t, i)
4411      char *t;
4412      int i;
4413 {
4414   unsigned char c, c1;
4415   int r;
4416
4417   c = t[i]; c1 = t[i+1];
4418   t[i] = '='; t[i+1] = '\0';
4419   r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
4420   t[i] = c; t[i+1] = c1;
4421   return r;
4422 }
4423
4424 /* XXX - possible changes here for `+=' */
4425 static int
4426 token_is_ident (t, i)
4427      char *t;
4428      int i;
4429 {
4430   unsigned char c;
4431   int r;
4432
4433   c = t[i];
4434   t[i] = '\0';
4435   r = legal_identifier (t);
4436   t[i] = c;
4437   return r;
4438 }
4439 #endif
4440
4441 static int
4442 read_token_word (character)
4443      int character;
4444 {
4445   /* The value for YYLVAL when a WORD is read. */
4446   WORD_DESC *the_word;
4447
4448   /* Index into the token that we are building. */
4449   int token_index;
4450
4451   /* ALL_DIGITS becomes zero when we see a non-digit. */
4452   int all_digit_token;
4453
4454   /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
4455   int dollar_present;
4456
4457   /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
4458      assignment. */
4459   int compound_assignment;
4460
4461   /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
4462   int quoted;
4463
4464   /* Non-zero means to ignore the value of the next character, and just
4465      to add it no matter what. */
4466  int pass_next_character;
4467
4468   /* The current delimiting character. */
4469   int cd;
4470   int result, peek_char;
4471   char *ttok, *ttrans;
4472   int ttoklen, ttranslen;
4473   intmax_t lvalue;
4474
4475   if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
4476     token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
4477
4478   token_index = 0;
4479   all_digit_token = DIGIT (character);
4480   dollar_present = quoted = pass_next_character = compound_assignment = 0;
4481
4482   for (;;)
4483     {
4484       if (character == EOF)
4485         goto got_token;
4486
4487       if (pass_next_character)
4488         {
4489           pass_next_character = 0;
4490           goto got_escaped_character;
4491         }
4492
4493       cd = current_delimiter (dstack);
4494
4495       /* Handle backslashes.  Quote lots of things when not inside of
4496          double-quotes, quote some things inside of double-quotes. */
4497       if MBTEST(character == '\\')
4498         {
4499           peek_char = shell_getc (0);
4500
4501           /* Backslash-newline is ignored in all cases except
4502              when quoted with single quotes. */
4503           if (peek_char == '\n')
4504             {
4505               character = '\n';
4506               goto next_character;
4507             }
4508           else
4509             {
4510               shell_ungetc (peek_char);
4511
4512               /* If the next character is to be quoted, note it now. */
4513               if (cd == 0 || cd == '`' ||
4514                   (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
4515                 pass_next_character++;
4516
4517               quoted = 1;
4518               goto got_character;
4519             }
4520         }
4521
4522       /* Parse a matched pair of quote characters. */
4523       if MBTEST(shellquote (character))
4524         {
4525           push_delimiter (dstack, character);
4526           ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
4527           pop_delimiter (dstack);
4528           if (ttok == &matched_pair_error)
4529             return -1;          /* Bail immediately. */
4530           RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4531                                   token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
4532           token[token_index++] = character;
4533           strcpy (token + token_index, ttok);
4534           token_index += ttoklen;
4535           all_digit_token = 0;
4536           quoted = 1;
4537           dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
4538           FREE (ttok);
4539           goto next_character;
4540         }
4541
4542 #ifdef COND_REGEXP
4543       /* When parsing a regexp as a single word inside a conditional command,
4544          we need to special-case characters special to both the shell and
4545          regular expressions.  Right now, that is only '(' and '|'. */ /*)*/
4546       if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|'))          /*)*/
4547         {
4548           if (character == '|')
4549             goto got_character;
4550
4551           push_delimiter (dstack, character);
4552           ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
4553           pop_delimiter (dstack);
4554           if (ttok == &matched_pair_error)
4555             return -1;          /* Bail immediately. */
4556           RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4557                                   token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
4558           token[token_index++] = character;
4559           strcpy (token + token_index, ttok);
4560           token_index += ttoklen;
4561           FREE (ttok);
4562           dollar_present = all_digit_token = 0;
4563           goto next_character;
4564         }
4565 #endif /* COND_REGEXP */
4566
4567 #ifdef EXTENDED_GLOB
4568       /* Parse a ksh-style extended pattern matching specification. */
4569       if MBTEST(extended_glob && PATTERN_CHAR (character))
4570         {
4571           peek_char = shell_getc (1);
4572           if MBTEST(peek_char == '(')           /* ) */
4573             {
4574               push_delimiter (dstack, peek_char);
4575               ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
4576               pop_delimiter (dstack);
4577               if (ttok == &matched_pair_error)
4578                 return -1;              /* Bail immediately. */
4579               RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
4580                                       token_buffer_size,
4581                                       TOKEN_DEFAULT_GROW_SIZE);
4582               token[token_index++] = character;
4583               token[token_index++] = peek_char;
4584               strcpy (token + token_index, ttok);
4585               token_index += ttoklen;
4586               FREE (ttok);
4587               dollar_present = all_digit_token = 0;
4588               goto next_character;
4589             }
4590           else
4591             shell_ungetc (peek_char);
4592         }
4593 #endif /* EXTENDED_GLOB */
4594
4595       /* If the delimiter character is not single quote, parse some of
4596          the shell expansions that must be read as a single word. */
4597       if (shellexp (character))
4598         {
4599           peek_char = shell_getc (1);
4600           /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
4601           if MBTEST(peek_char == '(' ||
4602                 ((peek_char == '{' || peek_char == '[') && character == '$'))   /* ) ] } */
4603             {
4604               if (peek_char == '{')             /* } */
4605                 ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE|P_DOLBRACE);
4606               else if (peek_char == '(')                /* ) */
4607                 {
4608                   /* XXX - push and pop the `(' as a delimiter for use by
4609                      the command-oriented-history code.  This way newlines
4610                      appearing in the $(...) string get added to the
4611                      history literally rather than causing a possibly-
4612                      incorrect `;' to be added. ) */
4613                   push_delimiter (dstack, peek_char);
4614                   ttok = parse_comsub (cd, '(', ')', &ttoklen, P_COMMAND);
4615                   pop_delimiter (dstack);
4616                 }
4617               else
4618                 ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
4619               if (ttok == &matched_pair_error)
4620                 return -1;              /* Bail immediately. */
4621               RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
4622                                       token_buffer_size,
4623                                       TOKEN_DEFAULT_GROW_SIZE);
4624               token[token_index++] = character;
4625               token[token_index++] = peek_char;
4626               strcpy (token + token_index, ttok);
4627               token_index += ttoklen;
4628               FREE (ttok);
4629               dollar_present = 1;
4630               all_digit_token = 0;
4631               goto next_character;
4632             }
4633           /* This handles $'...' and $"..." new-style quoted strings. */
4634           else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
4635             {
4636               int first_line;
4637
4638               first_line = line_number;
4639               push_delimiter (dstack, peek_char);
4640               ttok = parse_matched_pair (peek_char, peek_char, peek_char,
4641                                          &ttoklen,
4642                                          (peek_char == '\'') ? P_ALLOWESC : 0);
4643               pop_delimiter (dstack);
4644               if (ttok == &matched_pair_error)
4645                 return -1;
4646               if (peek_char == '\'')
4647                 {
4648                   ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
4649                   free (ttok);
4650
4651                   /* Insert the single quotes and correctly quote any
4652                      embedded single quotes (allowed because P_ALLOWESC was
4653                      passed to parse_matched_pair). */
4654                   ttok = sh_single_quote (ttrans);
4655                   free (ttrans);
4656                   ttranslen = strlen (ttok);
4657                   ttrans = ttok;
4658                 }
4659               else
4660                 {
4661                   /* Try to locale-expand the converted string. */
4662                   ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
4663                   free (ttok);
4664
4665                   /* Add the double quotes back */
4666                   ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
4667                   free (ttrans);
4668                   ttranslen += 2;
4669                   ttrans = ttok;
4670                 }
4671
4672               RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 1,
4673                                       token_buffer_size,
4674                                       TOKEN_DEFAULT_GROW_SIZE);
4675               strcpy (token + token_index, ttrans);
4676               token_index += ttranslen;
4677               FREE (ttrans);
4678               quoted = 1;
4679               all_digit_token = 0;
4680               goto next_character;
4681             }
4682           /* This could eventually be extended to recognize all of the
4683              shell's single-character parameter expansions, and set flags.*/
4684           else if MBTEST(character == '$' && peek_char == '$')
4685             {
4686               RESIZE_MALLOCED_BUFFER (token, token_index, 3,
4687                                       token_buffer_size,
4688                                       TOKEN_DEFAULT_GROW_SIZE);
4689               token[token_index++] = '$';
4690               token[token_index++] = peek_char;
4691               dollar_present = 1;
4692               all_digit_token = 0;
4693               goto next_character;
4694             }
4695           else
4696             shell_ungetc (peek_char);
4697         }
4698
4699 #if defined (ARRAY_VARS)
4700       /* Identify possible array subscript assignment; match [...].  If
4701          parser_state&PST_COMPASSIGN, we need to parse [sub]=words treating
4702          `sub' as if it were enclosed in double quotes. */
4703       else if MBTEST(character == '[' &&                /* ] */
4704                      ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
4705                       (token_index == 0 && (parser_state&PST_COMPASSIGN))))
4706         {
4707           ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
4708           if (ttok == &matched_pair_error)
4709             return -1;          /* Bail immediately. */
4710           RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
4711                                   token_buffer_size,
4712                                   TOKEN_DEFAULT_GROW_SIZE);
4713           token[token_index++] = character;
4714           strcpy (token + token_index, ttok);
4715           token_index += ttoklen;
4716           FREE (ttok);
4717           all_digit_token = 0;
4718           goto next_character;
4719         }
4720       /* Identify possible compound array variable assignment. */
4721       else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
4722         {
4723           peek_char = shell_getc (1);
4724           if MBTEST(peek_char == '(')           /* ) */
4725             {
4726               ttok = parse_compound_assignment (&ttoklen);
4727
4728               RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
4729                                       token_buffer_size,
4730                                       TOKEN_DEFAULT_GROW_SIZE);
4731
4732               token[token_index++] = '=';
4733               token[token_index++] = '(';
4734               if (ttok)
4735                 {
4736                   strcpy (token + token_index, ttok);
4737                   token_index += ttoklen;
4738                 }
4739               token[token_index++] = ')';
4740               FREE (ttok);
4741               all_digit_token = 0;
4742               compound_assignment = 1;
4743 #if 1
4744               goto next_character;
4745 #else
4746               goto got_token;           /* ksh93 seems to do this */
4747 #endif
4748             }
4749           else
4750             shell_ungetc (peek_char);
4751         }
4752 #endif
4753
4754       /* When not parsing a multi-character word construct, shell meta-
4755          characters break words. */
4756       if MBTEST(shellbreak (character))
4757         {
4758           shell_ungetc (character);
4759           goto got_token;
4760         }
4761
4762 got_character:
4763
4764       if (character == CTLESC || character == CTLNUL)
4765         {
4766           RESIZE_MALLOCED_BUFFER (token, token_index, 2, token_buffer_size,
4767                                   TOKEN_DEFAULT_GROW_SIZE);
4768           token[token_index++] = CTLESC;
4769         }
4770       else
4771 got_escaped_character:
4772         RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
4773                                 TOKEN_DEFAULT_GROW_SIZE);
4774
4775       token[token_index++] = character;
4776
4777       all_digit_token &= DIGIT (character);
4778       dollar_present |= character == '$';
4779
4780     next_character:
4781       if (character == '\n' && SHOULD_PROMPT ())
4782         prompt_again ();
4783
4784       /* We want to remove quoted newlines (that is, a \<newline> pair)
4785          unless we are within single quotes or pass_next_character is
4786          set (the shell equivalent of literal-next). */
4787       cd = current_delimiter (dstack);
4788       character = shell_getc (cd != '\'' && pass_next_character == 0);
4789     }   /* end for (;;) */
4790
4791 got_token:
4792
4793   /* Calls to RESIZE_MALLOCED_BUFFER ensure there is sufficient room. */
4794   token[token_index] = '\0';
4795
4796   /* Check to see what thing we should return.  If the last_read_token
4797      is a `<', or a `&', or the character which ended this token is
4798      a '>' or '<', then, and ONLY then, is this input token a NUMBER.
4799      Otherwise, it is just a word, and should be returned as such. */
4800   if MBTEST(all_digit_token && (character == '<' || character == '>' ||
4801                     last_read_token == LESS_AND ||
4802                     last_read_token == GREATER_AND))
4803       {
4804         if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
4805           {
4806             yylval.number = lvalue;
4807             return (NUMBER);
4808           }
4809       }
4810
4811   /* Check for special case tokens. */
4812   result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
4813   if (result >= 0)
4814     return result;
4815
4816 #if defined (ALIAS)
4817   /* Posix.2 does not allow reserved words to be aliased, so check for all
4818      of them, including special cases, before expanding the current token
4819      as an alias. */
4820   if MBTEST(posixly_correct)
4821     CHECK_FOR_RESERVED_WORD (token);
4822
4823   /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
4824      inhibits alias expansion. */
4825   if (expand_aliases && quoted == 0)
4826     {
4827       result = alias_expand_token (token);
4828       if (result == RE_READ_TOKEN)
4829         return (RE_READ_TOKEN);
4830       else if (result == NO_EXPANSION)
4831         parser_state &= ~PST_ALEXPNEXT;
4832     }
4833
4834   /* If not in Posix.2 mode, check for reserved words after alias
4835      expansion. */
4836   if MBTEST(posixly_correct == 0)
4837 #endif
4838     CHECK_FOR_RESERVED_WORD (token);
4839
4840   the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
4841   the_word->word = (char *)xmalloc (1 + token_index);
4842   the_word->flags = 0;
4843   strcpy (the_word->word, token);
4844   if (dollar_present)
4845     the_word->flags |= W_HASDOLLAR;
4846   if (quoted)
4847     the_word->flags |= W_QUOTED;                /*(*/
4848   if (compound_assignment && token[token_index-1] == ')')
4849     the_word->flags |= W_COMPASSIGN;
4850   /* A word is an assignment if it appears at the beginning of a
4851      simple command, or after another assignment word.  This is
4852      context-dependent, so it cannot be handled in the grammar. */
4853   if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
4854     {
4855       the_word->flags |= W_ASSIGNMENT;
4856       /* Don't perform word splitting on assignment statements. */
4857       if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
4858         {
4859           the_word->flags |= W_NOSPLIT;
4860           if (parser_state & PST_COMPASSIGN)
4861             the_word->flags |= W_NOGLOB;        /* XXX - W_NOBRACE? */
4862         }
4863     }
4864
4865   if (command_token_position (last_read_token))
4866     {
4867       struct builtin *b;
4868       b = builtin_address_internal (token, 0);
4869       if (b && (b->flags & ASSIGNMENT_BUILTIN))
4870         parser_state |= PST_ASSIGNOK;
4871       else if (STREQ (token, "eval") || STREQ (token, "let"))
4872         parser_state |= PST_ASSIGNOK;
4873     }
4874
4875   yylval.word = the_word;
4876
4877   if (token[0] == '{' && token[token_index-1] == '}' &&
4878       (character == '<' || character == '>'))
4879     {
4880       /* can use token; already copied to the_word */
4881       token[token_index-1] = '\0';
4882 #if defined (ARRAY_VARS)
4883       if (legal_identifier (token+1) || valid_array_reference (token+1))
4884 #else
4885       if (legal_identifier (token+1))
4886 #endif
4887         {
4888           strcpy (the_word->word, token+1);
4889 /*itrace("read_token_word: returning REDIR_WORD for %s", the_word->word);*/
4890           return (REDIR_WORD);
4891         }
4892     }
4893
4894   result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
4895                 ? ASSIGNMENT_WORD : WORD;
4896
4897   switch (last_read_token)
4898     {
4899     case FUNCTION:
4900       parser_state |= PST_ALLOWOPNBRC;
4901       function_dstart = line_number;
4902       break;
4903     case CASE:
4904     case SELECT:
4905     case FOR:
4906       if (word_top < MAX_CASE_NEST)
4907         word_top++;
4908       word_lineno[word_top] = line_number;
4909       break;
4910     }
4911
4912   return (result);
4913 }
4914
4915 /* Return 1 if TOKSYM is a token that after being read would allow
4916    a reserved word to be seen, else 0. */
4917 static int
4918 reserved_word_acceptable (toksym)
4919      int toksym;
4920 {
4921   switch (toksym)
4922     {
4923     case '\n':
4924     case ';':
4925     case '(':
4926     case ')':
4927     case '|':
4928     case '&':
4929     case '{':
4930     case '}':           /* XXX */
4931     case AND_AND:
4932     case BANG:
4933     case BAR_AND:
4934     case DO:
4935     case DONE:
4936     case ELIF:
4937     case ELSE:
4938     case ESAC:
4939     case FI:
4940     case IF:
4941     case OR_OR:
4942     case SEMI_SEMI:
4943     case SEMI_AND:
4944     case SEMI_SEMI_AND:
4945     case THEN:
4946     case TIME:
4947     case TIMEOPT:
4948     case TIMEIGN:
4949     case COPROC:
4950     case UNTIL:
4951     case WHILE:
4952     case 0:
4953       return 1;
4954     default:
4955 #if defined (COPROCESS_SUPPORT)
4956       if (last_read_token == WORD && token_before_that == COPROC)
4957         return 1;
4958 #endif
4959       if (last_read_token == WORD && token_before_that == FUNCTION)
4960         return 1;
4961       return 0;
4962     }
4963 }
4964     
4965 /* Return the index of TOKEN in the alist of reserved words, or -1 if
4966    TOKEN is not a shell reserved word. */
4967 int
4968 find_reserved_word (tokstr)
4969      char *tokstr;
4970 {
4971   int i;
4972   for (i = 0; word_token_alist[i].word; i++)
4973     if (STREQ (tokstr, word_token_alist[i].word))
4974       return i;
4975   return -1;
4976 }
4977
4978 /* An interface to let the rest of the shell (primarily the completion
4979    system) know what the parser is expecting. */
4980 int
4981 parser_in_command_position ()
4982 {
4983   return (command_token_position (last_read_token));
4984 }
4985
4986 #if 0
4987 #if defined (READLINE)
4988 /* Called after each time readline is called.  This insures that whatever
4989    the new prompt string is gets propagated to readline's local prompt
4990    variable. */
4991 static void
4992 reset_readline_prompt ()
4993 {
4994   char *temp_prompt;
4995
4996   if (prompt_string_pointer)
4997     {
4998       temp_prompt = (*prompt_string_pointer)
4999                         ? decode_prompt_string (*prompt_string_pointer)
5000                         : (char *)NULL;
5001
5002       if (temp_prompt == 0)
5003         {
5004           temp_prompt = (char *)xmalloc (1);
5005           temp_prompt[0] = '\0';
5006         }
5007
5008       FREE (current_readline_prompt);
5009       current_readline_prompt = temp_prompt;
5010     }
5011 }
5012 #endif /* READLINE */
5013 #endif /* 0 */
5014
5015 #if defined (HISTORY)
5016 /* A list of tokens which can be followed by newlines, but not by
5017    semi-colons.  When concatenating multiple lines of history, the
5018    newline separator for such tokens is replaced with a space. */
5019 static const int no_semi_successors[] = {
5020   '\n', '{', '(', ')', ';', '&', '|',
5021   CASE, DO, ELSE, IF, SEMI_SEMI, SEMI_AND, SEMI_SEMI_AND, THEN, UNTIL,
5022   WHILE, AND_AND, OR_OR, IN,
5023   0
5024 };
5025
5026 /* If we are not within a delimited expression, try to be smart
5027    about which separators can be semi-colons and which must be
5028    newlines.  Returns the string that should be added into the
5029    history entry.  LINE is the line we're about to add; it helps
5030    make some more intelligent decisions in certain cases. */
5031 char *
5032 history_delimiting_chars (line)
5033      const char *line;
5034 {
5035   static int last_was_heredoc = 0;      /* was the last entry the start of a here document? */
5036   register int i;
5037
5038   if ((parser_state & PST_HEREDOC) == 0)
5039     last_was_heredoc = 0;
5040
5041   if (dstack.delimiter_depth != 0)
5042     return ("\n");
5043
5044   /* We look for current_command_line_count == 2 because we are looking to
5045      add the first line of the body of the here document (the second line
5046      of the command).  We also keep LAST_WAS_HEREDOC as a private sentinel
5047      variable to note when we think we added the first line of a here doc
5048      (the one with a "<<" somewhere in it) */
5049   if (parser_state & PST_HEREDOC)
5050     {
5051       if (last_was_heredoc)
5052         {
5053           last_was_heredoc = 0;
5054           return "\n";
5055         }
5056       return (current_command_line_count == 2 ? "\n" : "");
5057     }
5058
5059   if (parser_state & PST_COMPASSIGN)
5060     return (" ");
5061
5062   /* First, handle some special cases. */
5063   /*(*/
5064   /* If we just read `()', assume it's a function definition, and don't
5065      add a semicolon.  If the token before the `)' was not `(', and we're
5066      not in the midst of parsing a case statement, assume it's a
5067      parenthesized command and add the semicolon. */
5068   /*)(*/
5069   if (token_before_that == ')')
5070     {
5071       if (two_tokens_ago == '(')        /*)*/   /* function def */
5072         return " ";
5073       /* This does not work for subshells inside case statement
5074          command lists.  It's a suboptimal solution. */
5075       else if (parser_state & PST_CASESTMT)     /* case statement pattern */
5076         return " ";
5077       else      
5078         return "; ";                            /* (...) subshell */
5079     }
5080   else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
5081     return " ";         /* function def using `function name' without `()' */
5082
5083   /* If we're not in a here document, but we think we're about to parse one,
5084      and we would otherwise return a `;', return a newline to delimit the
5085      line with the here-doc delimiter */
5086   else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
5087     {
5088       last_was_heredoc = 1;
5089       return "\n";
5090     }
5091
5092   else if (token_before_that == WORD && two_tokens_ago == FOR)
5093     {
5094       /* Tricky.  `for i\nin ...' should not have a semicolon, but
5095          `for i\ndo ...' should.  We do what we can. */
5096       for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
5097         ;
5098       if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
5099         return " ";
5100       return ";";
5101     }
5102   else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
5103     return " ";
5104
5105   for (i = 0; no_semi_successors[i]; i++)
5106     {
5107       if (token_before_that == no_semi_successors[i])
5108         return (" ");
5109     }
5110
5111   return ("; ");
5112 }
5113 #endif /* HISTORY */
5114
5115 /* Issue a prompt, or prepare to issue a prompt when the next character
5116    is read. */
5117 static void
5118 prompt_again ()
5119 {
5120   char *temp_prompt;
5121
5122   if (interactive == 0 || expanding_alias ())   /* XXX */
5123     return;
5124
5125   ps1_prompt = get_string_value ("PS1");
5126   ps2_prompt = get_string_value ("PS2");
5127
5128   if (!prompt_string_pointer)
5129     prompt_string_pointer = &ps1_prompt;
5130
5131   temp_prompt = *prompt_string_pointer
5132                         ? decode_prompt_string (*prompt_string_pointer)
5133                         : (char *)NULL;
5134
5135   if (temp_prompt == 0)
5136     {
5137       temp_prompt = (char *)xmalloc (1);
5138       temp_prompt[0] = '\0';
5139     }
5140
5141   current_prompt_string = *prompt_string_pointer;
5142   prompt_string_pointer = &ps2_prompt;
5143
5144 #if defined (READLINE)
5145   if (!no_line_editing)
5146     {
5147       FREE (current_readline_prompt);
5148       current_readline_prompt = temp_prompt;
5149     }
5150   else
5151 #endif  /* READLINE */
5152     {
5153       FREE (current_decoded_prompt);
5154       current_decoded_prompt = temp_prompt;
5155     }
5156 }
5157
5158 int
5159 get_current_prompt_level ()
5160 {
5161   return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
5162 }
5163
5164 void
5165 set_current_prompt_level (x)
5166      int x;
5167 {
5168   prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
5169   current_prompt_string = *prompt_string_pointer;
5170 }
5171       
5172 static void
5173 print_prompt ()
5174 {
5175   fprintf (stderr, "%s", current_decoded_prompt);
5176   fflush (stderr);
5177 }
5178
5179 /* Return a string which will be printed as a prompt.  The string
5180    may contain special characters which are decoded as follows:
5181
5182         \a      bell (ascii 07)
5183         \d      the date in Day Mon Date format
5184         \e      escape (ascii 033)
5185         \h      the hostname up to the first `.'
5186         \H      the hostname
5187         \j      the number of active jobs
5188         \l      the basename of the shell's tty device name
5189         \n      CRLF
5190         \r      CR
5191         \s      the name of the shell
5192         \t      the time in 24-hour hh:mm:ss format
5193         \T      the time in 12-hour hh:mm:ss format
5194         \@      the time in 12-hour hh:mm am/pm format
5195         \A      the time in 24-hour hh:mm format
5196         \D{fmt} the result of passing FMT to strftime(3)
5197         \u      your username
5198         \v      the version of bash (e.g., 2.00)
5199         \V      the release of bash, version + patchlevel (e.g., 2.00.0)
5200         \w      the current working directory
5201         \W      the last element of $PWD
5202         \!      the history number of this command
5203         \#      the command number of this command
5204         \$      a $ or a # if you are root
5205         \nnn    character code nnn in octal
5206         \\      a backslash
5207         \[      begin a sequence of non-printing chars
5208         \]      end a sequence of non-printing chars
5209 */
5210 #define PROMPT_GROWTH 48
5211 char *
5212 decode_prompt_string (string)
5213      char *string;
5214 {
5215   WORD_LIST *list;
5216   char *result, *t;
5217   struct dstack save_dstack;
5218   int last_exit_value, last_comsub_pid;
5219 #if defined (PROMPT_STRING_DECODE)
5220   int result_size, result_index;
5221   int c, n, i;
5222   char *temp, octal_string[4];
5223   struct tm *tm;  
5224   time_t the_time;
5225   char timebuf[128];
5226   char *timefmt;
5227
5228   result = (char *)xmalloc (result_size = PROMPT_GROWTH);
5229   result[result_index = 0] = 0;
5230   temp = (char *)NULL;
5231
5232   while (c = *string++)
5233     {
5234       if (posixly_correct && c == '!')
5235         {
5236           if (*string == '!')
5237             {
5238               temp = savestring ("!");
5239               goto add_string;
5240             }
5241           else
5242             {
5243 #if !defined (HISTORY)
5244                 temp = savestring ("1");
5245 #else /* HISTORY */
5246                 temp = itos (history_number ());
5247 #endif /* HISTORY */
5248                 string--;       /* add_string increments string again. */
5249                 goto add_string;
5250             }
5251         }
5252       if (c == '\\')
5253         {
5254           c = *string;
5255
5256           switch (c)
5257             {
5258             case '0':
5259             case '1':
5260             case '2':
5261             case '3':
5262             case '4':
5263             case '5':
5264             case '6':
5265             case '7':
5266               strncpy (octal_string, string, 3);
5267               octal_string[3] = '\0';
5268
5269               n = read_octal (octal_string);
5270               temp = (char *)xmalloc (3);
5271
5272               if (n == CTLESC || n == CTLNUL)
5273                 {
5274                   temp[0] = CTLESC;
5275                   temp[1] = n;
5276                   temp[2] = '\0';
5277                 }
5278               else if (n == -1)
5279                 {
5280                   temp[0] = '\\';
5281                   temp[1] = '\0';
5282                 }
5283               else
5284                 {
5285                   temp[0] = n;
5286                   temp[1] = '\0';
5287                 }
5288
5289               for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
5290                 string++;
5291
5292               c = 0;            /* tested at add_string: */
5293               goto add_string;
5294
5295             case 'd':
5296             case 't':
5297             case 'T':
5298             case '@':
5299             case 'A':
5300               /* Make the current time/date into a string. */
5301               (void) time (&the_time);
5302 #if defined (HAVE_TZSET)
5303               sv_tz ("TZ");             /* XXX -- just make sure */
5304 #endif
5305               tm = localtime (&the_time);
5306
5307               if (c == 'd')
5308                 n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
5309               else if (c == 't')
5310                 n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
5311               else if (c == 'T')
5312                 n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
5313               else if (c == '@')
5314                 n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
5315               else if (c == 'A')
5316                 n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
5317
5318               if (n == 0)
5319                 timebuf[0] = '\0';
5320               else
5321                 timebuf[sizeof(timebuf) - 1] = '\0';
5322
5323               temp = savestring (timebuf);
5324               goto add_string;
5325
5326             case 'D':           /* strftime format */
5327               if (string[1] != '{')             /* } */
5328                 goto not_escape;
5329
5330               (void) time (&the_time);
5331               tm = localtime (&the_time);
5332               string += 2;                      /* skip { */
5333               timefmt = xmalloc (strlen (string) + 3);
5334               for (t = timefmt; *string && *string != '}'; )
5335                 *t++ = *string++;
5336               *t = '\0';
5337               c = *string;      /* tested at add_string */
5338               if (timefmt[0] == '\0')
5339                 {
5340                   timefmt[0] = '%';
5341                   timefmt[1] = 'X';     /* locale-specific current time */
5342                   timefmt[2] = '\0';
5343                 }
5344               n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
5345               free (timefmt);
5346
5347               if (n == 0)
5348                 timebuf[0] = '\0';
5349               else
5350                 timebuf[sizeof(timebuf) - 1] = '\0';
5351
5352               if (promptvars || posixly_correct)
5353                 /* Make sure that expand_prompt_string is called with a
5354                    second argument of Q_DOUBLE_QUOTES if we use this
5355                    function here. */
5356                 temp = sh_backslash_quote_for_double_quotes (timebuf);
5357               else
5358                 temp = savestring (timebuf);
5359               goto add_string;
5360               
5361             case 'n':
5362               temp = (char *)xmalloc (3);
5363               temp[0] = no_line_editing ? '\n' : '\r';
5364               temp[1] = no_line_editing ? '\0' : '\n';
5365               temp[2] = '\0';
5366               goto add_string;
5367
5368             case 's':
5369               temp = base_pathname (shell_name);
5370               temp = savestring (temp);
5371               goto add_string;
5372
5373             case 'v':
5374             case 'V':
5375               temp = (char *)xmalloc (16);
5376               if (c == 'v')
5377                 strcpy (temp, dist_version);
5378               else
5379                 sprintf (temp, "%s.%d", dist_version, patch_level);
5380               goto add_string;
5381
5382             case 'w':
5383             case 'W':
5384               {
5385                 /* Use the value of PWD because it is much more efficient. */
5386                 char t_string[PATH_MAX];
5387                 int tlen;
5388
5389                 temp = get_string_value ("PWD");
5390
5391                 if (temp == 0)
5392                   {
5393                     if (getcwd (t_string, sizeof(t_string)) == 0)
5394                       {
5395                         t_string[0] = '.';
5396                         tlen = 1;
5397                       }
5398                     else
5399                       tlen = strlen (t_string);
5400                   }
5401                 else
5402                   {
5403                     tlen = sizeof (t_string) - 1;
5404                     strncpy (t_string, temp, tlen);
5405                   }
5406                 t_string[tlen] = '\0';
5407
5408 #if defined (MACOSX)
5409                 /* Convert from "fs" format to "input" format */
5410                 temp = fnx_fromfs (t_string, strlen (t_string));
5411                 if (temp != t_string)
5412                   strcpy (t_string, temp);
5413 #endif
5414
5415 #define ROOT_PATH(x)    ((x)[0] == '/' && (x)[1] == 0)
5416 #define DOUBLE_SLASH_ROOT(x)    ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
5417                 /* Abbreviate \W as ~ if $PWD == $HOME */
5418                 if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
5419                   {
5420                     if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
5421                       {
5422                         t = strrchr (t_string, '/');
5423                         if (t)
5424                           memmove (t_string, t + 1, strlen (t));        /* strlen(t) to copy NULL */
5425                       }
5426                   }
5427 #undef ROOT_PATH
5428 #undef DOUBLE_SLASH_ROOT
5429                 else
5430                   {
5431                     /* polite_directory_format is guaranteed to return a string
5432                        no longer than PATH_MAX - 1 characters. */
5433                     temp = polite_directory_format (t_string);
5434                     if (temp != t_string)
5435                       strcpy (t_string, temp);
5436                   }
5437
5438                 temp = trim_pathname (t_string, PATH_MAX - 1);
5439                 /* If we're going to be expanding the prompt string later,
5440                    quote the directory name. */
5441                 if (promptvars || posixly_correct)
5442                   /* Make sure that expand_prompt_string is called with a
5443                      second argument of Q_DOUBLE_QUOTES if we use this
5444                      function here. */
5445                   temp = sh_backslash_quote_for_double_quotes (t_string);
5446                 else
5447                   temp = savestring (t_string);
5448
5449                 goto add_string;
5450               }
5451
5452             case 'u':
5453               if (current_user.user_name == 0)
5454                 get_current_user_info ();
5455               temp = savestring (current_user.user_name);
5456               goto add_string;
5457
5458             case 'h':
5459             case 'H':
5460               temp = savestring (current_host_name);
5461               if (c == 'h' && (t = (char *)strchr (temp, '.')))
5462                 *t = '\0';
5463               goto add_string;
5464
5465             case '#':
5466               temp = itos (current_command_number);
5467               goto add_string;
5468
5469             case '!':
5470 #if !defined (HISTORY)
5471               temp = savestring ("1");
5472 #else /* HISTORY */
5473               temp = itos (history_number ());
5474 #endif /* HISTORY */
5475               goto add_string;
5476
5477             case '$':
5478               t = temp = (char *)xmalloc (3);
5479               if ((promptvars || posixly_correct) && (current_user.euid != 0))
5480                 *t++ = '\\';
5481               *t++ = current_user.euid == 0 ? '#' : '$';
5482               *t = '\0';
5483               goto add_string;
5484
5485             case 'j':
5486               temp = itos (count_all_jobs ());
5487               goto add_string;
5488
5489             case 'l':
5490 #if defined (HAVE_TTYNAME)
5491               temp = (char *)ttyname (fileno (stdin));
5492               t = temp ? base_pathname (temp) : "tty";
5493               temp = savestring (t);
5494 #else
5495               temp = savestring ("tty");
5496 #endif /* !HAVE_TTYNAME */
5497               goto add_string;
5498
5499 #if defined (READLINE)
5500             case '[':
5501             case ']':
5502               if (no_line_editing)
5503                 {
5504                   string++;
5505                   break;
5506                 }
5507               temp = (char *)xmalloc (3);
5508               n = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
5509               i = 0;
5510               if (n == CTLESC || n == CTLNUL)
5511                 temp[i++] = CTLESC;
5512               temp[i++] = n;
5513               temp[i] = '\0';
5514               goto add_string;
5515 #endif /* READLINE */
5516
5517             case '\\':
5518             case 'a':
5519             case 'e':
5520             case 'r':
5521               temp = (char *)xmalloc (2);
5522               if (c == 'a')
5523                 temp[0] = '\07';
5524               else if (c == 'e')
5525                 temp[0] = '\033';
5526               else if (c == 'r')
5527                 temp[0] = '\r';
5528               else                      /* (c == '\\') */
5529                 temp[0] = c;
5530               temp[1] = '\0';
5531               goto add_string;
5532
5533             default:
5534 not_escape:
5535               temp = (char *)xmalloc (3);
5536               temp[0] = '\\';
5537               temp[1] = c;
5538               temp[2] = '\0';
5539
5540             add_string:
5541               if (c)
5542                 string++;
5543               result =
5544                 sub_append_string (temp, result, &result_index, &result_size);
5545               temp = (char *)NULL; /* Freed in sub_append_string (). */
5546               result[result_index] = '\0';
5547               break;
5548             }
5549         }
5550       else
5551         {
5552           RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
5553           result[result_index++] = c;
5554           result[result_index] = '\0';
5555         }
5556     }
5557 #else /* !PROMPT_STRING_DECODE */
5558   result = savestring (string);
5559 #endif /* !PROMPT_STRING_DECODE */
5560
5561   /* Save the delimiter stack and point `dstack' to temp space so any
5562      command substitutions in the prompt string won't result in screwing
5563      up the parser's quoting state. */
5564   save_dstack = dstack;
5565   dstack = temp_dstack;
5566   dstack.delimiter_depth = 0;
5567
5568   /* Perform variable and parameter expansion and command substitution on
5569      the prompt string. */
5570   if (promptvars || posixly_correct)
5571     {
5572       last_exit_value = last_command_exit_value;
5573       last_comsub_pid = last_command_subst_pid;
5574       list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
5575       free (result);
5576       result = string_list (list);
5577       dispose_words (list);
5578       last_command_exit_value = last_exit_value;
5579       last_command_subst_pid = last_comsub_pid;
5580     }
5581   else
5582     {
5583       t = dequote_string (result);
5584       free (result);
5585       result = t;
5586     }
5587
5588   dstack = save_dstack;
5589
5590   return (result);
5591 }
5592
5593 /************************************************
5594  *                                              *
5595  *              ERROR HANDLING                  *
5596  *                                              *
5597  ************************************************/
5598
5599 /* Report a syntax error, and restart the parser.  Call here for fatal
5600    errors. */
5601 int
5602 yyerror (msg)
5603      const char *msg;
5604 {
5605   report_syntax_error ((char *)NULL);
5606   reset_parser ();
5607   return (0);
5608 }
5609
5610 static char *
5611 error_token_from_token (tok)
5612      int tok;
5613 {
5614   char *t;
5615
5616   if (t = find_token_in_alist (tok, word_token_alist, 0))
5617     return t;
5618
5619   if (t = find_token_in_alist (tok, other_token_alist, 0))
5620     return t;
5621
5622   t = (char *)NULL;
5623   /* This stuff is dicy and needs closer inspection */
5624   switch (current_token)
5625     {
5626     case WORD:
5627     case ASSIGNMENT_WORD:
5628       if (yylval.word)
5629         t = savestring (yylval.word->word);
5630       break;
5631     case NUMBER:
5632       t = itos (yylval.number);
5633       break;
5634     case ARITH_CMD:
5635       if (yylval.word_list)
5636         t = string_list (yylval.word_list);
5637       break;
5638     case ARITH_FOR_EXPRS:
5639       if (yylval.word_list)
5640         t = string_list_internal (yylval.word_list, " ; ");
5641       break;
5642     case COND_CMD:
5643       t = (char *)NULL;         /* punt */
5644       break;
5645     }
5646
5647   return t;
5648 }
5649
5650 static char *
5651 error_token_from_text ()
5652 {
5653   char *msg, *t;
5654   int token_end, i;
5655
5656   t = shell_input_line;
5657   i = shell_input_line_index;
5658   token_end = 0;
5659   msg = (char *)NULL;
5660
5661   if (i && t[i] == '\0')
5662     i--;
5663
5664   while (i && (whitespace (t[i]) || t[i] == '\n'))
5665     i--;
5666
5667   if (i)
5668     token_end = i + 1;
5669
5670   while (i && (member (t[i], " \n\t;|&") == 0))
5671     i--;
5672
5673   while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
5674     i++;
5675
5676   /* Return our idea of the offending token. */
5677   if (token_end || (i == 0 && token_end == 0))
5678     {
5679       if (token_end)
5680         msg = substring (t, i, token_end);
5681       else      /* one-character token */
5682         {
5683           msg = (char *)xmalloc (2);
5684           msg[0] = t[i];
5685           msg[1] = '\0';
5686         }
5687     }
5688
5689   return (msg);
5690 }
5691
5692 static void
5693 print_offending_line ()
5694 {
5695   char *msg;
5696   int token_end;
5697
5698   msg = savestring (shell_input_line);
5699   token_end = strlen (msg);
5700   while (token_end && msg[token_end - 1] == '\n')
5701     msg[--token_end] = '\0';
5702
5703   parser_error (line_number, "`%s'", msg);
5704   free (msg);
5705 }
5706
5707 /* Report a syntax error with line numbers, etc.
5708    Call here for recoverable errors.  If you have a message to print,
5709    then place it in MESSAGE, otherwise pass NULL and this will figure
5710    out an appropriate message for you. */
5711 static void
5712 report_syntax_error (message)
5713      char *message;
5714 {
5715   char *msg, *p;
5716
5717   if (message)
5718     {
5719       parser_error (line_number, "%s", message);
5720       if (interactive && EOF_Reached)
5721         EOF_Reached = 0;
5722       last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
5723       return;
5724     }
5725
5726   /* If the line of input we're reading is not null, try to find the
5727      objectionable token.  First, try to figure out what token the
5728      parser's complaining about by looking at current_token. */
5729   if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
5730     {
5731       if (ansic_shouldquote (msg))
5732         {
5733           p = ansic_quote (msg, 0, NULL);
5734           free (msg);
5735           msg = p;
5736         }
5737       parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
5738       free (msg);
5739
5740       if (interactive == 0)
5741         print_offending_line ();
5742
5743       last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
5744       return;
5745     }
5746
5747   /* If looking at the current token doesn't prove fruitful, try to find the
5748      offending token by analyzing the text of the input line near the current
5749      input line index and report what we find. */
5750   if (shell_input_line && *shell_input_line)
5751     {
5752       msg = error_token_from_text ();
5753       if (msg)
5754         {
5755           parser_error (line_number, _("syntax error near `%s'"), msg);
5756           free (msg);
5757         }
5758
5759       /* If not interactive, print the line containing the error. */
5760       if (interactive == 0)
5761         print_offending_line ();
5762     }
5763   else
5764     {
5765       msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
5766       parser_error (line_number, "%s", msg);
5767       /* When the shell is interactive, this file uses EOF_Reached
5768          only for error reporting.  Other mechanisms are used to
5769          decide whether or not to exit. */
5770       if (interactive && EOF_Reached)
5771         EOF_Reached = 0;
5772     }
5773
5774   last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
5775 }
5776
5777 /* ??? Needed function. ??? We have to be able to discard the constructs
5778    created during parsing.  In the case of error, we want to return
5779    allocated objects to the memory pool.  In the case of no error, we want
5780    to throw away the information about where the allocated objects live.
5781    (dispose_command () will actually free the command.) */
5782 static void
5783 discard_parser_constructs (error_p)
5784      int error_p;
5785 {
5786 }
5787
5788 /************************************************
5789  *                                              *
5790  *              EOF HANDLING                    *
5791  *                                              *
5792  ************************************************/
5793
5794 /* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
5795
5796 /* A flag denoting whether or not ignoreeof is set. */
5797 int ignoreeof = 0;
5798
5799 /* The number of times that we have encountered an EOF character without
5800    another character intervening.  When this gets above the limit, the
5801    shell terminates. */
5802 int eof_encountered = 0;
5803
5804 /* The limit for eof_encountered. */
5805 int eof_encountered_limit = 10;
5806
5807 /* If we have EOF as the only input unit, this user wants to leave
5808    the shell.  If the shell is not interactive, then just leave.
5809    Otherwise, if ignoreeof is set, and we haven't done this the
5810    required number of times in a row, print a message. */
5811 static void
5812 handle_eof_input_unit ()
5813 {
5814   if (interactive)
5815     {
5816       /* shell.c may use this to decide whether or not to write out the
5817          history, among other things.  We use it only for error reporting
5818          in this file. */
5819       if (EOF_Reached)
5820         EOF_Reached = 0;
5821
5822       /* If the user wants to "ignore" eof, then let her do so, kind of. */
5823       if (ignoreeof)
5824         {
5825           if (eof_encountered < eof_encountered_limit)
5826             {
5827               fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
5828                        login_shell ? "logout" : "exit");
5829               eof_encountered++;
5830               /* Reset the parsing state. */
5831               last_read_token = current_token = '\n';
5832               /* Reset the prompt string to be $PS1. */
5833               prompt_string_pointer = (char **)NULL;
5834               prompt_again ();
5835               return;
5836             }
5837         }
5838
5839       /* In this case EOF should exit the shell.  Do it now. */
5840       reset_parser ();
5841       exit_builtin ((WORD_LIST *)NULL);
5842     }
5843   else
5844     {
5845       /* We don't write history files, etc., for non-interactive shells. */
5846       EOF_Reached = 1;
5847     }
5848 }
5849
5850 /************************************************
5851  *                                              *
5852  *      STRING PARSING FUNCTIONS                *
5853  *                                              *
5854  ************************************************/
5855
5856 /* It's very important that these two functions treat the characters
5857    between ( and ) identically. */
5858
5859 static WORD_LIST parse_string_error;
5860
5861 /* Take a string and run it through the shell parser, returning the
5862    resultant word list.  Used by compound array assignment. */
5863 WORD_LIST *
5864 parse_string_to_word_list (s, flags, whom)
5865      char *s;
5866      int flags;
5867      const char *whom;
5868 {
5869   WORD_LIST *wl;
5870   int tok, orig_current_token, orig_line_number, orig_input_terminator;
5871   int orig_line_count;
5872   int old_echo_input, old_expand_aliases;
5873 #if defined (HISTORY)
5874   int old_remember_on_history, old_history_expansion_inhibited;
5875 #endif
5876
5877 #if defined (HISTORY)
5878   old_remember_on_history = remember_on_history;
5879 #  if defined (BANG_HISTORY)
5880   old_history_expansion_inhibited = history_expansion_inhibited;
5881 #  endif
5882   bash_history_disable ();
5883 #endif
5884
5885   orig_line_number = line_number;
5886   orig_line_count = current_command_line_count;
5887   orig_input_terminator = shell_input_line_terminator;
5888   old_echo_input = echo_input_at_read;
5889   old_expand_aliases = expand_aliases;
5890
5891   push_stream (1);
5892   last_read_token = WORD;               /* WORD to allow reserved words here */
5893   current_command_line_count = 0;
5894   echo_input_at_read = expand_aliases = 0;
5895
5896   with_input_from_string (s, whom);
5897   wl = (WORD_LIST *)NULL;
5898
5899   if (flags & 1)
5900     parser_state |= PST_COMPASSIGN|PST_REPARSE;
5901
5902   while ((tok = read_token (READ)) != yacc_EOF)
5903     {
5904       if (tok == '\n' && *bash_input.location.string == '\0')
5905         break;
5906       if (tok == '\n')          /* Allow newlines in compound assignments */
5907         continue;
5908       if (tok != WORD && tok != ASSIGNMENT_WORD)
5909         {
5910           line_number = orig_line_number + line_number - 1;
5911           orig_current_token = current_token;
5912           current_token = tok;
5913           yyerror (NULL);       /* does the right thing */
5914           current_token = orig_current_token;
5915           if (wl)
5916             dispose_words (wl);
5917           wl = &parse_string_error;
5918           break;
5919         }
5920       wl = make_word_list (yylval.word, wl);
5921     }
5922   
5923   last_read_token = '\n';
5924   pop_stream ();
5925
5926 #if defined (HISTORY)
5927   remember_on_history = old_remember_on_history;
5928 #  if defined (BANG_HISTORY)
5929   history_expansion_inhibited = old_history_expansion_inhibited;
5930 #  endif /* BANG_HISTORY */
5931 #endif /* HISTORY */
5932
5933   echo_input_at_read = old_echo_input;
5934   expand_aliases = old_expand_aliases;
5935
5936   current_command_line_count = orig_line_count;
5937   shell_input_line_terminator = orig_input_terminator;
5938
5939   if (flags & 1)
5940     parser_state &= ~(PST_COMPASSIGN|PST_REPARSE);
5941
5942   if (wl == &parse_string_error)
5943     {
5944       last_command_exit_value = EXECUTION_FAILURE;
5945       if (interactive_shell == 0 && posixly_correct)
5946         jump_to_top_level (FORCE_EOF);
5947       else
5948         jump_to_top_level (DISCARD);
5949     }
5950
5951   return (REVERSE_LIST (wl, WORD_LIST *));
5952 }
5953
5954 static char *
5955 parse_compound_assignment (retlenp)
5956      int *retlenp;
5957 {
5958   WORD_LIST *wl, *rl;
5959   int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
5960   char *saved_token, *ret;
5961
5962   saved_token = token;
5963   orig_token_size = token_buffer_size;
5964   orig_line_number = line_number;
5965   orig_last_token = last_read_token;
5966
5967   last_read_token = WORD;       /* WORD to allow reserved words here */
5968
5969   token = (char *)NULL;
5970   token_buffer_size = 0;
5971
5972   assignok = parser_state&PST_ASSIGNOK;         /* XXX */
5973
5974   wl = (WORD_LIST *)NULL;       /* ( */
5975   parser_state |= PST_COMPASSIGN;
5976
5977   while ((tok = read_token (READ)) != ')')
5978     {
5979       if (tok == '\n')                  /* Allow newlines in compound assignments */
5980         {
5981           if (SHOULD_PROMPT ())
5982             prompt_again ();
5983           continue;
5984         }
5985       if (tok != WORD && tok != ASSIGNMENT_WORD)
5986         {
5987           current_token = tok;  /* for error reporting */
5988           if (tok == yacc_EOF)  /* ( */
5989             parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
5990           else
5991             yyerror(NULL);      /* does the right thing */
5992           if (wl)
5993             dispose_words (wl);
5994           wl = &parse_string_error;
5995           break;
5996         }
5997       wl = make_word_list (yylval.word, wl);
5998     }
5999
6000   FREE (token);
6001   token = saved_token;
6002   token_buffer_size = orig_token_size;
6003
6004   parser_state &= ~PST_COMPASSIGN;
6005
6006   if (wl == &parse_string_error)
6007     {
6008       last_command_exit_value = EXECUTION_FAILURE;
6009       last_read_token = '\n';   /* XXX */
6010       if (interactive_shell == 0 && posixly_correct)
6011         jump_to_top_level (FORCE_EOF);
6012       else
6013         jump_to_top_level (DISCARD);
6014     }
6015
6016   last_read_token = orig_last_token;            /* XXX - was WORD? */
6017
6018   if (wl)
6019     {
6020       rl = REVERSE_LIST (wl, WORD_LIST *);
6021       ret = string_list (rl);
6022       dispose_words (rl);
6023     }
6024   else
6025     ret = (char *)NULL;
6026
6027   if (retlenp)
6028     *retlenp = (ret && *ret) ? strlen (ret) : 0;
6029
6030   if (assignok)
6031     parser_state |= PST_ASSIGNOK;
6032
6033   return ret;
6034 }
6035
6036 /************************************************
6037  *                                              *
6038  *   SAVING AND RESTORING PARTIAL PARSE STATE   *
6039  *                                              *
6040  ************************************************/
6041
6042 sh_parser_state_t *
6043 save_parser_state (ps)
6044      sh_parser_state_t *ps;
6045 {
6046   if (ps == 0)
6047     ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
6048   if (ps == 0)
6049     return ((sh_parser_state_t *)NULL);
6050
6051   ps->parser_state = parser_state;
6052   ps->token_state = save_token_state ();
6053
6054   ps->input_line_terminator = shell_input_line_terminator;
6055   ps->eof_encountered = eof_encountered;
6056
6057   ps->prompt_string_pointer = prompt_string_pointer;
6058
6059   ps->current_command_line_count = current_command_line_count;
6060
6061 #if defined (HISTORY)
6062   ps->remember_on_history = remember_on_history;
6063 #  if defined (BANG_HISTORY)
6064   ps->history_expansion_inhibited = history_expansion_inhibited;
6065 #  endif
6066 #endif
6067
6068   ps->last_command_exit_value = last_command_exit_value;
6069 #if defined (ARRAY_VARS)
6070   ps->pipestatus = save_pipestatus_array ();
6071 #endif
6072     
6073   ps->last_shell_builtin = last_shell_builtin;
6074   ps->this_shell_builtin = this_shell_builtin;
6075
6076   ps->expand_aliases = expand_aliases;
6077   ps->echo_input_at_read = echo_input_at_read;
6078
6079   ps->token = token;
6080   ps->token_buffer_size = token_buffer_size;
6081   /* Force reallocation on next call to read_token_word */
6082   token = 0;
6083   token_buffer_size = 0;
6084
6085   return (ps);
6086 }
6087
6088 void
6089 restore_parser_state (ps)
6090      sh_parser_state_t *ps;
6091 {
6092   if (ps == 0)
6093     return;
6094
6095   parser_state = ps->parser_state;
6096   if (ps->token_state)
6097     {
6098       restore_token_state (ps->token_state);
6099       free (ps->token_state);
6100     }
6101
6102   shell_input_line_terminator = ps->input_line_terminator;
6103   eof_encountered = ps->eof_encountered;
6104
6105   prompt_string_pointer = ps->prompt_string_pointer;
6106
6107   current_command_line_count = ps->current_command_line_count;
6108
6109 #if defined (HISTORY)
6110   remember_on_history = ps->remember_on_history;
6111 #  if defined (BANG_HISTORY)
6112   history_expansion_inhibited = ps->history_expansion_inhibited;
6113 #  endif
6114 #endif
6115
6116   last_command_exit_value = ps->last_command_exit_value;
6117 #if defined (ARRAY_VARS)
6118   restore_pipestatus_array (ps->pipestatus);
6119 #endif
6120
6121   last_shell_builtin = ps->last_shell_builtin;
6122   this_shell_builtin = ps->this_shell_builtin;
6123
6124   expand_aliases = ps->expand_aliases;
6125   echo_input_at_read = ps->echo_input_at_read;
6126
6127   FREE (token);
6128   token = ps->token;
6129   token_buffer_size = ps->token_buffer_size;
6130 }
6131
6132 sh_input_line_state_t *
6133 save_input_line_state (ls)
6134      sh_input_line_state_t *ls;
6135 {
6136   if (ls == 0)
6137     ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
6138   if (ls == 0)
6139     return ((sh_input_line_state_t *)NULL);
6140
6141   ls->input_line = shell_input_line;
6142   ls->input_line_size = shell_input_line_size;
6143   ls->input_line_len = shell_input_line_len;
6144   ls->input_line_index = shell_input_line_index;
6145
6146   /* force reallocation */
6147   shell_input_line = 0;
6148   shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
6149
6150   return ls;
6151 }
6152
6153 void
6154 restore_input_line_state (ls)
6155      sh_input_line_state_t *ls;
6156 {
6157   FREE (shell_input_line);
6158   shell_input_line = ls->input_line;
6159   shell_input_line_size = ls->input_line_size;
6160   shell_input_line_len = ls->input_line_len;
6161   shell_input_line_index = ls->input_line_index;
6162
6163   set_line_mbstate ();
6164 }
6165
6166 /************************************************
6167  *                                              *
6168  *      MULTIBYTE CHARACTER HANDLING            *
6169  *                                              *
6170  ************************************************/
6171
6172 #if defined (HANDLE_MULTIBYTE)
6173 static void
6174 set_line_mbstate ()
6175 {
6176   int c;
6177   size_t i, previ, len;
6178   mbstate_t mbs, prevs;
6179   size_t mbclen;
6180
6181   if (shell_input_line == NULL)
6182     return;
6183   len = strlen (shell_input_line);      /* XXX - shell_input_line_len ? */
6184   FREE (shell_input_line_property);
6185   shell_input_line_property = (char *)xmalloc (len + 1);
6186
6187   memset (&prevs, '\0', sizeof (mbstate_t));
6188   for (i = previ = 0; i < len; i++)
6189     {
6190       mbs = prevs;
6191
6192       c = shell_input_line[i];
6193       if (c == EOF)
6194         {
6195           size_t j;
6196           for (j = i; j < len; j++)
6197             shell_input_line_property[j] = 1;
6198           break;
6199         }
6200
6201       mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
6202       if (mbclen == 1 || mbclen == (size_t)-1)
6203         {
6204           mbclen = 1;
6205           previ = i + 1;
6206         }
6207       else if (mbclen == (size_t)-2)
6208         mbclen = 0;
6209       else if (mbclen > 1)
6210         {
6211           mbclen = 0;
6212           previ = i + 1;
6213           prevs = mbs;
6214         }
6215       else
6216         {
6217           /* XXX - what to do if mbrlen returns 0? (null wide character) */
6218           size_t j;
6219           for (j = i; j < len; j++)
6220             shell_input_line_property[j] = 1;
6221           break;
6222         }
6223
6224       shell_input_line_property[i] = mbclen;
6225     }
6226 }
6227 #endif /* HANDLE_MULTIBYTE */