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