]> git.ipfire.org Git - thirdparty/bash.git/blob - y.tab.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/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 }