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