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