2 /* A Bison parser, made from /usr/homes/chet/src/bash/src/parse.y
3 by GNU Bison version 1.25
6 #define YYBISON 1 /* Identify Bison output. */
22 #define COND_START 272
24 #define COND_ERROR 274
30 #define ASSIGNMENT_WORD 280
36 #define GREATER_GREATER 286
39 #define GREATER_AND 289
41 #define LESS_LESS_MINUS 291
42 #define AND_GREATER 292
43 #define LESS_GREATER 293
44 #define GREATER_BAR 294
47 #line 21 "/usr/homes/chet/src/bash/src/parse.y"
51 #include "bashtypes.h"
54 #if defined (HAVE_UNISTD_H)
58 #if defined (HAVE_LOCALE_H)
71 #include "mailcheck.h"
72 #include "builtins/common.h"
73 #include "builtins/builtext.h"
75 #if defined (READLINE)
76 # include "bashline.h"
77 # include <readline/readline.h>
81 # include "bashhist.h"
82 # include <readline/history.h>
85 #if defined (JOB_CONTROL)
87 #endif /* JOB_CONTROL */
93 #if defined (PROMPT_STRING_DECODE)
95 # include <sys/param.h>
99 #endif /* PROMPT_STRING_DECODE */
101 #define RE_READ_TOKEN -99
102 #define NO_EXPANSION -100
106 #if defined (EXTENDED_GLOB)
107 #define PATTERN_CHAR(c) \
108 ((c) == '@' || (c) == '*' || (c) == '+' || (c) == '?' || (c) == '!')
110 extern int extended_glob
;
113 extern int eof_encountered
;
114 extern int no_line_editing
, running_under_emacs
;
115 extern int current_command_number
;
116 extern int interactive
, interactive_shell
, login_shell
;
117 extern int sourcelevel
;
118 extern int posixly_correct
;
119 extern int last_command_exit_value
;
120 extern int interrupt_immediately
;
121 extern char *shell_name
, *current_host_name
;
122 extern char *dist_version
;
123 extern int patch_level
;
124 extern int dump_translatable_strings
, dump_po_strings
;
125 extern Function
*last_shell_builtin
, *this_shell_builtin
;
126 #if defined (BUFFERED_INPUT)
127 extern int bash_input_fd_changed
;
130 /* **************************************************************** */
132 /* "Forward" declarations */
134 /* **************************************************************** */
136 static char *ansiexpand ();
137 static char *localeexpand ();
138 static int reserved_word_acceptable ();
139 static int read_token ();
141 static int parse_arith_cmd ();
142 #if defined (COND_COMMAND)
143 static COMMAND
*parse_cond_command ();
145 static int read_token_word ();
146 static void discard_parser_constructs ();
148 static void report_syntax_error ();
149 static void handle_eof_input_unit ();
150 static void prompt_again ();
152 static void reset_readline_prompt ();
154 static void print_prompt ();
156 extern int yyerror ();
158 /* Default prompt strings */
159 char *primary_prompt
= PPROMPT
;
160 char *secondary_prompt
= SPROMPT
;
162 /* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
163 char *ps1_prompt
, *ps2_prompt
;
165 /* Handle on the current prompt string. Indirectly points through
166 ps1_ or ps2_prompt. */
167 char **prompt_string_pointer
= (char **)NULL
;
168 char *current_prompt_string
;
170 /* Non-zero means we expand aliases in commands. */
171 int expand_aliases
= 0;
173 /* If non-zero, the decoded prompt string undergoes parameter and
174 variable substitution, command substitution, arithmetic substitution,
175 string expansion, process substitution, and quote removal in
176 decode_prompt_string. */
179 /* The decoded prompt string. Used if READLINE is not defined or if
180 editing is turned off. Analogous to current_readline_prompt. */
181 static char *current_decoded_prompt
;
183 /* The number of lines read from input while creating the current command. */
184 int current_command_line_count
;
186 /* Variables to manage the task of reading here documents, because we need to
187 defer the reading until after a complete command has been collected. */
188 static REDIRECT
*redir_stack
[10];
191 /* Where shell input comes from. History expansion is performed on each
192 line when the shell is interactive. */
193 static char *shell_input_line
= (char *)NULL
;
194 static int shell_input_line_index
;
195 static int shell_input_line_size
; /* Amount allocated for shell_input_line. */
196 static int shell_input_line_len
; /* strlen (shell_input_line) */
198 /* Either zero or EOF. */
199 static int shell_input_line_terminator
;
201 /* The line number in a script on which a function definition starts. */
202 static int function_dstart
;
204 /* The line number in a script on which a function body starts. */
205 static int function_bstart
;
207 static REDIRECTEE redir
;
209 #line 183 "/usr/homes/chet/src/bash/src/parse.y"
211 WORD_DESC
*word
; /* the word that we read. */
212 int number
; /* the number that we read. */
213 WORD_LIST
*word_list
;
217 PATTERN_LIST
*pattern
;
230 #define YYFLAG -32768
233 #define YYTRANSLATE(x) ((unsigned)(x) <= 295 ? yytranslate[x] : 85)
235 static const char yytranslate
[] = { 0,
236 2, 2, 2, 2, 2, 2, 2, 2, 2, 42,
237 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
238 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
239 2, 2, 2, 2, 2, 2, 2, 40, 2, 50,
240 51, 2, 2, 2, 47, 2, 2, 2, 2, 2,
241 2, 2, 2, 2, 2, 2, 2, 2, 41, 46,
242 2, 45, 2, 2, 2, 2, 2, 2, 2, 2,
243 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
244 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
245 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
246 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
247 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
248 2, 2, 48, 44, 49, 2, 2, 2, 2, 2,
249 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
250 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
251 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
252 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
253 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
254 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
255 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
256 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
257 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
258 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
259 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
260 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
261 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
262 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
263 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
264 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
269 static const short yyprhs
[] = { 0,
270 0, 3, 5, 8, 10, 12, 15, 18, 21, 25,
271 29, 32, 36, 39, 43, 46, 50, 53, 57, 60,
272 64, 67, 71, 74, 78, 81, 85, 88, 92, 95,
273 99, 102, 105, 109, 111, 113, 115, 117, 120, 122,
274 125, 127, 129, 132, 134, 136, 142, 148, 150, 152,
275 154, 156, 158, 160, 162, 169, 176, 184, 192, 203,
276 214, 221, 228, 236, 244, 255, 266, 273, 281, 288,
277 294, 301, 306, 310, 316, 324, 331, 335, 337, 341,
278 346, 353, 359, 361, 364, 369, 374, 380, 386, 389,
279 393, 395, 399, 402, 404, 407, 411, 415, 419, 424,
280 429, 434, 439, 444, 446, 448, 450, 452, 453, 456,
281 458, 461, 464, 469, 474, 478, 482, 484, 486, 489,
282 492, 496, 500, 505, 507, 509
285 static const short yyrhs
[] = { 80,
286 42, 0, 42, 0, 1, 42, 0, 43, 0, 24,
287 0, 53, 24, 0, 45, 24, 0, 46, 24, 0,
288 26, 45, 24, 0, 26, 46, 24, 0, 31, 24,
289 0, 26, 31, 24, 0, 32, 24, 0, 26, 32,
290 24, 0, 33, 26, 0, 26, 33, 26, 0, 34,
291 26, 0, 26, 34, 26, 0, 33, 24, 0, 26,
292 33, 24, 0, 34, 24, 0, 26, 34, 24, 0,
293 36, 24, 0, 26, 36, 24, 0, 34, 47, 0,
294 26, 34, 47, 0, 33, 47, 0, 26, 33, 47,
295 0, 37, 24, 0, 26, 38, 24, 0, 38, 24,
296 0, 39, 24, 0, 26, 39, 24, 0, 24, 0,
297 25, 0, 54, 0, 54, 0, 56, 54, 0, 55,
298 0, 57, 55, 0, 57, 0, 59, 0, 59, 56,
299 0, 60, 0, 62, 0, 12, 75, 14, 75, 15,
300 0, 13, 75, 14, 75, 15, 0, 61, 0, 65,
301 0, 64, 0, 66, 0, 67, 0, 68, 0, 63,
302 0, 10, 24, 79, 14, 75, 15, 0, 10, 24,
303 79, 48, 75, 49, 0, 10, 24, 41, 79, 14,
304 75, 15, 0, 10, 24, 41, 79, 48, 75, 49,
305 0, 10, 24, 79, 20, 53, 78, 79, 14, 75,
306 15, 0, 10, 24, 79, 20, 53, 78, 79, 48,
307 75, 49, 0, 11, 24, 79, 14, 74, 15, 0,
308 11, 24, 79, 48, 74, 49, 0, 11, 24, 41,
309 79, 14, 74, 15, 0, 11, 24, 41, 79, 48,
310 74, 49, 0, 11, 24, 79, 20, 53, 78, 79,
311 14, 74, 15, 0, 11, 24, 79, 20, 53, 78,
312 79, 48, 74, 49, 0, 8, 24, 79, 20, 79,
313 9, 0, 8, 24, 79, 20, 72, 79, 9, 0,
314 8, 24, 79, 20, 70, 9, 0, 24, 50, 51,
315 79, 66, 0, 16, 24, 50, 51, 79, 66, 0,
316 16, 24, 79, 66, 0, 50, 75, 51, 0, 3,
317 75, 4, 75, 7, 0, 3, 75, 4, 75, 5,
318 75, 7, 0, 3, 75, 4, 75, 69, 7, 0,
319 48, 74, 49, 0, 27, 0, 17, 28, 18, 0,
320 6, 75, 4, 75, 0, 6, 75, 4, 75, 5,
321 75, 0, 6, 75, 4, 75, 69, 0, 71, 0,
322 72, 71, 0, 79, 73, 51, 75, 0, 79, 73,
323 51, 79, 0, 79, 50, 73, 51, 75, 0, 79,
324 50, 73, 51, 79, 0, 71, 35, 0, 72, 71,
325 35, 0, 24, 0, 73, 44, 24, 0, 79, 76,
326 0, 74, 0, 79, 77, 0, 77, 42, 79, 0,
327 77, 40, 79, 0, 77, 41, 79, 0, 77, 29,
328 79, 77, 0, 77, 30, 79, 77, 0, 77, 40,
329 79, 77, 0, 77, 41, 79, 77, 0, 77, 42,
330 79, 77, 0, 82, 0, 42, 0, 41, 0, 43,
331 0, 0, 79, 42, 0, 81, 0, 81, 40, 0,
332 81, 41, 0, 81, 29, 79, 81, 0, 81, 30,
333 79, 81, 0, 81, 40, 81, 0, 81, 41, 81,
334 0, 82, 0, 83, 0, 21, 83, 0, 84, 83,
335 0, 84, 21, 83, 0, 21, 84, 83, 0, 83,
336 44, 79, 83, 0, 58, 0, 22, 0, 22, 23,
343 static const short yyrline
[] = { 0,
344 232, 241, 248, 263, 273, 275, 279, 284, 289, 294,
345 299, 304, 309, 315, 321, 326, 331, 336, 341, 346,
346 351, 356, 361, 368, 375, 380, 385, 390, 395, 400,
347 405, 410, 415, 422, 424, 426, 430, 434, 445, 447,
348 451, 453, 455, 484, 486, 488, 490, 492, 494, 496,
349 498, 500, 502, 504, 508, 510, 512, 514, 516, 518,
350 522, 526, 530, 534, 538, 542, 548, 550, 552, 556,
351 560, 563, 567, 571, 573, 575, 580, 584, 588, 592,
352 594, 596, 600, 601, 605, 607, 609, 611, 615, 616,
353 620, 622, 631, 639, 640, 646, 647, 654, 658, 660,
354 662, 669, 671, 673, 677, 678, 679, 682, 683, 692,
355 698, 707, 715, 717, 719, 726, 729, 733, 735, 740,
356 745, 750, 757, 760, 764, 766
361 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
363 static const char * const yytname
[] = { "$","error","$undefined.","IF","THEN",
364 "ELSE","ELIF","FI","CASE","ESAC","FOR","SELECT","WHILE","UNTIL","DO","DONE",
365 "FUNCTION","COND_START","COND_END","COND_ERROR","IN","BANG","TIME","TIMEOPT",
366 "WORD","ASSIGNMENT_WORD","NUMBER","ARITH_CMD","COND_CMD","AND_AND","OR_OR","GREATER_GREATER",
367 "LESS_LESS","LESS_AND","GREATER_AND","SEMI_SEMI","LESS_LESS_MINUS","AND_GREATER",
368 "LESS_GREATER","GREATER_BAR","'&'","';'","'\\n'","yacc_EOF","'|'","'>'","'<'",
369 "'-'","'{'","'}'","'('","')'","inputunit","word_list","redirection","simple_command_element",
370 "redirection_list","simple_command","command","shell_command","for_command",
371 "select_command","case_command","function_def","subshell","if_command","group_command",
372 "arith_command","cond_command","elif_clause","case_clause","pattern_list","case_clause_sequence",
373 "pattern","list","compound_list","list0","list1","list_terminator","newline_list",
374 "simple_list","simple_list1","pipeline_command","pipeline","timespec", NULL
378 static const short yyr1
[] = { 0,
379 52, 52, 52, 52, 53, 53, 54, 54, 54, 54,
380 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
381 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
382 54, 54, 54, 55, 55, 55, 56, 56, 57, 57,
383 58, 58, 58, 59, 59, 59, 59, 59, 59, 59,
384 59, 59, 59, 59, 60, 60, 60, 60, 60, 60,
385 61, 61, 61, 61, 61, 61, 62, 62, 62, 63,
386 63, 63, 64, 65, 65, 65, 66, 67, 68, 69,
387 69, 69, 70, 70, 71, 71, 71, 71, 72, 72,
388 73, 73, 74, 75, 75, 76, 76, 76, 77, 77,
389 77, 77, 77, 77, 78, 78, 78, 79, 79, 80,
390 80, 80, 81, 81, 81, 81, 81, 82, 82, 82,
391 82, 82, 83, 83, 84, 84
394 static const short yyr2
[] = { 0,
395 2, 1, 2, 1, 1, 2, 2, 2, 3, 3,
396 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
397 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
398 2, 2, 3, 1, 1, 1, 1, 2, 1, 2,
399 1, 1, 2, 1, 1, 5, 5, 1, 1, 1,
400 1, 1, 1, 1, 6, 6, 7, 7, 10, 10,
401 6, 6, 7, 7, 10, 10, 6, 7, 6, 5,
402 6, 4, 3, 5, 7, 6, 3, 1, 3, 4,
403 6, 5, 1, 2, 4, 4, 5, 5, 2, 3,
404 1, 3, 2, 1, 2, 3, 3, 3, 4, 4,
405 4, 4, 4, 1, 1, 1, 1, 0, 2, 1,
406 2, 2, 4, 4, 3, 3, 1, 1, 2, 2,
410 static const short yydefact
[] = { 0,
411 0, 108, 0, 0, 0, 108, 108, 0, 0, 0,
412 125, 34, 35, 0, 78, 0, 0, 0, 0, 0,
413 0, 0, 0, 2, 4, 0, 0, 108, 108, 36,
414 39, 41, 124, 42, 44, 48, 45, 54, 50, 49,
415 51, 52, 53, 0, 110, 117, 118, 0, 3, 94,
416 0, 0, 108, 108, 108, 0, 0, 108, 0, 119,
417 0, 126, 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 11, 13, 19, 15, 27, 21, 17, 25,
419 23, 29, 31, 32, 7, 8, 0, 0, 0, 34,
420 40, 37, 43, 1, 108, 108, 111, 112, 108, 0,
421 120, 108, 109, 93, 95, 104, 0, 108, 0, 108,
422 0, 108, 108, 0, 0, 79, 122, 108, 12, 14,
423 20, 16, 28, 22, 18, 26, 24, 30, 33, 9,
424 10, 77, 0, 73, 38, 0, 0, 115, 116, 0,
425 121, 0, 108, 108, 108, 108, 108, 108, 0, 108,
426 0, 108, 0, 108, 0, 108, 0, 0, 108, 72,
427 0, 113, 114, 0, 0, 123, 108, 108, 74, 0,
428 0, 0, 97, 98, 96, 0, 83, 108, 0, 108,
429 108, 0, 5, 0, 0, 108, 108, 0, 0, 0,
430 46, 47, 0, 70, 0, 0, 76, 99, 100, 101,
431 102, 103, 69, 89, 84, 0, 67, 91, 0, 0,
432 0, 0, 55, 6, 106, 105, 107, 108, 56, 0,
433 0, 61, 108, 62, 71, 75, 108, 108, 108, 108,
434 90, 68, 0, 0, 108, 57, 58, 0, 63, 64,
435 0, 80, 0, 0, 0, 108, 92, 85, 86, 108,
436 108, 108, 108, 108, 82, 87, 88, 0, 0, 0,
437 0, 81, 59, 60, 65, 66, 0, 0, 0
440 static const short yydefgoto
[] = { 267,
441 184, 30, 31, 93, 32, 33, 34, 35, 36, 37,
442 38, 39, 40, 41, 42, 43, 170, 176, 177, 178,
443 210, 50, 51, 104, 105, 218, 52, 44, 138, 106,
447 static const short yypact
[] = { 246,
448 -34,-32768, 11, 20, 24,-32768,-32768, 33, -10, 369,
449 29, 19,-32768, 529,-32768, 42, 47, 30, 36, 64,
450 66, 78, 81,-32768,-32768, 84, 92,-32768,-32768,-32768,
451 -32768, 155,-32768, 513,-32768,-32768,-32768,-32768,-32768,-32768,
452 -32768,-32768,-32768, 89, -15,-32768, 77, 410,-32768,-32768,
453 130, 287,-32768, 95, 99, 127, 131, 97, 132, 77,
454 492,-32768, 100, 128, 129, 44, 56, 134, 135, 136,
455 139, 140,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
456 -32768,-32768,-32768,-32768,-32768,-32768, 105, 287, 104,-32768,
457 -32768,-32768, 513,-32768,-32768,-32768, 328, 328,-32768, 492,
458 77,-32768,-32768,-32768, 88,-32768, 1,-32768, -1,-32768,
459 16,-32768,-32768, 116, -32,-32768, 77,-32768,-32768,-32768,
460 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
461 -32768,-32768, 88,-32768,-32768, 287, 287, 69, 69, 451,
462 77, 79,-32768,-32768,-32768,-32768,-32768,-32768, 3,-32768,
463 144,-32768, 13,-32768, 144,-32768, 141, 157,-32768,-32768,
464 -32,-32768,-32768, 328, 328, 77,-32768,-32768,-32768, 166,
465 287, 287, 287, 287, 287, 169, 147,-32768, -4,-32768,
466 -32768, 175,-32768, 52, 146,-32768,-32768, 181, 52, 149,
467 -32768,-32768, -32,-32768, 192, 199,-32768,-32768,-32768, 71,
468 71, 71,-32768,-32768, 170, 0,-32768,-32768, 180, -22,
469 191, 161,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 196,
470 163,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
471 -32768,-32768, 28, 189,-32768,-32768,-32768, 17,-32768,-32768,
472 25, 114, 287, 287, 287,-32768,-32768,-32768, 287,-32768,
473 -32768,-32768,-32768,-32768,-32768,-32768, 287, 200, 167, 202,
474 171,-32768,-32768,-32768,-32768,-32768, 218, 219,-32768
477 static const short yypgoto
[] = {-32768,
478 67, -30, 194,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
479 -32768,-32768,-32768, -112,-32768,-32768, -19,-32768, 46,-32768,
480 18, -17, -6,-32768, -60, 39, -21,-32768, 6, 12,
488 static const short yytable
[] = { 56,
489 57, 60, 160, 92, 207, 45, 88, 49, 232, 103,
490 87, 46, 150, 95, 96, 28, 180, 59, 151, 208,
491 148, 234, 89, 208, 97, 98, 186, 133, 235, 154,
492 250, 107, 109, 111, 53, 155, 115, 103, 252, 101,
493 103, 103, 103, 54, 103, 209, 152, 55, 194, 209,
494 181, 62, 117, 75, 103, 76, 58, 103, 103, 78,
495 187, 79, 135, 156, 251, 73, 103, 121, 63, 122,
496 74, 234, 253, 136, 137, 214, 77, 140, 246, 124,
497 225, 125, 80, 167, 168, 169, 149, 81, 153, 82,
498 123, 141, 215, 216, 217, 142, 161, 95, 96, 143,
499 144, 83, 126, 139, 84, 157, 158, 85, 46, 46,
500 198, 199, 200, 201, 202, 86, 143, 144, 254, 168,
501 99, 171, 172, 173, 174, 175, 179, 145, 146, 147,
502 94, 166, 88, 102, 88, 108, 188, 193, 190, 110,
503 112, 162, 163, 182, 113, 185, 114, 46, 46, 116,
504 118, 119, 120, 132, 134, 191, 206, 127, 128, 129,
505 195, 196, 130, 131, 88, 88, 159, 183, 220, 221,
506 139, 192, 197, 211, 212, 46, 46, 203, 90, 13,
507 14, 204, 200, 201, 202, 16, 17, 18, 19, 213,
508 20, 21, 22, 23, 219, 222, 238, 224, 226, 26,
509 27, 241, 227, 208, 231, 236, 243, 244, 245, 237,
510 239, 240, 247, 249, 263, 264, 265, 268, 269, 266,
511 242, 189, 255, 205, 257, 91, 233, 223, 248, 61,
512 88, 88, 0, 0, 260, 261, 0, 0, 0, 256,
513 0, 0, 0, 258, 259, 0, 1, 262, 2, 0,
514 0, 0, 0, 3, 0, 4, 5, 6, 7, 0,
515 0, 8, 9, 0, 0, 0, 10, 11, 0, 12,
516 13, 14, 15, 0, 0, 0, 16, 17, 18, 19,
517 0, 20, 21, 22, 23, 0, 0, 24, 25, 2,
518 26, 27, 0, 28, 3, 29, 4, 5, 6, 7,
519 0, 0, 8, 9, 0, 0, 0, 10, 11, 0,
520 12, 13, 14, 15, 0, 0, 0, 16, 17, 18,
521 19, 0, 20, 21, 22, 23, 0, 0, 103, 0,
522 2, 26, 27, 0, 28, 3, 29, 4, 5, 6,
523 7, 0, 0, 8, 9, 0, 0, 0, 10, 11,
524 0, 12, 13, 14, 15, 0, 0, 0, 16, 17,
525 18, 19, 0, 20, 21, 22, 23, 0, 0, 0,
526 0, 2, 26, 27, 0, 28, 3, 29, 4, 5,
527 6, 7, 0, 0, 8, 9, 0, 0, 0, 0,
528 11, 0, 12, 13, 14, 15, 0, 0, 0, 16,
529 17, 18, 19, 0, 20, 21, 22, 23, 0, 0,
530 0, 0, 2, 26, 27, 0, 28, 3, 29, 4,
531 5, 6, 7, 0, 0, 8, 9, 0, 0, 0,
532 100, 0, 0, 12, 13, 14, 15, 0, 0, 0,
533 16, 17, 18, 19, 0, 20, 21, 22, 23, 0,
534 0, 0, 0, 2, 26, 27, 0, 28, 3, 29,
535 4, 5, 6, 7, 0, 0, 8, 9, 0, 0,
536 0, 0, 0, 0, 12, 13, 14, 15, 0, 0,
537 0, 16, 17, 18, 19, 0, 20, 21, 22, 23,
538 0, 0, 103, 0, 2, 26, 27, 0, 28, 3,
539 29, 4, 5, 6, 7, 0, 0, 8, 9, 0,
540 0, 0, 0, 0, 0, 12, 13, 14, 15, 0,
541 0, 0, 16, 17, 18, 19, 0, 20, 21, 22,
542 23, 0, 0, 0, 0, 0, 26, 27, 14, 28,
543 0, 29, 0, 16, 17, 18, 19, 0, 20, 21,
544 22, 23, 0, 0, 0, 0, 0, 26, 27, 64,
545 65, 66, 67, 0, 68, 0, 69, 70, 0, 0,
549 static const short yycheck
[] = { 6,
550 7, 10, 115, 34, 9, 0, 28, 42, 9, 42,
551 28, 0, 14, 29, 30, 48, 14, 28, 20, 24,
552 20, 44, 29, 24, 40, 41, 14, 88, 51, 14,
553 14, 53, 54, 55, 24, 20, 58, 42, 14, 48,
554 42, 42, 42, 24, 42, 50, 48, 24, 161, 50,
555 48, 23, 61, 24, 42, 26, 24, 42, 42, 24,
556 48, 26, 93, 48, 48, 24, 42, 24, 50, 26,
557 24, 44, 48, 95, 96, 24, 47, 99, 51, 24,
558 193, 26, 47, 5, 6, 7, 108, 24, 110, 24,
559 47, 100, 41, 42, 43, 102, 118, 29, 30, 29,
560 30, 24, 47, 98, 24, 112, 113, 24, 97, 98,
561 171, 172, 173, 174, 175, 24, 29, 30, 5, 6,
562 44, 143, 144, 145, 146, 147, 148, 40, 41, 42,
563 42, 140, 154, 4, 156, 41, 154, 159, 156, 41,
564 14, 136, 137, 150, 14, 152, 50, 136, 137, 18,
565 51, 24, 24, 49, 51, 15, 178, 24, 24, 24,
566 167, 168, 24, 24, 186, 187, 51, 24, 186, 187,
567 165, 15, 7, 180, 181, 164, 165, 9, 24, 25,
568 26, 35, 243, 244, 245, 31, 32, 33, 34, 15,
569 36, 37, 38, 39, 49, 15, 218, 49, 7, 45,
570 46, 223, 4, 24, 35, 15, 228, 229, 230, 49,
571 15, 49, 24, 235, 15, 49, 15, 0, 0, 49,
572 227, 155, 242, 178, 246, 32, 209, 189, 235, 10,
573 252, 253, -1, -1, 252, 253, -1, -1, -1, 246,
574 -1, -1, -1, 250, 251, -1, 1, 254, 3, -1,
575 -1, -1, -1, 8, -1, 10, 11, 12, 13, -1,
576 -1, 16, 17, -1, -1, -1, 21, 22, -1, 24,
577 25, 26, 27, -1, -1, -1, 31, 32, 33, 34,
578 -1, 36, 37, 38, 39, -1, -1, 42, 43, 3,
579 45, 46, -1, 48, 8, 50, 10, 11, 12, 13,
580 -1, -1, 16, 17, -1, -1, -1, 21, 22, -1,
581 24, 25, 26, 27, -1, -1, -1, 31, 32, 33,
582 34, -1, 36, 37, 38, 39, -1, -1, 42, -1,
583 3, 45, 46, -1, 48, 8, 50, 10, 11, 12,
584 13, -1, -1, 16, 17, -1, -1, -1, 21, 22,
585 -1, 24, 25, 26, 27, -1, -1, -1, 31, 32,
586 33, 34, -1, 36, 37, 38, 39, -1, -1, -1,
587 -1, 3, 45, 46, -1, 48, 8, 50, 10, 11,
588 12, 13, -1, -1, 16, 17, -1, -1, -1, -1,
589 22, -1, 24, 25, 26, 27, -1, -1, -1, 31,
590 32, 33, 34, -1, 36, 37, 38, 39, -1, -1,
591 -1, -1, 3, 45, 46, -1, 48, 8, 50, 10,
592 11, 12, 13, -1, -1, 16, 17, -1, -1, -1,
593 21, -1, -1, 24, 25, 26, 27, -1, -1, -1,
594 31, 32, 33, 34, -1, 36, 37, 38, 39, -1,
595 -1, -1, -1, 3, 45, 46, -1, 48, 8, 50,
596 10, 11, 12, 13, -1, -1, 16, 17, -1, -1,
597 -1, -1, -1, -1, 24, 25, 26, 27, -1, -1,
598 -1, 31, 32, 33, 34, -1, 36, 37, 38, 39,
599 -1, -1, 42, -1, 3, 45, 46, -1, 48, 8,
600 50, 10, 11, 12, 13, -1, -1, 16, 17, -1,
601 -1, -1, -1, -1, -1, 24, 25, 26, 27, -1,
602 -1, -1, 31, 32, 33, 34, -1, 36, 37, 38,
603 39, -1, -1, -1, -1, -1, 45, 46, 26, 48,
604 -1, 50, -1, 31, 32, 33, 34, -1, 36, 37,
605 38, 39, -1, -1, -1, -1, -1, 45, 46, 31,
606 32, 33, 34, -1, 36, -1, 38, 39, -1, -1,
609 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
610 #line 3 "/usr/share/misc/bison.simple"
612 /* Skeleton output parser for bison,
613 Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
615 This program is free software; you can redistribute it and/or modify
616 it under the terms of the GNU General Public License as published by
617 the Free Software Foundation; either version 2, or (at your option)
620 This program is distributed in the hope that it will be useful,
621 but WITHOUT ANY WARRANTY; without even the implied warranty of
622 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
623 GNU General Public License for more details.
625 You should have received a copy of the GNU General Public License
626 along with this program; if not, write to the Free Software
627 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
629 /* As a special exception, when this file is copied by Bison into a
630 Bison output file, you may use that output file without restriction.
631 This special exception was added by the Free Software Foundation
632 in version 1.24 of Bison. */
636 #define alloca __builtin_alloca
637 #else /* not GNU C. */
638 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
640 #else /* not sparc */
641 #if defined (MSDOS) && !defined (__TURBOC__)
643 #else /* not MSDOS, or __TURBOC__ */
647 #else /* not MSDOS, __TURBOC__, or _AIX */
651 void *alloca (unsigned int);
653 #else /* not __cplusplus */
655 #endif /* not __cplusplus */
657 #endif /* not _AIX */
658 #endif /* not MSDOS, or __TURBOC__ */
659 #endif /* not sparc. */
660 #endif /* not GNU C. */
661 #endif /* alloca not defined. */
663 /* This is the parser code that is written into each bison parser
664 when the %semantic_parser declaration is not specified in the grammar.
665 It was written by Richard Stallman by simplifying the hairy parser
666 used when %semantic_parser is specified. */
668 /* Note: there must be only one dollar sign in this file.
669 It is replaced by the list of actions, each action
670 as one case of the switch. */
672 #define yyerrok (yyerrstatus = 0)
673 #define yyclearin (yychar = YYEMPTY)
676 #define YYACCEPT return(0)
677 #define YYABORT return(1)
678 #define YYERROR goto yyerrlab1
679 /* Like YYERROR except do call yyerror.
680 This remains here temporarily to ease the
681 transition to the new meaning of YYERROR, for GCC.
682 Once GCC version 2 has supplanted version 1, this can go. */
683 #define YYFAIL goto yyerrlab
684 #define YYRECOVERING() (!!yyerrstatus)
685 #define YYBACKUP(token, value) \
687 if (yychar == YYEMPTY && yylen == 1) \
688 { yychar = (token), yylval = (value); \
689 yychar1 = YYTRANSLATE (yychar); \
694 { yyerror ("syntax error: cannot back up"); YYERROR; } \
698 #define YYERRCODE 256
701 #define YYLEX yylex()
707 #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
709 #define YYLEX yylex(&yylval, &yylloc)
711 #else /* not YYLSP_NEEDED */
713 #define YYLEX yylex(&yylval, YYLEX_PARAM)
715 #define YYLEX yylex(&yylval)
717 #endif /* not YYLSP_NEEDED */
720 /* If nonreentrant, generate the variables here */
724 int yychar
; /* the lookahead symbol */
725 YYSTYPE yylval
; /* the semantic value of the */
726 /* lookahead symbol */
729 YYLTYPE yylloc
; /* location data for the lookahead */
733 int yynerrs
; /* number of parse errors so far */
734 #endif /* not YYPURE */
737 int yydebug
; /* nonzero means print parse trace */
738 /* Since this is uninitialized, it does not stop multiple parsers
742 /* YYINITDEPTH indicates the initial size of the parser's stacks */
745 #define YYINITDEPTH 200
748 /* YYMAXDEPTH is the maximum size the stacks can grow to
749 (effective only if the built-in stack extension method is used). */
756 #define YYMAXDEPTH 10000
759 /* Prevent warning if -Wstrict-prototypes. */
764 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
765 #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
766 #else /* not GNU C or C++ */
769 /* This is the most reliable way to avoid incompatibilities
770 in available built-in functions on various systems. */
772 __yy_memcpy (to
, from
, count
)
777 register char *f
= from
;
778 register char *t
= to
;
779 register int i
= count
;
785 #else /* __cplusplus */
787 /* This is the most reliable way to avoid incompatibilities
788 in available built-in functions on various systems. */
790 __yy_memcpy (char *to
, char *from
, int count
)
792 register char *f
= from
;
793 register char *t
= to
;
794 register int i
= count
;
803 #line 196 "/usr/share/misc/bison.simple"
805 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
806 into yyparse. The argument should have type void *.
807 It should actually point to an object.
808 Grammar actions can access the variable by casting it
809 to the proper pointer type. */
813 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
814 #define YYPARSE_PARAM_DECL
815 #else /* not __cplusplus */
816 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
817 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
818 #endif /* not __cplusplus */
819 #else /* not YYPARSE_PARAM */
820 #define YYPARSE_PARAM_ARG
821 #define YYPARSE_PARAM_DECL
822 #endif /* not YYPARSE_PARAM */
825 yyparse(YYPARSE_PARAM_ARG
)
828 register int yystate
;
830 register short *yyssp
;
831 register YYSTYPE
*yyvsp
;
832 int yyerrstatus
; /* number of tokens to shift before error messages enabled */
833 int yychar1
= 0; /* lookahead token as an internal (translated) token number */
835 short yyssa
[YYINITDEPTH
]; /* the state stack */
836 YYSTYPE yyvsa
[YYINITDEPTH
]; /* the semantic value stack */
838 short *yyss
= yyssa
; /* refer to the stacks thru separate pointers */
839 YYSTYPE
*yyvs
= yyvsa
; /* to allow yyoverflow to reallocate them elsewhere */
842 YYLTYPE yylsa
[YYINITDEPTH
]; /* the location stack */
843 YYLTYPE
*yyls
= yylsa
;
846 #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
848 #define YYPOPSTACK (yyvsp--, yyssp--)
851 int yystacksize
= YYINITDEPTH
;
862 YYSTYPE yyval
; /* the variable used to return */
863 /* semantic values from the action */
870 fprintf(stderr
, "Starting parse\n");
876 yychar
= YYEMPTY
; /* Cause a token to be read. */
878 /* Initialize stack pointers.
879 Waste one element of value and location stack
880 so that they stay on the same level as the state stack.
881 The wasted elements are never initialized. */
889 /* Push a new state, which is found in yystate . */
890 /* In all cases, when you get here, the value and location stacks
891 have just been pushed. so pushing a state here evens the stacks. */
896 if (yyssp
>= yyss
+ yystacksize
- 1)
898 /* Give user a chance to reallocate the stack */
899 /* Use copies of these so that the &'s don't force the real ones into memory. */
900 YYSTYPE
*yyvs1
= yyvs
;
903 YYLTYPE
*yyls1
= yyls
;
906 /* Get the current used size of the three stacks, in elements. */
907 int size
= yyssp
- yyss
+ 1;
910 /* Each stack pointer address is followed by the size of
911 the data in use in that stack, in bytes. */
913 /* This used to be a conditional around just the two extra args,
914 but that might be undefined if yyoverflow is a macro. */
915 yyoverflow("parser stack overflow",
916 &yyss1
, size
* sizeof (*yyssp
),
917 &yyvs1
, size
* sizeof (*yyvsp
),
918 &yyls1
, size
* sizeof (*yylsp
),
921 yyoverflow("parser stack overflow",
922 &yyss1
, size
* sizeof (*yyssp
),
923 &yyvs1
, size
* sizeof (*yyvsp
),
927 yyss
= yyss1
; yyvs
= yyvs1
;
931 #else /* no yyoverflow */
932 /* Extend the stack our own way. */
933 if (yystacksize
>= YYMAXDEPTH
)
935 yyerror("parser stack overflow");
939 if (yystacksize
> YYMAXDEPTH
)
940 yystacksize
= YYMAXDEPTH
;
941 yyss
= (short *) alloca (yystacksize
* sizeof (*yyssp
));
942 __yy_memcpy ((char *)yyss
, (char *)yyss1
, size
* sizeof (*yyssp
));
943 yyvs
= (YYSTYPE
*) alloca (yystacksize
* sizeof (*yyvsp
));
944 __yy_memcpy ((char *)yyvs
, (char *)yyvs1
, size
* sizeof (*yyvsp
));
946 yyls
= (YYLTYPE
*) alloca (yystacksize
* sizeof (*yylsp
));
947 __yy_memcpy ((char *)yyls
, (char *)yyls1
, size
* sizeof (*yylsp
));
949 #endif /* no yyoverflow */
951 yyssp
= yyss
+ size
- 1;
952 yyvsp
= yyvs
+ size
- 1;
954 yylsp
= yyls
+ size
- 1;
959 fprintf(stderr
, "Stack size increased to %d\n", yystacksize
);
962 if (yyssp
>= yyss
+ yystacksize
- 1)
968 fprintf(stderr
, "Entering state %d\n", yystate
);
974 /* Do appropriate processing given the current state. */
975 /* Read a lookahead token if we need one and don't already have one. */
978 /* First try to decide what to do without reference to lookahead token. */
980 yyn
= yypact
[yystate
];
984 /* Not known => get a lookahead token if don't already have one. */
986 /* yychar is either YYEMPTY or YYEOF
987 or a valid token in external form. */
989 if (yychar
== YYEMPTY
)
993 fprintf(stderr
, "Reading a token: ");
998 /* Convert token to internal form (in yychar1) for indexing tables with */
1000 if (yychar
<= 0) /* This means end of input. */
1003 yychar
= YYEOF
; /* Don't call YYLEX any more */
1007 fprintf(stderr
, "Now at end of input.\n");
1012 yychar1
= YYTRANSLATE(yychar
);
1017 fprintf (stderr
, "Next token is %d (%s", yychar
, yytname
[yychar1
]);
1018 /* Give the individual parser a way to print the precise meaning
1019 of a token, for further debugging info. */
1021 YYPRINT (stderr
, yychar
, yylval
);
1023 fprintf (stderr
, ")\n");
1029 if (yyn
< 0 || yyn
> YYLAST
|| yycheck
[yyn
] != yychar1
)
1034 /* yyn is what to do for this token type in this state.
1035 Negative => reduce, -yyn is rule number.
1036 Positive => shift, yyn is new state.
1037 New state is final state => don't bother to shift,
1038 just return success.
1039 0, or most negative number => error. */
1054 /* Shift the lookahead token. */
1058 fprintf(stderr
, "Shifting token %d (%s), ", yychar
, yytname
[yychar1
]);
1061 /* Discard the token being shifted unless it is eof. */
1062 if (yychar
!= YYEOF
)
1070 /* count tokens shifted since error; after three, turn off error status. */
1071 if (yyerrstatus
) yyerrstatus
--;
1076 /* Do the default action for the current state. */
1079 yyn
= yydefact
[yystate
];
1083 /* Do a reduction. yyn is the number of a rule to reduce with. */
1087 yyval
= yyvsp
[1-yylen
]; /* implement default value of the action */
1094 fprintf (stderr
, "Reducing via rule %d (line %d), ",
1097 /* Print the symbols being reduced, and their result. */
1098 for (i
= yyprhs
[yyn
]; yyrhs
[i
] > 0; i
++)
1099 fprintf (stderr
, "%s ", yytname
[yyrhs
[i
]]);
1100 fprintf (stderr
, " -> %s\n", yytname
[yyr1
[yyn
]]);
1108 #line 233 "/usr/homes/chet/src/bash/src/parse.y"
1110 /* Case of regular command. Discard the error
1111 safety net,and return the command just parsed. */
1112 global_command
= yyvsp
[-1].command
;
1113 eof_encountered
= 0;
1114 discard_parser_constructs (0);
1119 #line 242 "/usr/homes/chet/src/bash/src/parse.y"
1121 /* Case of regular command, but not a very
1122 interesting one. Return a NULL command. */
1123 global_command
= (COMMAND
*)NULL
;
1128 #line 249 "/usr/homes/chet/src/bash/src/parse.y"
1130 /* Error during parsing. Return NULL command. */
1131 global_command
= (COMMAND
*)NULL
;
1132 eof_encountered
= 0;
1133 discard_parser_constructs (1);
1145 #line 264 "/usr/homes/chet/src/bash/src/parse.y"
1147 /* Case of EOF seen by itself. Do ignoreeof or
1149 global_command
= (COMMAND
*)NULL
;
1150 handle_eof_input_unit ();
1155 #line 274 "/usr/homes/chet/src/bash/src/parse.y"
1156 { yyval
.word_list
= make_word_list (yyvsp
[0].word
, (WORD_LIST
*)NULL
); ;
1159 #line 276 "/usr/homes/chet/src/bash/src/parse.y"
1160 { yyval
.word_list
= make_word_list (yyvsp
[0].word
, yyvsp
[-1].word_list
); ;
1163 #line 280 "/usr/homes/chet/src/bash/src/parse.y"
1165 redir
.filename
= yyvsp
[0].word
;
1166 yyval
.redirect
= make_redirection (1, r_output_direction
, redir
);
1170 #line 285 "/usr/homes/chet/src/bash/src/parse.y"
1172 redir
.filename
= yyvsp
[0].word
;
1173 yyval
.redirect
= make_redirection (0, r_input_direction
, redir
);
1177 #line 290 "/usr/homes/chet/src/bash/src/parse.y"
1179 redir
.filename
= yyvsp
[0].word
;
1180 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_output_direction
, redir
);
1184 #line 295 "/usr/homes/chet/src/bash/src/parse.y"
1186 redir
.filename
= yyvsp
[0].word
;
1187 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_input_direction
, redir
);
1191 #line 300 "/usr/homes/chet/src/bash/src/parse.y"
1193 redir
.filename
= yyvsp
[0].word
;
1194 yyval
.redirect
= make_redirection (1, r_appending_to
, redir
);
1198 #line 305 "/usr/homes/chet/src/bash/src/parse.y"
1200 redir
.filename
= yyvsp
[0].word
;
1201 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_appending_to
, redir
);
1205 #line 310 "/usr/homes/chet/src/bash/src/parse.y"
1207 redir
.filename
= yyvsp
[0].word
;
1208 yyval
.redirect
= make_redirection (0, r_reading_until
, redir
);
1209 redir_stack
[need_here_doc
++] = yyval
.redirect
;
1213 #line 316 "/usr/homes/chet/src/bash/src/parse.y"
1215 redir
.filename
= yyvsp
[0].word
;
1216 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_reading_until
, redir
);
1217 redir_stack
[need_here_doc
++] = yyval
.redirect
;
1221 #line 322 "/usr/homes/chet/src/bash/src/parse.y"
1223 redir
.dest
= yyvsp
[0].number
;
1224 yyval
.redirect
= make_redirection (0, r_duplicating_input
, redir
);
1228 #line 327 "/usr/homes/chet/src/bash/src/parse.y"
1230 redir
.dest
= yyvsp
[0].number
;
1231 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_duplicating_input
, redir
);
1235 #line 332 "/usr/homes/chet/src/bash/src/parse.y"
1237 redir
.dest
= yyvsp
[0].number
;
1238 yyval
.redirect
= make_redirection (1, r_duplicating_output
, redir
);
1242 #line 337 "/usr/homes/chet/src/bash/src/parse.y"
1244 redir
.dest
= yyvsp
[0].number
;
1245 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_duplicating_output
, redir
);
1249 #line 342 "/usr/homes/chet/src/bash/src/parse.y"
1251 redir
.filename
= yyvsp
[0].word
;
1252 yyval
.redirect
= make_redirection (0, r_duplicating_input_word
, redir
);
1256 #line 347 "/usr/homes/chet/src/bash/src/parse.y"
1258 redir
.filename
= yyvsp
[0].word
;
1259 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_duplicating_input_word
, redir
);
1263 #line 352 "/usr/homes/chet/src/bash/src/parse.y"
1265 redir
.filename
= yyvsp
[0].word
;
1266 yyval
.redirect
= make_redirection (1, r_duplicating_output_word
, redir
);
1270 #line 357 "/usr/homes/chet/src/bash/src/parse.y"
1272 redir
.filename
= yyvsp
[0].word
;
1273 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_duplicating_output_word
, redir
);
1277 #line 362 "/usr/homes/chet/src/bash/src/parse.y"
1279 redir
.filename
= yyvsp
[0].word
;
1280 yyval
.redirect
= make_redirection
1281 (0, r_deblank_reading_until
, redir
);
1282 redir_stack
[need_here_doc
++] = yyval
.redirect
;
1286 #line 369 "/usr/homes/chet/src/bash/src/parse.y"
1288 redir
.filename
= yyvsp
[0].word
;
1289 yyval
.redirect
= make_redirection
1290 (yyvsp
[-2].number
, r_deblank_reading_until
, redir
);
1291 redir_stack
[need_here_doc
++] = yyval
.redirect
;
1295 #line 376 "/usr/homes/chet/src/bash/src/parse.y"
1298 yyval
.redirect
= make_redirection (1, r_close_this
, redir
);
1302 #line 381 "/usr/homes/chet/src/bash/src/parse.y"
1305 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_close_this
, redir
);
1309 #line 386 "/usr/homes/chet/src/bash/src/parse.y"
1312 yyval
.redirect
= make_redirection (0, r_close_this
, redir
);
1316 #line 391 "/usr/homes/chet/src/bash/src/parse.y"
1319 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_close_this
, redir
);
1323 #line 396 "/usr/homes/chet/src/bash/src/parse.y"
1325 redir
.filename
= yyvsp
[0].word
;
1326 yyval
.redirect
= make_redirection (1, r_err_and_out
, redir
);
1330 #line 401 "/usr/homes/chet/src/bash/src/parse.y"
1332 redir
.filename
= yyvsp
[0].word
;
1333 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_input_output
, redir
);
1337 #line 406 "/usr/homes/chet/src/bash/src/parse.y"
1339 redir
.filename
= yyvsp
[0].word
;
1340 yyval
.redirect
= make_redirection (0, r_input_output
, redir
);
1344 #line 411 "/usr/homes/chet/src/bash/src/parse.y"
1346 redir
.filename
= yyvsp
[0].word
;
1347 yyval
.redirect
= make_redirection (1, r_output_force
, redir
);
1351 #line 416 "/usr/homes/chet/src/bash/src/parse.y"
1353 redir
.filename
= yyvsp
[0].word
;
1354 yyval
.redirect
= make_redirection (yyvsp
[-2].number
, r_output_force
, redir
);
1358 #line 423 "/usr/homes/chet/src/bash/src/parse.y"
1359 { yyval
.element
.word
= yyvsp
[0].word
; yyval
.element
.redirect
= 0; ;
1362 #line 425 "/usr/homes/chet/src/bash/src/parse.y"
1363 { yyval
.element
.word
= yyvsp
[0].word
; yyval
.element
.redirect
= 0; ;
1366 #line 427 "/usr/homes/chet/src/bash/src/parse.y"
1367 { yyval
.element
.redirect
= yyvsp
[0].redirect
; yyval
.element
.word
= 0; ;
1370 #line 431 "/usr/homes/chet/src/bash/src/parse.y"
1372 yyval
.redirect
= yyvsp
[0].redirect
;
1376 #line 435 "/usr/homes/chet/src/bash/src/parse.y"
1378 register REDIRECT
*t
;
1380 for (t
= yyvsp
[-1].redirect
; t
->next
; t
= t
->next
)
1382 t
->next
= yyvsp
[0].redirect
;
1383 yyval
.redirect
= yyvsp
[-1].redirect
;
1387 #line 446 "/usr/homes/chet/src/bash/src/parse.y"
1388 { yyval
.command
= make_simple_command (yyvsp
[0].element
, (COMMAND
*)NULL
); ;
1391 #line 448 "/usr/homes/chet/src/bash/src/parse.y"
1392 { yyval
.command
= make_simple_command (yyvsp
[0].element
, yyvsp
[-1].command
); ;
1395 #line 452 "/usr/homes/chet/src/bash/src/parse.y"
1396 { yyval
.command
= clean_simple_command (yyvsp
[0].command
); ;
1399 #line 454 "/usr/homes/chet/src/bash/src/parse.y"
1400 { yyval
.command
= yyvsp
[0].command
; ;
1403 #line 456 "/usr/homes/chet/src/bash/src/parse.y"
1407 tc
= yyvsp
[-1].command
;
1408 /* According to Posix.2 3.9.5, redirections
1409 specified after the body of a function should
1410 be attached to the function and performed when
1411 the function is executed, not as part of the
1412 function definition command. */
1413 if (tc
->type
== cm_function_def
)
1415 tc
= tc
->value
.Function_def
->command
;
1416 if (tc
->type
== cm_group
)
1417 tc
= tc
->value
.Group
->command
;
1421 register REDIRECT
*t
;
1422 for (t
= tc
->redirects
; t
->next
; t
= t
->next
)
1424 t
->next
= yyvsp
[0].redirect
;
1427 tc
->redirects
= yyvsp
[0].redirect
;
1428 yyval
.command
= yyvsp
[-1].command
;
1432 #line 485 "/usr/homes/chet/src/bash/src/parse.y"
1433 { yyval
.command
= yyvsp
[0].command
; ;
1436 #line 487 "/usr/homes/chet/src/bash/src/parse.y"
1437 { yyval
.command
= yyvsp
[0].command
; ;
1440 #line 489 "/usr/homes/chet/src/bash/src/parse.y"
1441 { yyval
.command
= make_while_command (yyvsp
[-3].command
, yyvsp
[-1].command
); ;
1444 #line 491 "/usr/homes/chet/src/bash/src/parse.y"
1445 { yyval
.command
= make_until_command (yyvsp
[-3].command
, yyvsp
[-1].command
); ;
1448 #line 493 "/usr/homes/chet/src/bash/src/parse.y"
1449 { yyval
.command
= yyvsp
[0].command
; ;
1452 #line 495 "/usr/homes/chet/src/bash/src/parse.y"
1453 { yyval
.command
= yyvsp
[0].command
; ;
1456 #line 497 "/usr/homes/chet/src/bash/src/parse.y"
1457 { yyval
.command
= yyvsp
[0].command
; ;
1460 #line 499 "/usr/homes/chet/src/bash/src/parse.y"
1461 { yyval
.command
= yyvsp
[0].command
; ;
1464 #line 501 "/usr/homes/chet/src/bash/src/parse.y"
1465 { yyval
.command
= yyvsp
[0].command
; ;
1468 #line 503 "/usr/homes/chet/src/bash/src/parse.y"
1469 { yyval
.command
= yyvsp
[0].command
; ;
1472 #line 505 "/usr/homes/chet/src/bash/src/parse.y"
1473 { yyval
.command
= yyvsp
[0].command
; ;
1476 #line 509 "/usr/homes/chet/src/bash/src/parse.y"
1477 { yyval
.command
= make_for_command (yyvsp
[-4].word
, add_string_to_list ("\"$@\"", (WORD_LIST
*)NULL
), yyvsp
[-1].command
); ;
1480 #line 511 "/usr/homes/chet/src/bash/src/parse.y"
1481 { yyval
.command
= make_for_command (yyvsp
[-4].word
, add_string_to_list ("$@", (WORD_LIST
*)NULL
), yyvsp
[-1].command
); ;
1484 #line 513 "/usr/homes/chet/src/bash/src/parse.y"
1485 { yyval
.command
= make_for_command (yyvsp
[-5].word
, add_string_to_list ("\"$@\"", (WORD_LIST
*)NULL
), yyvsp
[-1].command
); ;
1488 #line 515 "/usr/homes/chet/src/bash/src/parse.y"
1489 { yyval
.command
= make_for_command (yyvsp
[-5].word
, add_string_to_list ("\"$@\"", (WORD_LIST
*)NULL
), yyvsp
[-1].command
); ;
1492 #line 517 "/usr/homes/chet/src/bash/src/parse.y"
1493 { yyval
.command
= make_for_command (yyvsp
[-8].word
, REVERSE_LIST (yyvsp
[-5].word_list
, WORD_LIST
*), yyvsp
[-1].command
); ;
1496 #line 519 "/usr/homes/chet/src/bash/src/parse.y"
1497 { yyval
.command
= make_for_command (yyvsp
[-8].word
, REVERSE_LIST (yyvsp
[-5].word_list
, WORD_LIST
*), yyvsp
[-1].command
); ;
1500 #line 523 "/usr/homes/chet/src/bash/src/parse.y"
1502 yyval
.command
= make_select_command (yyvsp
[-4].word
, add_string_to_list ("\"$@\"", (WORD_LIST
*)NULL
), yyvsp
[-1].command
);
1506 #line 527 "/usr/homes/chet/src/bash/src/parse.y"
1508 yyval
.command
= make_select_command (yyvsp
[-4].word
, add_string_to_list ("$@", (WORD_LIST
*)NULL
), yyvsp
[-1].command
);
1512 #line 531 "/usr/homes/chet/src/bash/src/parse.y"
1514 yyval
.command
= make_select_command (yyvsp
[-5].word
, add_string_to_list ("\"$@\"", (WORD_LIST
*)NULL
), yyvsp
[-1].command
);
1518 #line 535 "/usr/homes/chet/src/bash/src/parse.y"
1520 yyval
.command
= make_select_command (yyvsp
[-5].word
, add_string_to_list ("\"$@\"", (WORD_LIST
*)NULL
), yyvsp
[-1].command
);
1524 #line 539 "/usr/homes/chet/src/bash/src/parse.y"
1526 yyval
.command
= make_select_command (yyvsp
[-8].word
, (WORD_LIST
*)reverse_list (yyvsp
[-5].word_list
), yyvsp
[-1].command
);
1530 #line 543 "/usr/homes/chet/src/bash/src/parse.y"
1532 yyval
.command
= make_select_command (yyvsp
[-8].word
, (WORD_LIST
*)reverse_list (yyvsp
[-5].word_list
), yyvsp
[-1].command
);
1536 #line 549 "/usr/homes/chet/src/bash/src/parse.y"
1537 { yyval
.command
= make_case_command (yyvsp
[-4].word
, (PATTERN_LIST
*)NULL
); ;
1540 #line 551 "/usr/homes/chet/src/bash/src/parse.y"
1541 { yyval
.command
= make_case_command (yyvsp
[-5].word
, yyvsp
[-2].pattern
); ;
1544 #line 553 "/usr/homes/chet/src/bash/src/parse.y"
1545 { yyval
.command
= make_case_command (yyvsp
[-4].word
, yyvsp
[-1].pattern
); ;
1548 #line 557 "/usr/homes/chet/src/bash/src/parse.y"
1549 { yyval
.command
= make_function_def (yyvsp
[-4].word
, yyvsp
[0].command
, function_dstart
, function_bstart
); ;
1552 #line 561 "/usr/homes/chet/src/bash/src/parse.y"
1553 { yyval
.command
= make_function_def (yyvsp
[-4].word
, yyvsp
[0].command
, function_dstart
, function_bstart
); ;
1556 #line 564 "/usr/homes/chet/src/bash/src/parse.y"
1557 { yyval
.command
= make_function_def (yyvsp
[-2].word
, yyvsp
[0].command
, function_dstart
, function_bstart
); ;
1560 #line 568 "/usr/homes/chet/src/bash/src/parse.y"
1561 { yyvsp
[-1].command
->flags
|= CMD_WANT_SUBSHELL
; yyval
.command
= yyvsp
[-1].command
; ;
1564 #line 572 "/usr/homes/chet/src/bash/src/parse.y"
1565 { yyval
.command
= make_if_command (yyvsp
[-3].command
, yyvsp
[-1].command
, (COMMAND
*)NULL
); ;
1568 #line 574 "/usr/homes/chet/src/bash/src/parse.y"
1569 { yyval
.command
= make_if_command (yyvsp
[-5].command
, yyvsp
[-3].command
, yyvsp
[-1].command
); ;
1572 #line 576 "/usr/homes/chet/src/bash/src/parse.y"
1573 { yyval
.command
= make_if_command (yyvsp
[-4].command
, yyvsp
[-2].command
, yyvsp
[-1].command
); ;
1576 #line 581 "/usr/homes/chet/src/bash/src/parse.y"
1577 { yyval
.command
= make_group_command (yyvsp
[-1].command
); ;
1580 #line 585 "/usr/homes/chet/src/bash/src/parse.y"
1581 { yyval
.command
= make_arith_command (yyvsp
[0].word_list
); ;
1584 #line 589 "/usr/homes/chet/src/bash/src/parse.y"
1585 { yyval
.command
= yyvsp
[-1].command
; ;
1588 #line 593 "/usr/homes/chet/src/bash/src/parse.y"
1589 { yyval
.command
= make_if_command (yyvsp
[-2].command
, yyvsp
[0].command
, (COMMAND
*)NULL
); ;
1592 #line 595 "/usr/homes/chet/src/bash/src/parse.y"
1593 { yyval
.command
= make_if_command (yyvsp
[-4].command
, yyvsp
[-2].command
, yyvsp
[0].command
); ;
1596 #line 597 "/usr/homes/chet/src/bash/src/parse.y"
1597 { yyval
.command
= make_if_command (yyvsp
[-3].command
, yyvsp
[-1].command
, yyvsp
[0].command
); ;
1600 #line 602 "/usr/homes/chet/src/bash/src/parse.y"
1601 { yyvsp
[0].pattern
->next
= yyvsp
[-1].pattern
; yyval
.pattern
= yyvsp
[0].pattern
; ;
1604 #line 606 "/usr/homes/chet/src/bash/src/parse.y"
1605 { yyval
.pattern
= make_pattern_list (yyvsp
[-2].word_list
, yyvsp
[0].command
); ;
1608 #line 608 "/usr/homes/chet/src/bash/src/parse.y"
1609 { yyval
.pattern
= make_pattern_list (yyvsp
[-2].word_list
, (COMMAND
*)NULL
); ;
1612 #line 610 "/usr/homes/chet/src/bash/src/parse.y"
1613 { yyval
.pattern
= make_pattern_list (yyvsp
[-2].word_list
, yyvsp
[0].command
); ;
1616 #line 612 "/usr/homes/chet/src/bash/src/parse.y"
1617 { yyval
.pattern
= make_pattern_list (yyvsp
[-2].word_list
, (COMMAND
*)NULL
); ;
1620 #line 617 "/usr/homes/chet/src/bash/src/parse.y"
1621 { yyvsp
[-1].pattern
->next
= yyvsp
[-2].pattern
; yyval
.pattern
= yyvsp
[-1].pattern
; ;
1624 #line 621 "/usr/homes/chet/src/bash/src/parse.y"
1625 { yyval
.word_list
= make_word_list (yyvsp
[0].word
, (WORD_LIST
*)NULL
); ;
1628 #line 623 "/usr/homes/chet/src/bash/src/parse.y"
1629 { yyval
.word_list
= make_word_list (yyvsp
[0].word
, yyvsp
[-2].word_list
); ;
1632 #line 632 "/usr/homes/chet/src/bash/src/parse.y"
1634 yyval
.command
= yyvsp
[0].command
;
1636 gather_here_documents ();
1640 #line 641 "/usr/homes/chet/src/bash/src/parse.y"
1642 yyval
.command
= yyvsp
[0].command
;
1646 #line 648 "/usr/homes/chet/src/bash/src/parse.y"
1648 if (yyvsp
[-2].command
->type
== cm_connection
)
1649 yyval
.command
= connect_async_list (yyvsp
[-2].command
, (COMMAND
*)NULL
, '&');
1651 yyval
.command
= command_connect (yyvsp
[-2].command
, (COMMAND
*)NULL
, '&');
1655 #line 659 "/usr/homes/chet/src/bash/src/parse.y"
1656 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, AND_AND
); ;
1659 #line 661 "/usr/homes/chet/src/bash/src/parse.y"
1660 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, OR_OR
); ;
1663 #line 663 "/usr/homes/chet/src/bash/src/parse.y"
1665 if (yyvsp
[-3].command
->type
== cm_connection
)
1666 yyval
.command
= connect_async_list (yyvsp
[-3].command
, yyvsp
[0].command
, '&');
1668 yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, '&');
1672 #line 670 "/usr/homes/chet/src/bash/src/parse.y"
1673 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, ';'); ;
1676 #line 672 "/usr/homes/chet/src/bash/src/parse.y"
1677 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, ';'); ;
1680 #line 674 "/usr/homes/chet/src/bash/src/parse.y"
1681 { yyval
.command
= yyvsp
[0].command
; ;
1684 #line 693 "/usr/homes/chet/src/bash/src/parse.y"
1686 yyval
.command
= yyvsp
[0].command
;
1688 gather_here_documents ();
1692 #line 699 "/usr/homes/chet/src/bash/src/parse.y"
1694 if (yyvsp
[-1].command
->type
== cm_connection
)
1695 yyval
.command
= connect_async_list (yyvsp
[-1].command
, (COMMAND
*)NULL
, '&');
1697 yyval
.command
= command_connect (yyvsp
[-1].command
, (COMMAND
*)NULL
, '&');
1699 gather_here_documents ();
1703 #line 708 "/usr/homes/chet/src/bash/src/parse.y"
1705 yyval
.command
= yyvsp
[-1].command
;
1707 gather_here_documents ();
1711 #line 716 "/usr/homes/chet/src/bash/src/parse.y"
1712 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, AND_AND
); ;
1715 #line 718 "/usr/homes/chet/src/bash/src/parse.y"
1716 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, OR_OR
); ;
1719 #line 720 "/usr/homes/chet/src/bash/src/parse.y"
1721 if (yyvsp
[-2].command
->type
== cm_connection
)
1722 yyval
.command
= connect_async_list (yyvsp
[-2].command
, yyvsp
[0].command
, '&');
1724 yyval
.command
= command_connect (yyvsp
[-2].command
, yyvsp
[0].command
, '&');
1728 #line 727 "/usr/homes/chet/src/bash/src/parse.y"
1729 { yyval
.command
= command_connect (yyvsp
[-2].command
, yyvsp
[0].command
, ';'); ;
1732 #line 730 "/usr/homes/chet/src/bash/src/parse.y"
1733 { yyval
.command
= yyvsp
[0].command
; ;
1736 #line 734 "/usr/homes/chet/src/bash/src/parse.y"
1737 { yyval
.command
= yyvsp
[0].command
; ;
1740 #line 736 "/usr/homes/chet/src/bash/src/parse.y"
1742 yyvsp
[0].command
->flags
|= CMD_INVERT_RETURN
;
1743 yyval
.command
= yyvsp
[0].command
;
1747 #line 741 "/usr/homes/chet/src/bash/src/parse.y"
1749 yyvsp
[0].command
->flags
|= yyvsp
[-1].number
;
1750 yyval
.command
= yyvsp
[0].command
;
1754 #line 746 "/usr/homes/chet/src/bash/src/parse.y"
1756 yyvsp
[0].command
->flags
|= yyvsp
[-2].number
;
1757 yyval
.command
= yyvsp
[0].command
;
1761 #line 751 "/usr/homes/chet/src/bash/src/parse.y"
1763 yyvsp
[0].command
->flags
|= yyvsp
[-1].number
|CMD_INVERT_RETURN
;
1764 yyval
.command
= yyvsp
[0].command
;
1768 #line 759 "/usr/homes/chet/src/bash/src/parse.y"
1769 { yyval
.command
= command_connect (yyvsp
[-3].command
, yyvsp
[0].command
, '|'); ;
1772 #line 761 "/usr/homes/chet/src/bash/src/parse.y"
1773 { yyval
.command
= yyvsp
[0].command
; ;
1776 #line 765 "/usr/homes/chet/src/bash/src/parse.y"
1777 { yyval
.number
= CMD_TIME_PIPELINE
; ;
1780 #line 767 "/usr/homes/chet/src/bash/src/parse.y"
1781 { yyval
.number
= CMD_TIME_PIPELINE
|CMD_TIME_POSIX
; ;
1784 /* the action file gets copied in in place of this dollarsign */
1785 #line 498 "/usr/share/misc/bison.simple"
1796 short *ssp1
= yyss
- 1;
1797 fprintf (stderr
, "state stack now");
1798 while (ssp1
!= yyssp
)
1799 fprintf (stderr
, " %d", *++ssp1
);
1800 fprintf (stderr
, "\n");
1810 yylsp
->first_line
= yylloc
.first_line
;
1811 yylsp
->first_column
= yylloc
.first_column
;
1812 yylsp
->last_line
= (yylsp
-1)->last_line
;
1813 yylsp
->last_column
= (yylsp
-1)->last_column
;
1818 yylsp
->last_line
= (yylsp
+yylen
-1)->last_line
;
1819 yylsp
->last_column
= (yylsp
+yylen
-1)->last_column
;
1823 /* Now "shift" the result of the reduction.
1824 Determine what state that goes to,
1825 based on the state we popped back to
1826 and the rule number reduced by. */
1830 yystate
= yypgoto
[yyn
- YYNTBASE
] + *yyssp
;
1831 if (yystate
>= 0 && yystate
<= YYLAST
&& yycheck
[yystate
] == *yyssp
)
1832 yystate
= yytable
[yystate
];
1834 yystate
= yydefgoto
[yyn
- YYNTBASE
];
1838 yyerrlab
: /* here on detecting error */
1841 /* If not already recovering from an error, report this error. */
1845 #ifdef YYERROR_VERBOSE
1846 yyn
= yypact
[yystate
];
1848 if (yyn
> YYFLAG
&& yyn
< YYLAST
)
1855 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
1856 for (x
= (yyn
< 0 ? -yyn
: 0);
1857 x
< (sizeof(yytname
) / sizeof(char *)); x
++)
1858 if (yycheck
[x
+ yyn
] == x
)
1859 size
+= strlen(yytname
[x
]) + 15, count
++;
1860 msg
= (char *) malloc(size
+ 15);
1863 strcpy(msg
, "parse error");
1868 for (x
= (yyn
< 0 ? -yyn
: 0);
1869 x
< (sizeof(yytname
) / sizeof(char *)); x
++)
1870 if (yycheck
[x
+ yyn
] == x
)
1872 strcat(msg
, count
== 0 ? ", expecting `" : " or `");
1873 strcat(msg
, yytname
[x
]);
1882 yyerror ("parse error; also virtual memory exceeded");
1885 #endif /* YYERROR_VERBOSE */
1886 yyerror("parse error");
1890 yyerrlab1
: /* here on error raised explicitly by an action */
1892 if (yyerrstatus
== 3)
1894 /* if just tried and failed to reuse lookahead token after an error, discard it. */
1896 /* return failure if at end of input */
1897 if (yychar
== YYEOF
)
1902 fprintf(stderr
, "Discarding token %d (%s).\n", yychar
, yytname
[yychar1
]);
1908 /* Else will try to reuse lookahead token
1909 after shifting the error token. */
1911 yyerrstatus
= 3; /* Each real token shifted decrements this */
1915 yyerrdefault
: /* current state does not do anything special for the error token. */
1918 /* This is wrong; only states that explicitly want error tokens
1919 should shift them. */
1920 yyn
= yydefact
[yystate
]; /* If its default is to accept any token, ok. Otherwise pop it.*/
1921 if (yyn
) goto yydefault
;
1924 yyerrpop
: /* pop the current state because it cannot handle the error token */
1926 if (yyssp
== yyss
) YYABORT
;
1936 short *ssp1
= yyss
- 1;
1937 fprintf (stderr
, "Error: state stack now");
1938 while (ssp1
!= yyssp
)
1939 fprintf (stderr
, " %d", *++ssp1
);
1940 fprintf (stderr
, "\n");
1946 yyn
= yypact
[yystate
];
1951 if (yyn
< 0 || yyn
> YYLAST
|| yycheck
[yyn
] != YYTERROR
)
1970 fprintf(stderr
, "Shifting error token, ");
1981 #line 769 "/usr/homes/chet/src/bash/src/parse.y"
1984 /* Possible states for the parser that require it to do special things. */
1985 #define PST_CASEPAT 0x001 /* in a case pattern list */
1986 #define PST_ALEXPNEXT 0x002 /* expand next word for aliases */
1987 #define PST_ALLOWOPNBRC 0x004 /* allow open brace for function def */
1988 #define PST_NEEDCLOSBRC 0x008 /* need close brace */
1989 #define PST_DBLPAREN 0x010 /* double-paren parsing */
1990 #define PST_SUBSHELL 0x020 /* ( ... ) subshell */
1991 #define PST_CMDSUBST 0x040 /* $( ... ) command substitution */
1992 #define PST_CASESTMT 0x080 /* parsing a case statement */
1993 #define PST_CONDCMD 0x100 /* parsing a [[...]] command */
1994 #define PST_CONDEXPR 0x200 /* parsing the guts of [[...]] */
1996 /* Initial size to allocate for tokens, and the
1997 amount to grow them by. */
1998 #define TOKEN_DEFAULT_INITIAL_SIZE 496
1999 #define TOKEN_DEFAULT_GROW_SIZE 512
2001 /* Shell meta-characters that, when unquoted, separate words. */
2002 #define shellmeta(c) (strchr ("()<>;&|", (c)) != 0)
2003 #define shellbreak(c) (strchr ("()<>;&| \t\n", (c)) != 0)
2004 #define shellquote(c) ((c) == '"' || (c) == '`' || (c) == '\'')
2005 #define shellexp(c) ((c) == '$' || (c) == '<' || (c) == '>')
2007 /* The token currently being read. */
2008 static int current_token
;
2010 /* The last read token, or NULL. read_token () uses this for context
2012 static int last_read_token
;
2014 /* The token read prior to last_read_token. */
2015 static int token_before_that
;
2017 /* The token read prior to token_before_that. */
2018 static int two_tokens_ago
;
2020 /* If non-zero, it is the token that we want read_token to return
2021 regardless of what text is (or isn't) present to be read. This
2022 is reset by read_token. If token_to_read == WORD or
2023 ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */
2024 static int token_to_read
;
2025 static WORD_DESC
*word_desc_to_read
;
2027 /* The current parser state. */
2028 static int parser_state
;
2030 /* Global var is non-zero when end of file has been reached. */
2031 int EOF_Reached
= 0;
2042 /* yy_getc () returns the next available character from input or EOF.
2043 yy_ungetc (c) makes `c' the next character to read.
2044 init_yy_io (get, unget, type, location) makes the function GET the
2045 installed function for getting the next character, makes UNGET the
2046 installed function for un-getting a character, sets the type of stream
2047 (either string or file) from TYPE, and makes LOCATION point to where
2048 the input is coming from. */
2050 /* Unconditionally returns end-of-file. */
2057 /* Variable containing the current get and unget functions.
2058 See ./input.h for a clearer description. */
2059 BASH_INPUT bash_input
;
2061 /* Set all of the fields in BASH_INPUT to NULL. Free bash_input.name if it
2062 is non-null, avoiding a memory leak. */
2064 initialize_bash_input ()
2066 bash_input
.type
= st_none
;
2067 FREE (bash_input
.name
);
2068 bash_input
.name
= (char *)NULL
;
2069 bash_input
.location
.file
= (FILE *)NULL
;
2070 bash_input
.location
.string
= (char *)NULL
;
2071 bash_input
.getter
= (Function
*)NULL
;
2072 bash_input
.ungetter
= (Function
*)NULL
;
2075 /* Set the contents of the current bash input stream from
2076 GET, UNGET, TYPE, NAME, and LOCATION. */
2078 init_yy_io (get
, unget
, type
, name
, location
)
2079 Function
*get
, *unget
;
2080 enum stream_type type
;
2082 INPUT_STREAM location
;
2084 bash_input
.type
= type
;
2085 FREE (bash_input
.name
);
2086 bash_input
.name
= name
? savestring (name
) : (char *)NULL
;
2090 memcpy((char *)&bash_input
.location
.string
, (char *)&location
.string
, sizeof(location
));
2092 bash_input
.location
= location
;
2094 bash_input
.getter
= get
;
2095 bash_input
.ungetter
= unget
;
2098 /* Call this to get the next character of input. */
2102 return (*(bash_input
.getter
)) ();
2105 /* Call this to unget C. That is, to make C the next character
2111 return (*(bash_input
.ungetter
)) (c
);
2114 #if defined (BUFFERED_INPUT)
2116 input_file_descriptor ()
2118 switch (bash_input
.type
)
2121 return (fileno (bash_input
.location
.file
));
2123 return (bash_input
.location
.buffered_fd
);
2126 return (fileno (stdin
));
2129 #endif /* BUFFERED_INPUT */
2131 /* **************************************************************** */
2133 /* Let input be read from readline (). */
2135 /* **************************************************************** */
2137 #if defined (READLINE)
2138 char *current_readline_prompt
= (char *)NULL
;
2139 char *current_readline_line
= (char *)NULL
;
2140 int current_readline_line_index
= 0;
2145 SigHandler
*old_sigint
;
2148 if (!current_readline_line
)
2150 if (!bash_readline_initialized
)
2151 initialize_readline ();
2153 #if defined (JOB_CONTROL)
2155 give_terminal_to (shell_pgrp
);
2156 #endif /* JOB_CONTROL */
2158 if (signal_is_ignored (SIGINT
) == 0)
2160 old_sigint
= (SigHandler
*)set_signal_handler (SIGINT
, sigint_sighandler
);
2161 interrupt_immediately
++;
2164 current_readline_line
= readline (current_readline_prompt
?
2165 current_readline_prompt
: "");
2167 if (signal_is_ignored (SIGINT
) == 0)
2169 interrupt_immediately
--;
2170 set_signal_handler (SIGINT
, old_sigint
);
2174 /* Reset the prompt to the decoded value of prompt_string_pointer. */
2175 reset_readline_prompt ();
2178 if (current_readline_line
== 0)
2181 current_readline_line_index
= 0;
2182 line_len
= strlen (current_readline_line
);
2184 current_readline_line
= xrealloc (current_readline_line
, 2 + line_len
);
2185 current_readline_line
[line_len
++] = '\n';
2186 current_readline_line
[line_len
] = '\0';
2189 if (current_readline_line
[current_readline_line_index
] == 0)
2191 free (current_readline_line
);
2192 current_readline_line
= (char *)NULL
;
2193 return (yy_readline_get ());
2197 c
= (unsigned char)current_readline_line
[current_readline_line_index
++];
2203 yy_readline_unget (c
)
2206 if (current_readline_line_index
&& current_readline_line
)
2207 current_readline_line
[--current_readline_line_index
] = c
;
2212 with_input_from_stdin ()
2214 INPUT_STREAM location
;
2216 if (bash_input
.type
!= st_stdin
&& stream_on_stack (st_stdin
) == 0)
2218 location
.string
= current_readline_line
;
2219 init_yy_io (yy_readline_get
, yy_readline_unget
,
2220 st_stdin
, "readline stdin", location
);
2224 #else /* !READLINE */
2227 with_input_from_stdin ()
2229 with_input_from_stream (stdin
, "stdin");
2231 #endif /* !READLINE */
2233 /* **************************************************************** */
2235 /* Let input come from STRING. STRING is zero terminated. */
2237 /* **************************************************************** */
2242 register char *string
;
2245 string
= bash_input
.location
.string
;
2248 /* If the string doesn't exist, or is empty, EOF found. */
2249 if (string
&& *string
)
2251 c
= *(unsigned char *)string
++;
2252 bash_input
.location
.string
= string
;
2261 *(--bash_input
.location
.string
) = c
;
2266 with_input_from_string (string
, name
)
2267 char *string
, *name
;
2269 INPUT_STREAM location
;
2271 location
.string
= string
;
2272 init_yy_io (yy_string_get
, yy_string_unget
, st_string
, name
, location
);
2275 /* **************************************************************** */
2277 /* Let input come from STREAM. */
2279 /* **************************************************************** */
2286 if (bash_input
.location
.file
)
2288 #if !defined (HAVE_RESTARTABLE_SYSCALLS)
2289 result
= getc_with_restart (bash_input
.location
.file
);
2290 #else /* HAVE_RESTARTABLE_SYSCALLS */
2291 result
= getc (bash_input
.location
.file
);
2292 result
= (feof (bash_input
.location
.file
)) ? EOF
: (unsigned char)result
;
2293 #endif /* HAVE_RESTARTABLE_SYSCALLS */
2302 #if !defined (HAVE_RESTARTABLE_SYSCALLS)
2303 return (ungetc_with_restart (c
, bash_input
.location
.file
));
2304 #else /* HAVE_RESTARTABLE_SYSCALLS */
2305 return (ungetc (c
, bash_input
.location
.file
));
2306 #endif /* HAVE_RESTARTABLE_SYSCALLS */
2310 with_input_from_stream (stream
, name
)
2314 INPUT_STREAM location
;
2316 location
.file
= stream
;
2317 init_yy_io (yy_stream_get
, yy_stream_unget
, st_stream
, name
, location
);
2320 typedef struct stream_saver
{
2321 struct stream_saver
*next
;
2322 BASH_INPUT bash_input
;
2324 #if defined (BUFFERED_INPUT)
2325 BUFFERED_STREAM
*bstream
;
2326 #endif /* BUFFERED_INPUT */
2329 /* The globally known line number. */
2330 int line_number
= 0;
2332 #if defined (COND_COMMAND)
2333 static int cond_lineno
;
2334 static int cond_token
;
2337 STREAM_SAVER
*stream_list
= (STREAM_SAVER
*)NULL
;
2340 push_stream (reset_lineno
)
2343 STREAM_SAVER
*saver
= (STREAM_SAVER
*)xmalloc (sizeof (STREAM_SAVER
));
2345 xbcopy ((char *)&bash_input
, (char *)&(saver
->bash_input
), sizeof (BASH_INPUT
));
2347 #if defined (BUFFERED_INPUT)
2348 saver
->bstream
= (BUFFERED_STREAM
*)NULL
;
2349 /* If we have a buffered stream, clear out buffers[fd]. */
2350 if (bash_input
.type
== st_bstream
&& bash_input
.location
.buffered_fd
>= 0)
2351 saver
->bstream
= set_buffered_stream (bash_input
.location
.buffered_fd
,
2352 (BUFFERED_STREAM
*)NULL
);
2353 #endif /* BUFFERED_INPUT */
2355 saver
->line
= line_number
;
2356 bash_input
.name
= (char *)NULL
;
2357 saver
->next
= stream_list
;
2358 stream_list
= saver
;
2371 STREAM_SAVER
*saver
= stream_list
;
2374 stream_list
= stream_list
->next
;
2376 init_yy_io (saver
->bash_input
.getter
,
2377 saver
->bash_input
.ungetter
,
2378 saver
->bash_input
.type
,
2379 saver
->bash_input
.name
,
2380 saver
->bash_input
.location
);
2382 #if defined (BUFFERED_INPUT)
2383 /* If we have a buffered stream, restore buffers[fd]. */
2384 /* If the input file descriptor was changed while this was on the
2385 save stack, update the buffered fd to the new file descriptor and
2386 re-establish the buffer <-> bash_input fd correspondence. */
2387 if (bash_input
.type
== st_bstream
&& bash_input
.location
.buffered_fd
>= 0)
2389 if (bash_input_fd_changed
)
2391 bash_input_fd_changed
= 0;
2392 if (default_buffered_input
>= 0)
2394 bash_input
.location
.buffered_fd
= default_buffered_input
;
2395 saver
->bstream
->b_fd
= default_buffered_input
;
2398 set_buffered_stream (bash_input
.location
.buffered_fd
, saver
->bstream
);
2400 #endif /* BUFFERED_INPUT */
2402 line_number
= saver
->line
;
2404 FREE (saver
->bash_input
.name
);
2409 /* Return 1 if a stream of type TYPE is saved on the stack. */
2411 stream_on_stack (type
)
2412 enum stream_type type
;
2414 register STREAM_SAVER
*s
;
2416 for (s
= stream_list
; s
; s
= s
->next
)
2417 if (s
->bash_input
.type
== type
)
2423 * This is used to inhibit alias expansion and reserved word recognition
2424 * inside case statement pattern lists. A `case statement pattern list' is:
2426 * everything between the `in' in a `case word in' and the next ')'
2428 * everything between a `;;' and the next `)' or `esac'
2431 #if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
2433 #if !defined (ALIAS)
2434 typedef void *alias_t
;
2437 #define END_OF_ALIAS 0
2440 * Pseudo-global variables used in implementing token-wise alias expansion.
2444 * Pushing and popping strings. This works together with shell_getc to
2445 * implement alias expansion on a per-token basis.
2448 typedef struct string_saver
{
2449 struct string_saver
*next
;
2450 int expand_alias
; /* Value to set expand_alias to when string is popped. */
2453 alias_t
*expander
; /* alias that caused this line to be pushed. */
2455 int saved_line_size
, saved_line_index
, saved_line_terminator
;
2458 STRING_SAVER
*pushed_string_list
= (STRING_SAVER
*)NULL
;
2461 * Push the current shell_input_line onto a stack of such lines and make S
2462 * the current input. Used when expanding aliases. EXPAND is used to set
2463 * the value of expand_next_token when the string is popped, so that the
2464 * word after the alias in the original line is handled correctly when the
2465 * alias expands to multiple words. TOKEN is the token that was expanded
2466 * into S; it is saved and used to prevent infinite recursive expansion.
2469 push_string (s
, expand
, ap
)
2474 STRING_SAVER
*temp
= (STRING_SAVER
*) xmalloc (sizeof (STRING_SAVER
));
2476 temp
->expand_alias
= expand
;
2477 temp
->saved_line
= shell_input_line
;
2478 temp
->saved_line_size
= shell_input_line_size
;
2479 temp
->saved_line_index
= shell_input_line_index
;
2480 temp
->saved_line_terminator
= shell_input_line_terminator
;
2482 temp
->expander
= ap
;
2484 temp
->next
= pushed_string_list
;
2485 pushed_string_list
= temp
;
2489 ap
->flags
|= AL_BEINGEXPANDED
;
2492 shell_input_line
= s
;
2493 shell_input_line_size
= strlen (s
);
2494 shell_input_line_index
= 0;
2495 shell_input_line_terminator
= '\0';
2496 parser_state
&= ~PST_ALEXPNEXT
;
2500 * Make the top of the pushed_string stack be the current shell input.
2501 * Only called when there is something on the stack. Called from shell_getc
2502 * when it thinks it has consumed the string generated by an alias expansion
2503 * and needs to return to the original input line.
2510 FREE (shell_input_line
);
2511 shell_input_line
= pushed_string_list
->saved_line
;
2512 shell_input_line_index
= pushed_string_list
->saved_line_index
;
2513 shell_input_line_size
= pushed_string_list
->saved_line_size
;
2514 shell_input_line_terminator
= pushed_string_list
->saved_line_terminator
;
2516 if (pushed_string_list
->expand_alias
)
2517 parser_state
|= PST_ALEXPNEXT
;
2519 parser_state
&= ~PST_ALEXPNEXT
;
2521 t
= pushed_string_list
;
2522 pushed_string_list
= pushed_string_list
->next
;
2526 t
->expander
->flags
&= ~AL_BEINGEXPANDED
;
2535 register STRING_SAVER
*t
, *t1
;
2537 for (t
= pushed_string_list
; t
; )
2540 FREE (t
->saved_line
);
2543 t
->expander
->flags
&= ~AL_BEINGEXPANDED
;
2548 pushed_string_list
= (STRING_SAVER
*)NULL
;
2551 #endif /* ALIAS || DPAREN_ARITHMETIC */
2553 /* Return a line of text, taken from wherever yylex () reads input.
2554 If there is no more input, then we return NULL. If REMOVE_QUOTED_NEWLINE
2555 is non-zero, we remove unquoted \<newline> pairs. This is used by
2556 read_secondary_line to read here documents. */
2558 read_a_line (remove_quoted_newline
)
2559 int remove_quoted_newline
;
2561 static char *line_buffer
= (char *)NULL
;
2562 static int buffer_size
= 0;
2563 int indx
= 0, c
, peekc
, pass_next
;
2565 #if defined (READLINE)
2566 if (interactive
&& bash_input
.type
!= st_string
&& no_line_editing
)
2568 if (interactive
&& bash_input
.type
!= st_string
)
2577 /* Allow immediate exit if interrupted during input. */
2583 /* If there is no more input, then we return NULL. */
2586 if (interactive
&& bash_input
.type
== st_stream
)
2589 return ((char *)NULL
);
2593 /* `+2' in case the final character in the buffer is a newline. */
2594 RESIZE_MALLOCED_BUFFER (line_buffer
, indx
, 2, buffer_size
, 128);
2596 /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
2597 here document with an unquoted delimiter. In this case,
2598 the line will be expanded as if it were in double quotes.
2599 We allow a backslash to escape the next character, but we
2600 need to treat the backslash specially only if a backslash
2601 quoting a backslash-newline pair appears in the line. */
2604 line_buffer
[indx
++] = c
;
2607 else if (c
== '\\' && remove_quoted_newline
)
2611 continue; /* Make the unquoted \<newline> pair disappear. */
2616 line_buffer
[indx
++] = c
; /* Preserve the backslash. */
2620 line_buffer
[indx
++] = c
;
2624 line_buffer
[indx
] = '\0';
2625 return (line_buffer
);
2630 /* Return a line as in read_a_line (), but insure that the prompt is
2631 the secondary prompt. This is used to read the lines of a here
2632 document. REMOVE_QUOTED_NEWLINE is non-zero if we should remove
2633 newlines quoted with backslashes while reading the line. It is
2634 non-zero unless the delimiter of the here document was quoted. */
2636 read_secondary_line (remove_quoted_newline
)
2637 int remove_quoted_newline
;
2639 prompt_string_pointer
= &ps2_prompt
;
2641 return (read_a_line (remove_quoted_newline
));
2644 /* **************************************************************** */
2648 /* **************************************************************** */
2650 /* Reserved words. These are only recognized as the first word of a
2652 STRING_INT_ALIST word_token_alist
[] = {
2661 #if defined (SELECT_COMMAND)
2662 { "select", SELECT
},
2669 { "function", FUNCTION
},
2670 #if defined (COMMAND_TIMING)
2676 #if defined (COND_COMMAND)
2677 { "[[", COND_START
},
2683 /* These are used by read_token_word, but appear up here so that shell_getc
2684 can use them to decide when to add otherwise blank lines to the history. */
2686 /* The primary delimiter stack. */
2687 struct dstack dstack
= { (char *)NULL
, 0, 0 };
2689 /* A temporary delimiter stack to be used when decoding prompt strings.
2690 This is needed because command substitutions in prompt strings (e.g., PS2)
2691 can screw up the parser's quoting state. */
2692 static struct dstack temp_dstack
= { (char *)NULL
, 0, 0 };
2694 /* Macro for accessing the top delimiter on the stack. Returns the
2695 delimiter or zero if none. */
2696 #define current_delimiter(ds) \
2697 (ds.delimiter_depth ? ds.delimiters[ds.delimiter_depth - 1] : 0)
2699 #define push_delimiter(ds, character) \
2702 if (ds.delimiter_depth + 2 > ds.delimiter_space) \
2703 ds.delimiters = xrealloc \
2704 (ds.delimiters, (ds.delimiter_space += 10) * sizeof (char)); \
2705 ds.delimiters[ds.delimiter_depth] = character; \
2706 ds.delimiter_depth++; \
2710 #define pop_delimiter(ds) ds.delimiter_depth--
2712 /* Return the next shell input character. This always reads characters
2713 from shell_input_line; when that line is exhausted, it is time to
2714 read the next line. This is called by read_token when the shell is
2715 processing normal command input. */
2718 shell_getc (remove_quoted_newline
)
2719 int remove_quoted_newline
;
2723 static int mustpop
= 0;
2727 #if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
2728 /* If shell_input_line[shell_input_line_index] == 0, but there is
2729 something on the pushed list of strings, then we don't want to go
2730 off and get another line. We let the code down below handle it. */
2732 if (!shell_input_line
|| ((!shell_input_line
[shell_input_line_index
]) &&
2733 (pushed_string_list
== (STRING_SAVER
*)NULL
)))
2734 #else /* !ALIAS && !DPAREN_ARITHMETIC */
2735 if (!shell_input_line
|| !shell_input_line
[shell_input_line_index
])
2736 #endif /* !ALIAS && !DPAREN_ARITHMETIC */
2742 /* Allow immediate exit if interrupted during input. */
2746 shell_input_line_terminator
= 0;
2748 #if defined (JOB_CONTROL)
2749 /* This can cause a problem when reading a command as the result
2750 of a trap, when the trap is called from flush_child. This call
2751 had better not cause jobs to disappear from the job table in
2752 that case, or we will have big trouble. */
2753 notify_and_cleanup ();
2754 #else /* !JOB_CONTROL */
2755 cleanup_dead_jobs ();
2756 #endif /* !JOB_CONTROL */
2758 #if defined (READLINE)
2759 if (interactive
&& bash_input
.type
!= st_string
&& no_line_editing
)
2761 if (interactive
&& bash_input
.type
!= st_string
)
2765 if (bash_input
.type
== st_stream
)
2768 while (c
= yy_getc ())
2770 /* Allow immediate exit if interrupted during input. */
2773 RESIZE_MALLOCED_BUFFER (shell_input_line
, i
, 2, shell_input_line_size
, 256);
2777 if (bash_input
.type
== st_stream
)
2781 shell_input_line_terminator
= EOF
;
2783 shell_input_line
[i
] = '\0';
2787 shell_input_line
[i
++] = c
;
2791 shell_input_line
[--i
] = '\0';
2792 current_command_line_count
++;
2796 shell_input_line_index
= 0;
2797 shell_input_line_len
= i
; /* == strlen (shell_input_line) */
2799 #if defined (HISTORY)
2800 if (remember_on_history
&& shell_input_line
&& shell_input_line
[0])
2803 # if defined (BANG_HISTORY)
2806 /* If the current delimiter is a single quote, we should not be
2807 performing history expansion, even if we're on a different
2808 line from the original single quote. */
2809 old_hist
= history_expansion_inhibited
;
2810 if (current_delimiter (dstack
) == '\'')
2811 history_expansion_inhibited
= 1;
2813 expansions
= pre_process_line (shell_input_line
, 1, 1);
2814 # if defined (BANG_HISTORY)
2815 history_expansion_inhibited
= old_hist
;
2817 if (expansions
!= shell_input_line
)
2819 free (shell_input_line
);
2820 shell_input_line
= expansions
;
2821 shell_input_line_len
= shell_input_line
?
2822 strlen (shell_input_line
) : 0;
2823 if (!shell_input_line_len
)
2824 current_command_line_count
--;
2826 /* We have to force the xrealloc below because we don't know
2827 the true allocated size of shell_input_line anymore. */
2828 shell_input_line_size
= shell_input_line_len
;
2831 /* XXX - this is grotesque */
2832 else if (remember_on_history
&& shell_input_line
&&
2833 shell_input_line
[0] == '\0' &&
2834 current_command_line_count
> 1 && current_delimiter (dstack
))
2836 /* We know shell_input_line[0] == 0 and we're reading some sort of
2837 quoted string. This means we've got a line consisting of only
2838 a newline in a quoted string. We want to make sure this line
2839 gets added to the history. */
2840 maybe_add_history (shell_input_line
);
2843 #endif /* HISTORY */
2845 if (shell_input_line
)
2847 /* Lines that signify the end of the shell's input should not be
2849 if (echo_input_at_read
&& (shell_input_line
[0] ||
2850 shell_input_line_terminator
!= EOF
))
2851 fprintf (stderr
, "%s\n", shell_input_line
);
2855 shell_input_line_size
= 0;
2856 prompt_string_pointer
= ¤t_prompt_string
;
2861 /* Add the newline to the end of this string, iff the string does
2862 not already end in an EOF character. */
2863 if (shell_input_line_terminator
!= EOF
)
2865 if (shell_input_line_len
+ 3 > shell_input_line_size
)
2866 shell_input_line
= xrealloc (shell_input_line
,
2867 1 + (shell_input_line_size
+= 2));
2869 shell_input_line
[shell_input_line_len
] = '\n';
2870 shell_input_line
[shell_input_line_len
+ 1] = '\0';
2874 c
= shell_input_line
[shell_input_line_index
];
2877 shell_input_line_index
++;
2879 if (c
== '\\' && remove_quoted_newline
&&
2880 shell_input_line
[shell_input_line_index
] == '\n')
2887 #if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
2888 /* If C is NULL, we have reached the end of the current input string. If
2889 pushed_string_list is non-empty, it's time to pop to the previous string
2890 because we have fully consumed the result of the last alias expansion.
2891 Do it transparently; just return the next character of the string popped
2893 if (!c
&& (pushed_string_list
!= (STRING_SAVER
*)NULL
))
2898 c
= shell_input_line
[shell_input_line_index
];
2900 shell_input_line_index
++;
2909 #endif /* ALIAS || DPAREN_ARITHMETIC */
2911 if (!c
&& shell_input_line_terminator
== EOF
)
2912 return ((shell_input_line_index
!= 0) ? '\n' : EOF
);
2914 return ((unsigned char)c
);
2917 /* Put C back into the input for the shell. */
2922 if (shell_input_line
&& shell_input_line_index
)
2923 shell_input_line
[--shell_input_line_index
] = c
;
2929 if (shell_input_line
&& shell_input_line_index
)
2930 shell_input_line_index
--;
2933 /* Discard input until CHARACTER is seen, then push that character back
2934 onto the input stream. */
2936 discard_until (character
)
2941 while ((c
= shell_getc (0)) != EOF
&& c
!= character
)
2949 execute_prompt_command (command
)
2952 Function
*temp_last
, *temp_this
;
2954 int temp_exit_value
, temp_eof_encountered
;
2956 temp_last
= last_shell_builtin
;
2957 temp_this
= this_shell_builtin
;
2958 temp_exit_value
= last_command_exit_value
;
2959 temp_eof_encountered
= eof_encountered
;
2960 last_lastarg
= get_string_value ("_");
2962 last_lastarg
= savestring (last_lastarg
);
2964 parse_and_execute (savestring (command
), "PROMPT_COMMAND", SEVAL_NONINT
|SEVAL_NOHIST
);
2966 last_shell_builtin
= temp_last
;
2967 this_shell_builtin
= temp_this
;
2968 last_command_exit_value
= temp_exit_value
;
2969 eof_encountered
= temp_eof_encountered
;
2971 bind_variable ("_", last_lastarg
);
2972 FREE (last_lastarg
);
2974 if (token_to_read
== '\n') /* reset_parser was called */
2978 /* Place to remember the token. We try to keep the buffer
2979 at a reasonable size, but it can grow. */
2980 static char *token
= (char *)NULL
;
2982 /* Current size of the token buffer. */
2983 static int token_buffer_size
;
2985 /* Command to read_token () explaining what we want it to do. */
2988 #define prompt_is_ps1 \
2989 (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
2991 /* Function for yyparse to call. yylex keeps track of
2992 the last two tokens read, and calls read_token. */
2996 if (interactive
&& (current_token
== 0 || current_token
== '\n'))
2998 /* Before we print a prompt, we might have to check mailboxes.
2999 We do this only if it is time to do so. Notice that only here
3000 is the mail alarm reset; nothing takes place in check_mail ()
3001 except the checking of mail. Please don't change this. */
3002 if (prompt_is_ps1
&& time_to_check_mail ())
3005 reset_mail_timer ();
3008 /* Avoid printing a prompt if we're not going to read anything, e.g.
3009 after resetting the parser with read_token (RESET). */
3010 if (token_to_read
== 0 && interactive
)
3014 two_tokens_ago
= token_before_that
;
3015 token_before_that
= last_read_token
;
3016 last_read_token
= current_token
;
3017 current_token
= read_token (READ
);
3018 return (current_token
);
3021 /* When non-zero, we have read the required tokens
3022 which allow ESAC to be the next one read. */
3023 static int esacs_needed_count
;
3026 gather_here_documents ()
3029 while (need_here_doc
)
3031 make_here_document (redir_stack
[r
++]);
3036 /* When non-zero, an open-brace used to create a group is awaiting a close
3038 static int open_brace_count
;
3040 #define command_token_position(token) \
3041 (((token) == ASSIGNMENT_WORD) || \
3042 ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
3044 #define assignment_acceptable(token) command_token_position(token) && \
3045 ((parser_state & PST_CASEPAT) == 0)
3047 /* Check to see if TOKEN is a reserved word and return the token
3049 #define CHECK_FOR_RESERVED_WORD(tok) \
3051 if (!dollar_present && !quoted && \
3052 reserved_word_acceptable (last_read_token)) \
3055 for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
3056 if (STREQ (tok, word_token_alist[i].word)) \
3058 if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \
3060 if (word_token_alist[i].token == TIME) \
3062 if (word_token_alist[i].token == ESAC) \
3063 parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
3064 else if (word_token_alist[i].token == CASE) \
3065 parser_state |= PST_CASESTMT; \
3066 else if (word_token_alist[i].token == COND_END) \
3067 parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
3068 else if (word_token_alist[i].token == COND_START) \
3069 parser_state |= PST_CONDCMD; \
3070 else if (word_token_alist[i].token == '{') \
3071 open_brace_count++; \
3072 else if (word_token_alist[i].token == '}' && open_brace_count) \
3073 open_brace_count--; \
3074 return (word_token_alist[i].token); \
3081 /* OK, we have a token. Let's try to alias expand it, if (and only if)
3084 It is eligible for expansion if the shell is in interactive mode, and
3085 the token is unquoted and the last token read was a command
3086 separator (or expand_next_token is set), and we are currently
3087 processing an alias (pushed_string_list is non-empty) and this
3088 token is not the same as the current or any previously
3091 Special cases that disqualify:
3092 In a pattern list in a case statement (parser_state & PST_CASEPAT). */
3094 alias_expand_token (token
)
3100 if (((parser_state
& PST_ALEXPNEXT
) || command_token_position (last_read_token
)) &&
3101 (parser_state
& PST_CASEPAT
) == 0)
3103 ap
= find_alias (token
);
3105 /* Currently expanding this token. */
3106 if (ap
&& (ap
->flags
& AL_BEINGEXPANDED
))
3107 return (NO_EXPANSION
);
3109 expanded
= ap
? savestring (ap
->value
) : (char *)NULL
;
3112 push_string (expanded
, ap
->flags
& AL_EXPANDNEXT
, ap
);
3113 return (RE_READ_TOKEN
);
3116 /* This is an eligible token that does not have an expansion. */
3117 return (NO_EXPANSION
);
3119 return (NO_EXPANSION
);
3124 time_command_acceptable ()
3126 #if defined (COMMAND_TIMING)
3127 switch (last_read_token
)
3141 #endif /* COMMAND_TIMING */
3144 /* Handle special cases of token recognition:
3145 IN is recognized if the last token was WORD and the token
3146 before that was FOR or CASE or SELECT.
3148 DO is recognized if the last token was WORD and the token
3149 before that was FOR or SELECT.
3151 ESAC is recognized if the last token caused `esacs_needed_count'
3154 `{' is recognized if the last token as WORD and the token
3155 before that was FUNCTION.
3157 `}' is recognized if there is an unclosed `{' prsent.
3159 `-p' is returned as TIMEOPT if the last read token was TIME.
3161 ']]' is returned as COND_END if the parser is currently parsing
3162 a conditional expression ((parser_state & PST_CONDEXPR) != 0)
3164 `time' is returned as TIME if and only if it is immediately
3165 preceded by one of `;', `\n', `||', `&&', or `&'.
3169 special_case_tokens (token
)
3172 if ((last_read_token
== WORD
) &&
3173 #if defined (SELECT_COMMAND)
3174 ((token_before_that
== FOR
) || (token_before_that
== CASE
) || (token_before_that
== SELECT
)) &&
3176 ((token_before_that
== FOR
) || (token_before_that
== CASE
)) &&
3178 (token
[0] == 'i' && token
[1] == 'n' && token
[2] == 0))
3180 if (token_before_that
== CASE
)
3182 parser_state
|= PST_CASEPAT
;
3183 esacs_needed_count
++;
3188 if (last_read_token
== WORD
&&
3189 #if defined (SELECT_COMMAND)
3190 (token_before_that
== FOR
|| token_before_that
== SELECT
) &&
3192 (token_before_that
== FOR
) &&
3194 (token
[0] == 'd' && token
[1] == 'o' && token
[2] == '\0'))
3197 /* Ditto for ESAC in the CASE case.
3198 Specifically, this handles "case word in esac", which is a legal
3199 construct, certainly because someone will pass an empty arg to the
3200 case construct, and we don't want it to barf. Of course, we should
3201 insist that the case construct has at least one pattern in it, but
3202 the designers disagree. */
3203 if (esacs_needed_count
)
3205 esacs_needed_count
--;
3206 if (STREQ (token
, "esac"))
3208 parser_state
&= ~PST_CASEPAT
;
3213 /* The start of a shell function definition. */
3214 if (parser_state
& PST_ALLOWOPNBRC
)
3216 parser_state
&= ~PST_ALLOWOPNBRC
;
3217 if (token
[0] == '{' && token
[1] == '\0') /* } */
3220 function_bstart
= line_number
;
3221 return ('{'); /* } */
3225 if (open_brace_count
&& reserved_word_acceptable (last_read_token
) && token
[0] == '}' && !token
[1])
3227 open_brace_count
--; /* { */
3231 #if defined (COMMAND_TIMING)
3232 /* Handle -p after `time'. */
3233 if (last_read_token
== TIME
&& token
[0] == '-' && token
[1] == 'p' && !token
[2])
3237 #if defined (COMMAND_TIMING)
3238 if (STREQ (token
, "time") && time_command_acceptable ())
3240 #endif /* COMMAND_TIMING */
3242 #if defined (COND_COMMAND) /* [[ */
3243 if ((parser_state
& PST_CONDEXPR
) && token
[0] == ']' && token
[1] == ']' && token
[2] == '\0')
3250 /* Called from shell.c when Control-C is typed at top level. Or
3251 by the error rule at top level. */
3255 dstack
.delimiter_depth
= 0; /* No delimiters found so far. */
3256 open_brace_count
= 0;
3260 #if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
3261 if (pushed_string_list
)
3262 free_string_list ();
3263 #endif /* ALIAS || DPAREN_ARITHMETIC */
3265 if (shell_input_line
)
3267 free (shell_input_line
);
3268 shell_input_line
= (char *)NULL
;
3269 shell_input_line_size
= shell_input_line_index
= 0;
3272 FREE (word_desc_to_read
);
3273 word_desc_to_read
= (WORD_DESC
*)NULL
;
3275 last_read_token
= '\n';
3276 token_to_read
= '\n';
3279 /* Read the next token. Command can be READ (normal operation) or
3280 RESET (to normalize state). */
3282 read_token (command
)
3285 int character
; /* Current character. */
3286 int peek_char
; /* Temporary look-ahead character. */
3287 int result
; /* The thing to return. */
3289 if (command
== RESET
)
3297 result
= token_to_read
;
3298 if (token_to_read
== WORD
|| token_to_read
== ASSIGNMENT_WORD
)
3300 yylval
.word
= word_desc_to_read
;
3301 word_desc_to_read
= (WORD_DESC
*)NULL
;
3307 #if defined (COND_COMMAND)
3308 if ((parser_state
& (PST_CONDCMD
|PST_CONDEXPR
)) == PST_CONDCMD
)
3310 cond_lineno
= line_number
;
3311 parser_state
|= PST_CONDEXPR
;
3312 yylval
.command
= parse_cond_command ();
3313 if (cond_token
!= COND_END
)
3315 if (EOF_Reached
&& cond_token
!= COND_ERROR
) /* [[ */
3316 parser_error (cond_lineno
, "unexpected EOF while looking for `]]'");
3317 else if (cond_token
!= COND_ERROR
)
3318 parser_error (cond_lineno
, "syntax error in conditional expression");
3321 token_to_read
= COND_END
;
3322 parser_state
&= ~(PST_CONDEXPR
|PST_CONDCMD
);
3328 /* This is a place to jump back to once we have successfully expanded a
3329 token with an alias and pushed the string with push_string () */
3333 /* Read a single word from input. Start by skipping blanks. */
3334 while ((character
= shell_getc (1)) != EOF
&& whitespace (character
))
3337 if (character
== EOF
)
3343 if (character
== '#' && (!interactive
|| interactive_comments
))
3345 /* A comment. Discard until EOL or EOF, and then return a newline. */
3346 discard_until ('\n');
3348 character
= '\n'; /* this will take the next if statement and return. */
3351 if (character
== '\n')
3353 /* If we're about to return an unquoted newline, we can go and collect
3354 the text of any pending here document. */
3356 gather_here_documents ();
3359 parser_state
&= ~PST_ALEXPNEXT
;
3365 /* Shell meta-characters. */
3366 if (shellmeta (character
) && ((parser_state
& PST_DBLPAREN
) == 0))
3369 /* Turn off alias tokenization iff this character sequence would
3370 not leave us ready to read a command. */
3371 if (character
== '<' || character
== '>')
3372 parser_state
&= ~PST_ALEXPNEXT
;
3375 peek_char
= shell_getc (1);
3376 if (character
== peek_char
)
3381 /* If '<' then we could be at "<<" or at "<<-". We have to
3382 look ahead one more character. */
3383 peek_char
= shell_getc (1);
3384 if (peek_char
== '-')
3385 return (LESS_LESS_MINUS
);
3388 shell_ungetc (peek_char
);
3393 return (GREATER_GREATER
);
3396 parser_state
|= PST_CASEPAT
;
3398 parser_state
&= ~PST_ALEXPNEXT
;
3408 #if defined (DPAREN_ARITHMETIC)
3410 if (reserved_word_acceptable (last_read_token
))
3416 sline
= line_number
;
3417 cmdtyp
= parse_arith_cmd (&wval
);
3418 if (cmdtyp
== 1) /* arithmetic command */
3420 wd
= make_word (wval
);
3421 wd
->flags
= W_QUOTED
;
3422 yylval
.word_list
= make_word_list (wd
, (WORD_LIST
*)NULL
);
3423 free (wval
); /* make_word copies it */
3426 else if (cmdtyp
== 0) /* nested subshell */
3428 push_string (wval
, 0, (alias_t
*)NULL
);
3429 if ((parser_state
& PST_CASEPAT
) == 0)
3430 parser_state
|= PST_SUBSHELL
;
3440 else if (character
== '<' && peek_char
== '&')
3442 else if (character
== '>' && peek_char
== '&')
3443 return (GREATER_AND
);
3444 else if (character
== '<' && peek_char
== '>')
3445 return (LESS_GREATER
);
3446 else if (character
== '>' && peek_char
== '|')
3447 return (GREATER_BAR
);
3448 else if (peek_char
== '>' && character
== '&')
3449 return (AND_GREATER
);
3451 shell_ungetc (peek_char
);
3453 /* If we look like we are reading the start of a function
3454 definition, then let the reader know about it so that
3455 we will do the right thing with `{'. */
3456 if (character
== ')' && last_read_token
== '(' && token_before_that
== WORD
)
3458 parser_state
|= PST_ALLOWOPNBRC
;
3460 parser_state
&= ~PST_ALEXPNEXT
;
3462 function_dstart
= line_number
;
3465 /* case pattern lists may be preceded by an optional left paren. If
3466 we're not trying to parse a case pattern list, the left paren
3467 indicates a subshell. */
3468 if (character
== '(' && (parser_state
& PST_CASEPAT
) == 0) /* ) */
3469 parser_state
|= PST_SUBSHELL
;
3471 else if ((parser_state
& PST_CASEPAT
) && character
== ')')
3472 parser_state
&= ~PST_CASEPAT
;
3474 else if ((parser_state
& PST_SUBSHELL
) && character
== ')')
3475 parser_state
&= ~PST_SUBSHELL
;
3477 #if defined (PROCESS_SUBSTITUTION)
3478 /* Check for the constructs which introduce process substitution.
3479 Shells running in `posix mode' don't do process substitution. */
3480 if (posixly_correct
||
3481 ((character
!= '>' && character
!= '<') || peek_char
!= '('))
3482 #endif /* PROCESS_SUBSTITUTION */
3486 /* Hack <&- (close stdin) case. */
3487 if (character
== '-' && (last_read_token
== LESS_AND
|| last_read_token
== GREATER_AND
))
3490 /* Okay, if we got this far, we have to read a word. Read one,
3491 and then check it against the known ones. */
3492 result
= read_token_word (character
);
3494 if (result
== RE_READ_TOKEN
)
3500 /* Match a $(...) or other grouping construct. This has to handle embedded
3501 quoted strings ('', ``, "") and nested constructs. It also must handle
3502 reprompting the user, if necessary, after reading a newline, and returning
3503 correct error values if it reads EOF. */
3504 static char matched_pair_error
;
3506 parse_matched_pair (qc
, open
, close
, lenp
, flags
)
3507 int qc
; /* `"' if this construct is within double quotes */
3511 int count
, ch
, was_dollar
;
3512 int pass_next_character
, nestlen
, start_lineno
;
3513 char *ret
, *nestret
;
3514 int retind
, retsize
;
3517 pass_next_character
= was_dollar
= 0;
3519 ret
= xmalloc (retsize
= 64);
3522 start_lineno
= line_number
;
3525 ch
= shell_getc (qc
!= '\'' && pass_next_character
== 0);
3529 parser_error (start_lineno
, "unexpected EOF while looking for matching `%c'", close
);
3530 EOF_Reached
= 1; /* XXX */
3531 return (&matched_pair_error
);
3534 /* Possible reprompting. */
3535 if (ch
== '\n' && interactive
&&
3536 (bash_input
.type
== st_stdin
|| bash_input
.type
== st_stream
))
3539 if (pass_next_character
) /* last char was backslash */
3541 pass_next_character
= 0;
3542 if (qc
!= '\'' && ch
== '\n') /* double-quoted \<newline> disappears. */
3544 if (retind
> 0) retind
--; /* swallow previously-added backslash */
3548 RESIZE_MALLOCED_BUFFER (ret
, retind
, 2, retsize
, 64);
3549 if (ch
== CTLESC
|| ch
== CTLNUL
)
3550 ret
[retind
++] = CTLESC
;
3554 else if (ch
== CTLESC
|| ch
== CTLNUL
) /* special shell escapes */
3556 RESIZE_MALLOCED_BUFFER (ret
, retind
, 2, retsize
, 64);
3557 ret
[retind
++] = CTLESC
;
3561 else if (ch
== close
) /* ending delimiter */
3563 else if (ch
== open
) /* nested begin */
3566 /* Add this character. */
3567 RESIZE_MALLOCED_BUFFER (ret
, retind
, 1, retsize
, 64);
3570 if (open
== '\'') /* '' inside grouping construct */
3573 if (ch
== '\\') /* backslashes */
3574 pass_next_character
++;
3576 if (open
!= close
) /* a grouping construct */
3578 if (shellquote (ch
))
3580 /* '', ``, or "" inside $(...) or other grouping construct. */
3581 push_delimiter (dstack
, ch
);
3582 nestret
= parse_matched_pair (ch
, ch
, ch
, &nestlen
, 0);
3583 pop_delimiter (dstack
);
3584 if (nestret
== &matched_pair_error
)
3587 return &matched_pair_error
;
3591 RESIZE_MALLOCED_BUFFER (ret
, retind
, nestlen
, retsize
, 64);
3592 strcpy (ret
+ retind
, nestret
);
3598 /* Parse an old-style command substitution within double quotes as a
3600 /* XXX - sh and ksh93 don't do this - XXX */
3601 else if (open
== '"' && ch
== '`')
3603 nestret
= parse_matched_pair (0, '`', '`', &nestlen
, 0);
3604 if (nestret
== &matched_pair_error
)
3607 return &matched_pair_error
;
3611 RESIZE_MALLOCED_BUFFER (ret
, retind
, nestlen
, retsize
, 64);
3612 strcpy (ret
+ retind
, nestret
);
3617 else if (was_dollar
&& (ch
== '(' || ch
== '{' || ch
== '[')) /* ) } ] */
3618 /* check for $(), $[], or ${} inside quoted string. */
3620 if (open
== ch
) /* undo previous increment */
3622 if (ch
== '(') /* ) */
3623 nestret
= parse_matched_pair (0, '(', ')', &nestlen
, 0);
3624 else if (ch
== '{') /* } */
3625 nestret
= parse_matched_pair (0, '{', '}', &nestlen
, 0);
3626 else if (ch
== '[') /* ] */
3627 nestret
= parse_matched_pair (0, '[', ']', &nestlen
, 0);
3628 if (nestret
== &matched_pair_error
)
3631 return &matched_pair_error
;
3635 RESIZE_MALLOCED_BUFFER (ret
, retind
, nestlen
, retsize
, 64);
3636 strcpy (ret
+ retind
, nestret
);
3641 was_dollar
= (ch
== '$');
3650 #if defined (DPAREN_ARITHMETIC)
3651 /* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
3652 If not, assume it's a nested subshell for backwards compatibility and
3653 return 0. In any case, put the characters we've consumed into a locally-
3654 allocated buffer and make *ep point to that buffer. Return -1 on an
3655 error, for example EOF. */
3657 parse_arith_cmd (ep
)
3660 int exp_lineno
, rval
, c
;
3664 exp_lineno
= line_number
;
3665 ttok
= parse_matched_pair (0, '(', ')', &ttoklen
, 0);
3667 if (ttok
== &matched_pair_error
)
3669 /* Check that the next character is the closing right paren. If
3670 not, this is a syntax error. ( */
3671 if ((c
= shell_getc (0)) != ')')
3674 token
= xmalloc(ttoklen
+ 4);
3676 /* (( ... )) -> "..." */
3677 token
[0] = (rval
== 1) ? '"' : '(';
3678 strncpy (token
+ 1, ttok
, ttoklen
- 1); /* don't copy the final `)' */
3681 token
[ttoklen
] = '"';
3682 token
[ttoklen
+1] = '\0';
3686 token
[ttoklen
] = ')';
3687 token
[ttoklen
+1] = c
;
3688 token
[ttoklen
+2] = '\0';
3694 #endif /* DPAREN_ARITHMETIC */
3696 #if defined (COND_COMMAND)
3697 static COND_COM
*cond_term ();
3698 static COND_COM
*cond_and ();
3699 static COND_COM
*cond_or ();
3700 static COND_COM
*cond_expr ();
3705 return (cond_or ());
3714 if (cond_token
== OR_OR
)
3717 l
= make_cond_node (COND_OR
, (WORD_DESC
*)NULL
, l
, r
);
3728 if (cond_token
== AND_AND
)
3731 l
= make_cond_node (COND_AND
, (WORD_DESC
*)NULL
, l
, r
);
3737 cond_skip_newlines ()
3739 while ((cond_token
= read_token (READ
)) == '\n')
3741 if (interactive
&& (bash_input
.type
== st_stdin
|| bash_input
.type
== st_stream
))
3744 return (cond_token
);
3747 #define COND_RETURN_ERROR() \
3748 do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
3754 COND_COM
*term
, *tleft
, *tright
;
3757 /* Read a token. It can be a left paren, a `!', a unary operator, or a
3758 word that should be the first argument of a binary operator. Start by
3759 skipping newlines, since this is a compound command. */
3760 tok
= cond_skip_newlines ();
3761 lineno
= line_number
;
3762 if (tok
== COND_END
)
3764 COND_RETURN_ERROR ();
3766 else if (tok
== '(')
3768 term
= cond_expr ();
3769 if (cond_token
!= ')')
3772 dispose_cond_node (term
); /* ( */
3773 parser_error (lineno
, "expected `)'");
3774 COND_RETURN_ERROR ();
3776 term
= make_cond_node (COND_EXPR
, (WORD_DESC
*)NULL
, term
, (COND_COM
*)NULL
);
3777 (void)cond_skip_newlines ();
3779 else if (tok
== BANG
|| (tok
== WORD
&& (yylval
.word
->word
[0] == '!' && yylval
.word
->word
[1] == '\0')))
3782 dispose_word (yylval
.word
); /* not needed */
3783 term
= cond_term ();
3785 term
->flags
|= CMD_INVERT_RETURN
;
3787 else if (tok
== WORD
&& test_unop (yylval
.word
->word
))
3790 tok
= read_token (READ
);
3793 tleft
= make_cond_node (COND_TERM
, yylval
.word
, (COND_COM
*)NULL
, (COND_COM
*)NULL
);
3794 term
= make_cond_node (COND_UNARY
, op
, tleft
, (COND_COM
*)NULL
);
3799 parser_error (line_number
, "unexpected argument to conditional unary operator");
3800 COND_RETURN_ERROR ();
3803 (void)cond_skip_newlines ();
3805 else /* left argument to binary operator */
3808 tleft
= make_cond_node (COND_TERM
, yylval
.word
, (COND_COM
*)NULL
, (COND_COM
*)NULL
);
3811 tok
= read_token (READ
);
3812 if (tok
== WORD
&& test_binop (yylval
.word
->word
))
3814 else if (tok
== '<' || tok
== '>')
3815 op
= make_word_from_token (tok
);
3816 else if (tok
== COND_END
|| tok
== AND_AND
|| tok
== OR_OR
)
3818 /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
3819 the test command. Similarly for [[ x && expr ]] or
3821 op
= make_word ("-n");
3822 term
= make_cond_node (COND_UNARY
, op
, tleft
, (COND_COM
*)NULL
);
3828 parser_error (line_number
, "conditional binary operator expected");
3829 dispose_cond_node (tleft
);
3830 COND_RETURN_ERROR ();
3834 tok
= read_token (READ
);
3837 tright
= make_cond_node (COND_TERM
, yylval
.word
, (COND_COM
*)NULL
, (COND_COM
*)NULL
);
3838 term
= make_cond_node (COND_BINARY
, op
, tleft
, tright
);
3842 parser_error (line_number
, "unexpected argument to conditional binary operator");
3843 dispose_cond_node (tleft
);
3845 COND_RETURN_ERROR ();
3848 (void)cond_skip_newlines ();
3853 /* This is kind of bogus -- we slip a mini recursive-descent parser in
3854 here to handle the conditional statement syntax. */
3856 parse_cond_command ()
3860 cexp
= cond_expr ();
3861 return (make_cond_command (cexp
));
3866 read_token_word (character
)
3869 /* The value for YYLVAL when a WORD is read. */
3870 WORD_DESC
*the_word
;
3872 /* Index into the token that we are building. */
3875 /* ALL_DIGITS becomes zero when we see a non-digit. */
3878 /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
3881 /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
3884 /* Non-zero means to ignore the value of the next character, and just
3885 to add it no matter what. */
3886 int pass_next_character
;
3888 /* The current delimiting character. */
3890 int result
, peek_char
;
3891 char *ttok
, *ttrans
;
3892 int ttoklen
, ttranslen
;
3894 if (token_buffer_size
< TOKEN_DEFAULT_INITIAL_SIZE
)
3895 token
= xrealloc (token
, token_buffer_size
= TOKEN_DEFAULT_INITIAL_SIZE
);
3898 all_digits
= digit (character
);
3899 dollar_present
= quoted
= pass_next_character
= 0;
3903 if (character
== EOF
)
3906 if (pass_next_character
)
3908 pass_next_character
= 0;
3912 cd
= current_delimiter (dstack
);
3914 /* Handle backslashes. Quote lots of things when not inside of
3915 double-quotes, quote some things inside of double-quotes. */
3916 if (character
== '\\')
3918 peek_char
= shell_getc (0);
3920 /* Backslash-newline is ignored in all cases except
3921 when quoted with single quotes. */
3922 if (peek_char
== '\n')
3925 goto next_character
;
3929 shell_ungetc (peek_char
);
3931 /* If the next character is to be quoted, note it now. */
3932 if (cd
== 0 || cd
== '`' ||
3933 (cd
== '"' && member (peek_char
, slashify_in_quotes
)))
3934 pass_next_character
++;
3941 /* Parse a matched pair of quote characters. */
3942 if (shellquote (character
))
3944 push_delimiter (dstack
, character
);
3945 ttok
= parse_matched_pair (character
, character
, character
, &ttoklen
, 0);
3946 pop_delimiter (dstack
);
3947 if (ttok
== &matched_pair_error
)
3948 return -1; /* Bail immediately. */
3949 RESIZE_MALLOCED_BUFFER (token
, token_index
, ttoklen
+ 2,
3950 token_buffer_size
, TOKEN_DEFAULT_GROW_SIZE
);
3951 token
[token_index
++] = character
;
3952 strcpy (token
+ token_index
, ttok
);
3953 token_index
+= ttoklen
;
3956 dollar_present
|= (character
== '"' && strchr (ttok
, '$') != 0);
3958 goto next_character
;
3961 #ifdef EXTENDED_GLOB
3962 /* Parse a ksh-style extended pattern matching specification. */
3963 if (extended_glob
&& PATTERN_CHAR(character
))
3965 peek_char
= shell_getc (1);
3966 if (peek_char
== '(') /* ) */
3968 push_delimiter (dstack
, peek_char
);
3969 ttok
= parse_matched_pair (cd
, '(', ')', &ttoklen
, 0);
3970 pop_delimiter (dstack
);
3971 if (ttok
== &matched_pair_error
)
3972 return -1; /* Bail immediately. */
3973 RESIZE_MALLOCED_BUFFER (token
, token_index
, ttoklen
+ 2,
3975 TOKEN_DEFAULT_GROW_SIZE
);
3976 token
[token_index
++] = character
;
3977 token
[token_index
++] = peek_char
;
3978 strcpy (token
+ token_index
, ttok
);
3979 token_index
+= ttoklen
;
3981 dollar_present
= all_digits
= 0;
3982 goto next_character
;
3985 shell_ungetc (peek_char
);
3987 #endif /* EXTENDED_GLOB */
3989 /* If the delimiter character is not single quote, parse some of
3990 the shell expansions that must be read as a single word. */
3991 #if defined (PROCESS_SUBSTITUTION)
3992 if (character
== '$' || character
== '<' || character
== '>')
3994 if (character
== '$')
3995 #endif /* !PROCESS_SUBSTITUTION */
3997 peek_char
= shell_getc (1);
3998 /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
3999 if (peek_char
== '(' ||
4000 ((peek_char
== '{' || peek_char
== '[') && character
== '$')) /* ) ] } */
4002 if (peek_char
== '{') /* } */
4003 ttok
= parse_matched_pair (cd
, '{', '}', &ttoklen
, 0);
4004 else if (peek_char
== '(') /* ) */
4006 /* XXX - push and pop the `(' as a delimiter for use by
4007 the command-oriented-history code. This way newlines
4008 appearing in the $(...) string get added to the
4009 history literally rather than causing a possibly-
4010 incorrect `;' to be added. */
4011 push_delimiter (dstack
, peek_char
);
4012 ttok
= parse_matched_pair (cd
, '(', ')', &ttoklen
, 0);
4013 pop_delimiter (dstack
);
4016 ttok
= parse_matched_pair (cd
, '[', ']', &ttoklen
, 0);
4017 if (ttok
== &matched_pair_error
)
4018 return -1; /* Bail immediately. */
4019 RESIZE_MALLOCED_BUFFER (token
, token_index
, ttoklen
+ 2,
4021 TOKEN_DEFAULT_GROW_SIZE
);
4022 token
[token_index
++] = character
;
4023 token
[token_index
++] = peek_char
;
4024 strcpy (token
+ token_index
, ttok
);
4025 token_index
+= ttoklen
;
4029 goto next_character
;
4031 /* This handles $'...' and $"..." new-style quoted strings. */
4032 else if (character
== '$' && (peek_char
== '\'' || peek_char
== '"'))
4036 first_line
= line_number
;
4037 ttok
= parse_matched_pair (peek_char
, peek_char
, peek_char
, &ttoklen
, 0);
4038 if (ttok
== &matched_pair_error
)
4040 if (peek_char
== '\'')
4041 ttrans
= ansiexpand (ttok
, 0, ttoklen
- 1, &ttranslen
);
4043 ttrans
= localeexpand (ttok
, 0, ttoklen
- 1, first_line
, &ttranslen
);
4045 RESIZE_MALLOCED_BUFFER (token
, token_index
, ttranslen
+ 2,
4047 TOKEN_DEFAULT_GROW_SIZE
);
4048 token
[token_index
++] = peek_char
;
4049 strcpy (token
+ token_index
, ttrans
);
4050 token_index
+= ttranslen
;
4051 token
[token_index
++] = peek_char
;
4055 goto next_character
;
4058 shell_ungetc (peek_char
);
4061 #if defined (ARRAY_VARS)
4062 /* Identify possible compound array variable assignment. */
4063 else if (character
== '=' && token_index
> 0)
4065 peek_char
= shell_getc (1);
4066 if (peek_char
== '(') /* ) */
4068 ttok
= parse_matched_pair (cd
, '(', ')', &ttoklen
, 0);
4069 if (ttok
== &matched_pair_error
)
4070 return -1; /* Bail immediately. */
4071 RESIZE_MALLOCED_BUFFER (token
, token_index
, ttoklen
+ 2,
4073 TOKEN_DEFAULT_GROW_SIZE
);
4074 token
[token_index
++] = character
;
4075 token
[token_index
++] = peek_char
;
4076 strcpy (token
+ token_index
, ttok
);
4077 token_index
+= ttoklen
;
4080 goto next_character
;
4083 shell_ungetc (peek_char
);
4087 /* When not parsing a multi-character word construct, shell meta-
4088 characters break words. */
4089 if (shellbreak (character
))
4091 shell_ungetc (character
);
4097 all_digits
&= digit (character
);
4098 dollar_present
|= character
== '$';
4100 if (character
== CTLESC
|| character
== CTLNUL
)
4101 token
[token_index
++] = CTLESC
;
4103 token
[token_index
++] = character
;
4105 RESIZE_MALLOCED_BUFFER (token
, token_index
, 1, token_buffer_size
,
4106 TOKEN_DEFAULT_GROW_SIZE
);
4109 if (character
== '\n' && interactive
&&
4110 (bash_input
.type
== st_stdin
|| bash_input
.type
== st_stream
))
4113 /* We want to remove quoted newlines (that is, a \<newline> pair)
4114 unless we are within single quotes or pass_next_character is
4115 set (the shell equivalent of literal-next). */
4116 cd
= current_delimiter (dstack
);
4117 character
= shell_getc (cd
!= '\'' && pass_next_character
== 0);
4118 } /* end for (;;) */
4122 token
[token_index
] = '\0';
4124 /* Check to see what thing we should return. If the last_read_token
4125 is a `<', or a `&', or the character which ended this token is
4126 a '>' or '<', then, and ONLY then, is this input token a NUMBER.
4127 Otherwise, it is just a word, and should be returned as such. */
4128 if (all_digits
&& (character
== '<' || character
== '>' ||
4129 last_read_token
== LESS_AND
||
4130 last_read_token
== GREATER_AND
))
4132 yylval
.number
= atoi (token
);
4136 /* Check for special case tokens. */
4137 result
= special_case_tokens (token
);
4142 /* Posix.2 does not allow reserved words to be aliased, so check for all
4143 of them, including special cases, before expanding the current token
4145 if (posixly_correct
)
4146 CHECK_FOR_RESERVED_WORD (token
);
4148 /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
4149 inhibits alias expansion. */
4150 if (expand_aliases
&& quoted
== 0)
4152 result
= alias_expand_token (token
);
4153 if (result
== RE_READ_TOKEN
)
4154 return (RE_READ_TOKEN
);
4155 else if (result
== NO_EXPANSION
)
4156 parser_state
&= ~PST_ALEXPNEXT
;
4159 /* If not in Posix.2 mode, check for reserved words after alias
4161 if (posixly_correct
== 0)
4163 CHECK_FOR_RESERVED_WORD (token
);
4165 the_word
= (WORD_DESC
*)xmalloc (sizeof (WORD_DESC
));
4166 the_word
->word
= xmalloc (1 + token_index
);
4167 the_word
->flags
= 0;
4168 strcpy (the_word
->word
, token
);
4170 the_word
->flags
|= W_HASDOLLAR
;
4172 the_word
->flags
|= W_QUOTED
;
4173 /* A word is an assignment if it appears at the beginning of a
4174 simple command, or after another assignment word. This is
4175 context-dependent, so it cannot be handled in the grammar. */
4176 if (assignment (token
))
4178 the_word
->flags
|= W_ASSIGNMENT
;
4179 /* Don't perform word splitting on assignment statements. */
4180 if (assignment_acceptable (last_read_token
))
4181 the_word
->flags
|= W_NOSPLIT
;
4184 yylval
.word
= the_word
;
4186 result
= ((the_word
->flags
& (W_ASSIGNMENT
|W_NOSPLIT
)) == (W_ASSIGNMENT
|W_NOSPLIT
))
4187 ? ASSIGNMENT_WORD
: WORD
;
4189 if (last_read_token
== FUNCTION
)
4191 parser_state
|= PST_ALLOWOPNBRC
;
4192 function_dstart
= line_number
;
4198 /* $'...' ANSI-C expand the portion of STRING between START and END and
4199 return the result. The result cannot be longer than the input string. */
4201 ansiexpand (string
, start
, end
, lenp
)
4203 int start
, end
, *lenp
;
4208 temp
= xmalloc (end
- start
+ 1);
4209 for (tlen
= 0, len
= start
; len
< end
; )
4210 temp
[tlen
++] = string
[len
++];
4215 t
= ansicstr (temp
, tlen
, (int *)NULL
, lenp
);
4227 /* $"..." -- Translate the portion of STRING between START and END
4228 according to current locale using gettext (if available) and return
4229 the result. The caller will take care of leaving the quotes intact.
4230 The string will be left without the leading `$' by the caller.
4231 If translation is performed, the translated string will be double-quoted
4232 by the caller. The length of the translated string is returned in LENP,
4235 localeexpand (string
, start
, end
, lineno
, lenp
)
4237 int start
, end
, lineno
, *lenp
;
4242 temp
= xmalloc (end
- start
+ 1);
4243 for (tlen
= 0, len
= start
; len
< end
; )
4244 temp
[tlen
++] = string
[len
++];
4247 /* If we're just dumping translatable strings, don't do anything. */
4248 if (dump_translatable_strings
)
4250 if (dump_po_strings
)
4251 printf ("#: %s:%d\nmsgid \"%s\"\nmsgstr \"\"\n",
4252 (bash_input
.name
? bash_input
.name
: "stdin"), lineno
, temp
);
4254 printf ("\"%s\"\n", temp
);
4261 t
= localetrans (temp
, tlen
, &len
);
4275 /* Return 1 if TOKEN is a token that after being read would allow
4276 a reserved word to be seen, else 0. */
4278 reserved_word_acceptable (token
)
4281 if (token
== '\n' || token
== ';' || token
== '(' || token
== ')' ||
4282 token
== '|' || token
== '&' || token
== '{' ||
4283 token
== '}' || /* XXX */
4286 token
== TIME
|| token
== TIMEOPT
||
4293 token
== SEMI_SEMI
||
4297 token
== DONE
|| /* XXX these two are experimental */
4305 /* Return the index of TOKEN in the alist of reserved words, or -1 if
4306 TOKEN is not a shell reserved word. */
4308 find_reserved_word (token
)
4312 for (i
= 0; word_token_alist
[i
].word
; i
++)
4313 if (STREQ (token
, word_token_alist
[i
].word
))
4319 #if defined (READLINE)
4320 /* Called after each time readline is called. This insures that whatever
4321 the new prompt string is gets propagated to readline's local prompt
4324 reset_readline_prompt ()
4328 if (prompt_string_pointer
)
4330 temp_prompt
= (*prompt_string_pointer
)
4331 ? decode_prompt_string (*prompt_string_pointer
)
4334 if (temp_prompt
== 0)
4336 temp_prompt
= xmalloc (1);
4337 temp_prompt
[0] = '\0';
4340 FREE (current_readline_prompt
);
4341 current_readline_prompt
= temp_prompt
;
4344 #endif /* READLINE */
4347 #if defined (HISTORY)
4348 /* A list of tokens which can be followed by newlines, but not by
4349 semi-colons. When concatenating multiple lines of history, the
4350 newline separator for such tokens is replaced with a space. */
4351 static int no_semi_successors
[] = {
4352 '\n', '{', '(', ')', ';', '&', '|',
4353 CASE
, DO
, ELSE
, IF
, SEMI_SEMI
, THEN
, UNTIL
, WHILE
, AND_AND
, OR_OR
, IN
,
4357 /* If we are not within a delimited expression, try to be smart
4358 about which separators can be semi-colons and which must be
4359 newlines. Returns the string that should be added into the
4362 history_delimiting_chars ()
4366 if (dstack
.delimiter_depth
!= 0)
4369 /* First, handle some special cases. */
4371 /* If we just read `()', assume it's a function definition, and don't
4372 add a semicolon. If the token before the `)' was not `(', and we're
4373 not in the midst of parsing a case statement, assume it's a
4374 parenthesized command and add the semicolon. */
4376 if (token_before_that
== ')')
4378 if (two_tokens_ago
== '(') /*)*/ /* function def */
4380 /* This does not work for subshells inside case statement
4381 command lists. It's a suboptimal solution. */
4382 else if (parser_state
& PST_CASESTMT
) /* case statement pattern */
4385 return "; "; /* (...) subshell */
4387 else if (token_before_that
== WORD
&& two_tokens_ago
== FUNCTION
)
4388 return " "; /* function def using `function name' without `()' */
4390 for (i
= 0; no_semi_successors
[i
]; i
++)
4392 if (token_before_that
== no_semi_successors
[i
])
4398 #endif /* HISTORY */
4400 /* Issue a prompt, or prepare to issue a prompt when the next character
4407 if (!interactive
) /* XXX */
4410 ps1_prompt
= get_string_value ("PS1");
4411 ps2_prompt
= get_string_value ("PS2");
4413 if (!prompt_string_pointer
)
4414 prompt_string_pointer
= &ps1_prompt
;
4416 temp_prompt
= *prompt_string_pointer
4417 ? decode_prompt_string (*prompt_string_pointer
)
4420 if (temp_prompt
== 0)
4422 temp_prompt
= xmalloc (1);
4423 temp_prompt
[0] = '\0';
4426 current_prompt_string
= *prompt_string_pointer
;
4427 prompt_string_pointer
= &ps2_prompt
;
4429 #if defined (READLINE)
4430 if (!no_line_editing
)
4432 FREE (current_readline_prompt
);
4433 current_readline_prompt
= temp_prompt
;
4436 #endif /* READLINE */
4438 FREE (current_decoded_prompt
);
4439 current_decoded_prompt
= temp_prompt
;
4446 fprintf (stderr
, "%s", current_decoded_prompt
);
4450 /* Return a string which will be printed as a prompt. The string
4451 may contain special characters which are decoded as follows:
4454 \e escape (ascii 033)
4455 \d the date in Day Mon Date format
4456 \h the hostname up to the first `.'
4459 \s the name of the shell
4460 \t the time in 24-hour hh:mm:ss format
4461 \T the time in 12-hour hh:mm:ss format
4462 \@ the time in 12-hour am/pm format
4463 \v the version of bash (e.g., 2.00)
4464 \V the release of bash, version + patchlevel (e.g., 2.00.0)
4465 \w the current working directory
4466 \W the last element of $PWD
4468 \# the command number of this command
4469 \! the history number of this command
4470 \$ a $ or a # if you are root
4471 \nnn character code nnn in octal
4473 \[ begin a sequence of non-printing chars
4474 \] end a sequence of non-printing chars
4476 #define PROMPT_GROWTH 48
4478 decode_prompt_string (string
)
4483 struct dstack save_dstack
;
4484 #if defined (PROMPT_STRING_DECODE)
4485 int result_size
, result_index
;
4487 char *temp
, octal_string
[4];
4490 result
= xmalloc (result_size
= PROMPT_GROWTH
);
4491 result
[result_index
= 0] = 0;
4492 temp
= (char *)NULL
;
4494 while (c
= *string
++)
4496 if (posixly_correct
&& c
== '!')
4500 temp
= savestring ("!");
4505 #if !defined (HISTORY)
4506 temp
= savestring ("1");
4508 temp
= itos (history_number ());
4509 #endif /* HISTORY */
4510 string
--; /* add_string increments string again. */
4528 strncpy (octal_string
, string
, 3);
4529 octal_string
[3] = '\0';
4531 n
= read_octal (octal_string
);
4534 if (n
== CTLESC
|| n
== CTLNUL
)
4560 /* Make the current time/date into a string. */
4561 the_time
= time (0);
4562 temp
= ctime (&the_time
);
4564 temp
= (c
!= 'd') ? savestring (temp
+ 11) : savestring (temp
);
4565 temp
[(c
!= 'd') ? 8 : 10] = '\0';
4567 /* quick and dirty conversion to 12-hour time */
4568 if (c
== 'T' || c
== '@')
4572 temp
[5] = 'a'; /* am/pm format */
4583 temp
[0] = (n
/ 10) + '0';
4584 temp
[1] = (n
% 10) + '0';
4586 if (n
>= 0 && temp
[5] == 'a')
4599 temp
[0] = no_line_editing
? '\n' : '\r';
4600 temp
[1] = no_line_editing
? '\0' : '\n';
4605 temp
= base_pathname (shell_name
);
4606 temp
= savestring (temp
);
4613 strcpy (temp
, dist_version
);
4615 sprintf (temp
, "%s.%d", dist_version
, patch_level
);
4621 /* Use the value of PWD because it is much more efficient. */
4622 char t_string
[PATH_MAX
];
4625 temp
= get_string_value ("PWD");
4629 if (getcwd (t_string
, sizeof(t_string
)) == 0)
4635 tlen
= strlen (t_string
);
4639 tlen
= sizeof (t_string
) - 1;
4640 strncpy (t_string
, temp
, tlen
);
4642 t_string
[tlen
] = '\0';
4646 t
= strrchr (t_string
, '/');
4647 if (t
&& t
!= t_string
)
4648 strcpy (t_string
, t
+ 1);
4651 /* polite_directory_format is guaranteed to return a string
4652 no longer than PATH_MAX - 1 characters. */
4653 strcpy (t_string
, polite_directory_format (t_string
));
4655 /* If we're going to be expanding the prompt string later,
4656 quote the directory name. */
4657 if (promptvars
|| posixly_correct
)
4658 temp
= backslash_quote (t_string
);
4660 temp
= savestring (t_string
);
4666 temp
= savestring (current_user
.user_name
);
4671 temp
= savestring (current_host_name
);
4672 if (c
== 'h' && (t
= (char *)strchr (temp
, '.')))
4677 temp
= itos (current_command_number
);
4681 #if !defined (HISTORY)
4682 temp
= savestring ("1");
4684 temp
= itos (history_number ());
4685 #endif /* HISTORY */
4690 temp
[0] = current_user
.euid
== 0 ? '#' : '$';
4694 #if defined (READLINE)
4699 temp
[1] = (c
== '[') ? RL_PROMPT_START_IGNORE
: RL_PROMPT_END_IGNORE
;
4702 #endif /* READLINE */
4713 temp
[0] = (c
== 'a') ? '\07' : '\033';
4727 sub_append_string (temp
, result
, &result_index
, &result_size
);
4728 temp
= (char *)NULL
; /* Freed in sub_append_string (). */
4729 result
[result_index
] = '\0';
4735 RESIZE_MALLOCED_BUFFER (result
, result_index
, 3, result_size
, PROMPT_GROWTH
);
4736 result
[result_index
++] = c
;
4737 result
[result_index
] = '\0';
4740 #else /* !PROMPT_STRING_DECODE */
4741 result
= savestring (string
);
4742 #endif /* !PROMPT_STRING_DECODE */
4744 /* Save the delimiter stack and point `dstack' to temp space so any
4745 command substitutions in the prompt string won't result in screwing
4746 up the parser's quoting state. */
4747 save_dstack
= dstack
;
4748 dstack
= temp_dstack
;
4749 dstack
.delimiter_depth
= 0;
4751 /* Perform variable and parameter expansion and command substitution on
4752 the prompt string. */
4753 if (promptvars
|| posixly_correct
)
4755 list
= expand_string_unsplit (result
, Q_DOUBLE_QUOTES
);
4757 result
= string_list (list
);
4758 dispose_words (list
);
4762 t
= dequote_string (result
);
4767 dstack
= save_dstack
;
4772 /* Report a syntax error, and restart the parser. Call here for fatal
4777 report_syntax_error ((char *)NULL
);
4782 /* Report a syntax error with line numbers, etc.
4783 Call here for recoverable errors. If you have a message to print,
4784 then place it in MESSAGE, otherwise pass NULL and this will figure
4785 out an appropriate message for you. */
4787 report_syntax_error (message
)
4796 parser_error (line_number
, "%s", message
);
4797 if (interactive
&& EOF_Reached
)
4799 last_command_exit_value
= EX_USAGE
;
4803 /* If the line of input we're reading is not null, try to find the
4804 objectionable token. */
4805 if (shell_input_line
&& *shell_input_line
)
4807 t
= shell_input_line
;
4808 i
= shell_input_line_index
;
4811 if (i
&& t
[i
] == '\0')
4814 while (i
&& (whitespace (t
[i
]) || t
[i
] == '\n'))
4820 while (i
&& (member (t
[i
], " \n\t;|&") == 0))
4823 while (i
!= token_end
&& (whitespace (t
[i
]) || t
[i
] == '\n'))
4826 /* Print the offending token. */
4827 if (token_end
|| (i
== 0 && token_end
== 0))
4831 msg
= xmalloc (1 + (token_end
- i
));
4832 strncpy (msg
, t
+ i
, token_end
- i
);
4833 msg
[token_end
- i
] = '\0';
4835 else /* one-character token */
4842 parser_error (line_number
, "syntax error near unexpected token `%s'", msg
);
4848 /* If not interactive, print the line containing the error. */
4849 if (interactive
== 0)
4851 msg
= savestring (shell_input_line
);
4852 token_end
= strlen (msg
);
4853 while (token_end
&& msg
[token_end
- 1] == '\n')
4854 msg
[--token_end
] = '\0';
4856 parser_error (line_number
, "`%s'", msg
);
4862 msg
= EOF_Reached
? "syntax error: unexpected end of file" : "syntax error";
4863 parser_error (line_number
, "%s", msg
);
4864 /* When the shell is interactive, this file uses EOF_Reached
4865 only for error reporting. Other mechanisms are used to
4866 decide whether or not to exit. */
4867 if (interactive
&& EOF_Reached
)
4870 last_command_exit_value
= EX_USAGE
;
4873 /* ??? Needed function. ??? We have to be able to discard the constructs
4874 created during parsing. In the case of error, we want to return
4875 allocated objects to the memory pool. In the case of no error, we want
4876 to throw away the information about where the allocated objects live.
4877 (dispose_command () will actually free the command. */
4879 discard_parser_constructs (error_p
)
4884 /* Do that silly `type "bye" to exit' stuff. You know, "ignoreeof". */
4886 /* A flag denoting whether or not ignoreeof is set. */
4889 /* The number of times that we have encountered an EOF character without
4890 another character intervening. When this gets above the limit, the
4891 shell terminates. */
4892 int eof_encountered
= 0;
4894 /* The limit for eof_encountered. */
4895 int eof_encountered_limit
= 10;
4897 /* If we have EOF as the only input unit, this user wants to leave
4898 the shell. If the shell is not interactive, then just leave.
4899 Otherwise, if ignoreeof is set, and we haven't done this the
4900 required number of times in a row, print a message. */
4902 handle_eof_input_unit ()
4906 /* shell.c may use this to decide whether or not to write out the
4907 history, among other things. We use it only for error reporting
4912 /* If the user wants to "ignore" eof, then let her do so, kind of. */
4915 if (eof_encountered
< eof_encountered_limit
)
4917 fprintf (stderr
, "Use \"%s\" to leave the shell.\n",
4918 login_shell
? "logout" : "exit");
4920 /* Reset the prompt string to be $PS1. */
4921 prompt_string_pointer
= (char **)NULL
;
4923 last_read_token
= current_token
= '\n';
4928 /* In this case EOF should exit the shell. Do it now. */
4930 exit_builtin ((WORD_LIST
*)NULL
);
4934 /* We don't write history files, etc., for non-interactive shells. */