1 /* Yacc grammar for bash. */
2 
3 /* Copyright (C) 1989 Free Software Foundation, Inc.
4 
5    This file is part of GNU Bash, the Bourne Again SHell.
6 
7    Bash is free software; you can redistribute it and/or modify it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 1, or (at your option) any later
10    version.
11 
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16 
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file LICENSE.  If not, write to the Free Software
19    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 
21 %{
22 #include <stdio.h>
23 #include "bashtypes.h"
24 #include <signal.h>
25 #include "bashansi.h"
26 #include "shell.h"
27 #include "flags.h"
28 #include "input.h"
29 
30 #if defined (READLINE)
31 #  include <readline/readline.h>
32 #endif /* READLINE */
33 
34 #if defined (HISTORY)
35 #  include "bashhist.h"
36 #  include <readline/history.h>
37 #endif /* HISTORY */
38 
39 #if defined (JOB_CONTROL)
40 #  include "jobs.h"
41 #endif /* JOB_CONTROL */
42 
43 #if defined (ALIAS)
44 #  include "alias.h"
45 #endif /* ALIAS */
46 
47 #if defined (PROMPT_STRING_DECODE)
48 #include <sys/param.h>
49 #include <time.h>
50 #include "maxpath.h"
51 #endif /* PROMPT_STRING_DECODE */
52 
53 #define YYDEBUG 1
54 extern int eof_encountered;
55 extern int no_line_editing;
56 extern int current_command_number;
57 extern int interactive, interactive_shell, login_shell;
58 extern int posixly_correct;
59 extern int last_command_exit_value;
60 extern int interrupt_immediately;
61 extern char *shell_name, *current_host_name;
62 extern Function *last_shell_builtin, *this_shell_builtin;
63 #if defined (READLINE)
64 extern int bash_readline_initialized;
65 #endif
66 #if defined (BUFFERED_INPUT)
67 extern int bash_input_fd_changed;
68 #endif
69 
70 /* **************************************************************** */
71 /*								    */
72 /*		    "Forward" declarations			    */
73 /*								    */
74 /* **************************************************************** */
75 
76 /* This is kind of sickening.  In order to let these variables be seen by
77    all the functions that need them, I am forced to place their declarations
78    far away from the place where they should logically be found. */
79 
80 static int reserved_word_acceptable ();
81 static int read_token ();
82 
83 static void report_syntax_error ();
84 static void handle_eof_input_unit ();
85 static void prompt_again ();
86 static void reset_readline_prompt ();
87 static void print_prompt ();
88 
89 /* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
90 char *ps1_prompt, *ps2_prompt;
91 
92 /* Handle on the current prompt string.  Indirectly points through
93    ps1_ or ps2_prompt. */
94 char **prompt_string_pointer = (char **)NULL;
95 char *current_prompt_string;
96 
97 /* The decoded prompt string.  Used if READLINE is not defined or if
98    editing is turned off.  Analogous to current_readline_prompt. */
99 static char *current_decoded_prompt;
100 
101 /* The number of lines read from input while creating the current command. */
102 int current_command_line_count = 0;
103 
104 /* Variables to manage the task of reading here documents, because we need to
105    defer the reading until after a complete command has been collected. */
106 static REDIRECT *redir_stack[10];
107 int need_here_doc = 0;
108 
109 /* Where shell input comes from.  History expansion is performed on each
110    line when the shell is interactive. */
111 static char *shell_input_line = (char *)NULL;
112 static int shell_input_line_index = 0;
113 static int shell_input_line_size = 0;	/* Amount allocated for shell_input_line. */
114 static int shell_input_line_len = 0;	/* strlen (shell_input_line) */
115 
116 /* Either zero or EOF. */
117 static int shell_input_line_terminator = 0;
118 
119 static REDIRECTEE redir;
120 %}
121 
122 %union {
123   WORD_DESC *word;		/* the word that we read. */
124   int number;			/* the number that we read. */
125   WORD_LIST *word_list;
126   COMMAND *command;
127   REDIRECT *redirect;
128   ELEMENT element;
129   PATTERN_LIST *pattern;
130 }
131 
132 /* Reserved words.  Members of the first group are only recognized
133    in the case that they are preceded by a list_terminator.  Members
134    of the second group are recognized only under special circumstances. */
135 %token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
136 %token IN BANG
137 
138 /* More general tokens. yylex () knows how to make these. */
139 %token <word> WORD ASSIGNMENT_WORD
140 %token <number> NUMBER
141 %token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND
142 %token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
143 %token GREATER_BAR
144 
145 /* The types that the various syntactical units return. */
146 
147 %type <command> inputunit command pipeline
148 %type <command> list list0 list1 simple_list simple_list1
149 %type <command> simple_command shell_command_1 shell_command select_command
150 %type <command> group_command function_def if_command elif_clause subshell
151 %type <redirect> redirection redirections
152 %type <element> simple_command_element
153 %type <word_list> words pattern
154 %type <pattern> pattern_list case_clause_sequence case_clause_1 pattern_list_1
155 
156 %start inputunit
157 
158 %left '&' ';' '\n' yacc_EOF
159 %left AND_AND OR_OR
160 %right '|'
161 %%
162 
163 inputunit:	simple_list '\n'
164 			{
165 			  /* Case of regular command.  Discard the error
166 			     safety net,and return the command just parsed. */
167 			  global_command = $1;
168 			  eof_encountered = 0;
169 			  discard_parser_constructs (0);
170 			  YYACCEPT;
171 			}
172 	|	'\n'
173 			{
174 			  /* Case of regular command, but not a very
175 			     interesting one.  Return a NULL command. */
176 			  global_command = (COMMAND *)NULL;
177 			  YYACCEPT;
178 			}
179 	|
180 		error '\n'
181 			{
182 			  /* Error during parsing.  Return NULL command. */
183 			  global_command = (COMMAND *)NULL;
184 			  eof_encountered = 0;
185 			  discard_parser_constructs (1);
186 			  if (interactive)
187 			    {
188 			      YYACCEPT;
189 			    }
190 			  else
191 			    {
192 			      YYABORT;
193 			    }
194 			}
195 	|	yacc_EOF
196 			{
197 			  /* Case of EOF seen by itself.  Do ignoreeof or
198 			     not. */
199 			  global_command = (COMMAND *)NULL;
200 			  handle_eof_input_unit ();
201 			  YYACCEPT;
202 			}
203 	;
204 
205 words:
206 			{ $$ = (WORD_LIST *)NULL; }
207 	|	words WORD
208 			{ $$ = make_word_list ($2, $1); }
209 	;
210 
211 redirection:	'>' WORD
212 			{
213 			  redir.filename = $2;
214 			  $$ = make_redirection (1, r_output_direction, redir);
215 			}
216 	|	'<' WORD
217 			{
218 			  redir.filename = $2;
219 			  $$ = make_redirection (0, r_input_direction, redir);
220 			}
221 	|	NUMBER '>' WORD
222 			{
223 			  redir.filename = $3;
224 			  $$ = make_redirection ($1, r_output_direction, redir);
225 			}
226 	|	NUMBER '<' WORD
227 			{
228 			  redir.filename = $3;
229 			  $$ = make_redirection ($1, r_input_direction, redir);
230 			}
231 	|	GREATER_GREATER WORD
232 			{
233 			  redir.filename = $2;
234 			  $$ = make_redirection (1, r_appending_to, redir);
235 			}
236 	|	NUMBER GREATER_GREATER WORD
237 			{
238 			  redir.filename = $3;
239 			  $$ = make_redirection ($1, r_appending_to, redir);
240 			}
241 	|	LESS_LESS WORD
242 			{
243 			  redir.filename = $2;
244 			  $$ = make_redirection (0, r_reading_until, redir);
245 			  redir_stack[need_here_doc++] = $$;
246 			}
247 	|	NUMBER LESS_LESS WORD
248 			{
249 			  redir.filename = $3;
250 			  $$ = make_redirection ($1, r_reading_until, redir);
251 			  redir_stack[need_here_doc++] = $$;
252 			}
253 	|	LESS_AND NUMBER
254 			{
255 			  redir.dest = $2;
256 			  $$ = make_redirection (0, r_duplicating_input, redir);
257 			}
258 	|	NUMBER LESS_AND NUMBER
259 			{
260 			  redir.dest = $3;
261 			  $$ = make_redirection ($1, r_duplicating_input, redir);
262 			}
263 	|	GREATER_AND NUMBER
264 			{
265 			  redir.dest = $2;
266 			  $$ = make_redirection (1, r_duplicating_output, redir);
267 			}
268 	|	NUMBER GREATER_AND NUMBER
269 			{
270 			  redir.dest = $3;
271 			  $$ = make_redirection ($1, r_duplicating_output, redir);
272 			}
273 	|	LESS_AND WORD
274 			{
275 			  redir.filename = $2;
276 			  $$ = make_redirection (0, r_duplicating_input_word, redir);
277 			}
278 	|	NUMBER LESS_AND WORD
279 			{
280 			  redir.filename = $3;
281 			  $$ = make_redirection ($1, r_duplicating_input_word, redir);
282 			}
283 	|	GREATER_AND WORD
284 			{
285 			  redir.filename = $2;
286 			  $$ = make_redirection (1, r_duplicating_output_word, redir);
287 			}
288 	|	NUMBER GREATER_AND WORD
289 			{
290 			  redir.filename = $3;
291 			  $$ = make_redirection ($1, r_duplicating_output_word, redir);
292 			}
293 	|	LESS_LESS_MINUS WORD
294 			{
295 			  redir.filename = $2;
296 			  $$ = make_redirection
297 			    (0, r_deblank_reading_until, redir);
298 			  redir_stack[need_here_doc++] = $$;
299 			}
300 	|	NUMBER LESS_LESS_MINUS WORD
301 			{
302 			  redir.filename = $3;
303 			  $$ = make_redirection
304 			    ($1, r_deblank_reading_until, redir);
305 			  redir_stack[need_here_doc++] = $$;
306 			}
307 	|	GREATER_AND '-'
308 			{
309 			  redir.dest = 0L;
310 			  $$ = make_redirection (1, r_close_this, redir);
311 			}
312 	|	NUMBER GREATER_AND '-'
313 			{
314 			  redir.dest = 0L;
315 			  $$ = make_redirection ($1, r_close_this, redir);
316 			}
317 	|	LESS_AND '-'
318 			{
319 			  redir.dest = 0L;
320 			  $$ = make_redirection (0, r_close_this, redir);
321 			}
322 	|	NUMBER LESS_AND '-'
323 			{
324 			  redir.dest = 0L;
325 			  $$ = make_redirection ($1, r_close_this, redir);
326 			}
327 	|	AND_GREATER WORD
328 			{
329 			  redir.filename = $2;
330 			  $$ = make_redirection (1, r_err_and_out, redir);
331 			}
332 	|	NUMBER LESS_GREATER WORD
333 			{
334 			  redir.filename = $3;
335 			  $$ = make_redirection ($1, r_input_output, redir);
336 			}
337 	|	LESS_GREATER WORD
338 			{
339 			  REDIRECT *t1, *t2;
340 
341 			  redir.filename = $2;
342 			  if (posixly_correct)
343 			    $$ = make_redirection (0, r_input_output, redir);
344 			  else
345 			    {
346 			      t1 = make_redirection (0, r_input_direction, redir);
347 			      redir.filename = copy_word ($2);
348 			      t2 = make_redirection (1, r_output_direction, redir);
349 			      t1->next = t2;
350 			      $$ = t1;
351 			    }
352 			}
353 	|	GREATER_BAR WORD
354 			{
355 			  redir.filename = $2;
356 			  $$ = make_redirection (1, r_output_force, redir);
357 			}
358 	|	NUMBER GREATER_BAR WORD
359 			{
360 			  redir.filename = $3;
361 			  $$ = make_redirection ($1, r_output_force, redir);
362 			}
363 	;
364 
365 simple_command_element: WORD
366 			{ $$.word = $1; $$.redirect = 0; }
367 	|	ASSIGNMENT_WORD
368 			{ $$.word = $1; $$.redirect = 0; }
369 	|	redirection
370 			{ $$.redirect = $1; $$.word = 0; }
371 	;
372 
373 redirections:	redirection
374 			{
375 			  $$ = $1;
376 			}
377 	|	redirections redirection
378 			{
379 			  register REDIRECT *t = $1;
380 
381 			  while (t->next)
382 			    t = t->next;
383 			  t->next = $2;
384 			  $$ = $1;
385 			}
386 	;
387 
388 simple_command:	simple_command_element
389 			{ $$ = make_simple_command ($1, (COMMAND *)NULL); }
390 	|	simple_command simple_command_element
391 			{ $$ = make_simple_command ($2, $1); }
392 	;
393 
394 command:	simple_command
395 			{ $$ = clean_simple_command ($1); }
396 	|	shell_command
397 			{ $$ = $1; }
398 	;
399 
400 shell_command:	shell_command_1
401 			{ $$ = $1; }
402 	|	shell_command_1 redirections
403 			{
404 			  if ($1->redirects)
405 			    {
406 			      register REDIRECT *t;
407 			      for (t = $1->redirects; t->next; t = t->next)
408 				;
409 			      t->next = $2;
410 			    }
411 			  else
412 			    $1->redirects = $2;
413 			  $$ = $1;
414 			}
415 	;
416 
417 shell_command_1: FOR WORD newlines DO list DONE
418 			{ $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5); }
419 	|	FOR WORD newlines '{' list '}'
420 			{ $$ = make_for_command ($2, add_string_to_list ("$@", (WORD_LIST *)NULL), $5); }
421 	|	FOR WORD ';' newlines DO list DONE
422 			{ $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6); }
423 	|	FOR WORD ';' newlines '{' list '}'
424 			{ $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6); }
425 	|	FOR WORD newlines IN words list_terminator newlines DO list DONE
426 			{ $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9); }
427 	|	FOR WORD newlines IN words list_terminator newlines '{' list '}'
428 			{ $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9); }
429 
430 	|	CASE WORD newlines IN newlines ESAC
431 			{ $$ = make_case_command ($2, (PATTERN_LIST *)NULL); }
432 	|	CASE WORD newlines IN case_clause_sequence newlines ESAC
433 			{ $$ = make_case_command ($2, $5); }
434 	|	CASE WORD newlines IN case_clause_1 ESAC
435 			{ $$ = make_case_command ($2, $5); }
436  	|	WHILE list DO list DONE
437 			{ $$ = make_while_command ($2, $4); }
438 	|	UNTIL list DO list DONE
439 			{ $$ = make_until_command ($2, $4); }
440 	|	select_command
441 			{ $$ = $1; }
442 	|	if_command
443 			{ $$ = $1; }
444 	|	subshell
445 			{ $$ = $1; }
446 	|	group_command
447 			{ $$ = $1; }
448 	|	function_def
449 			{ $$ = $1; }
450 	;
451 
452 select_command:	SELECT WORD newlines DO list DONE
453 			{
454 #if defined (SELECT_COMMAND)
455 			  $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5);
456 #endif
457 			}
458 	|	SELECT WORD newlines '{' list '}'
459 			{
460 #if defined (SELECT_COMMAND)
461 			  $$ = make_select_command ($2, add_string_to_list ("$@", (WORD_LIST *)NULL), $5);
462 #endif
463 			}
464 	|	SELECT WORD ';' newlines DO list DONE
465 			{
466 #if defined (SELECT_COMMAND)
467 			  $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6);
468 #endif
469 			}
470 	|	SELECT WORD ';' newlines '{' list '}'
471 			{
472 #if defined (SELECT_COMMAND)
473 			  $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6);
474 #endif
475 			}
476 	|	SELECT WORD newlines IN words list_terminator newlines DO list DONE
477 			{
478 #if defined (SELECT_COMMAND)
479 			  $$ = make_select_command ($2, (WORD_LIST *)reverse_list ($5), $9);
480 #endif
481 			}
482 	|	SELECT WORD newlines IN words list_terminator newlines '{' list '}'
483 			{
484 #if defined (SELECT_COMMAND)
485 			  $$ = make_select_command ($2, (WORD_LIST *)reverse_list ($5), $9);
486 #endif
487 			}
488 	;
489 
490 function_def:	WORD '(' ')' newlines group_command
491 			{ $$ = make_function_def ($1, $5); }
492 
493 	|	WORD '(' ')' newlines group_command redirections
494 			{ $5->redirects = $6; $$ = make_function_def ($1, $5); }
495 
496 	|	FUNCTION WORD '(' ')' newlines group_command
497 			{ $$ = make_function_def ($2, $6); }
498 
499 	|	FUNCTION WORD '(' ')' newlines group_command redirections
500 			{ $6->redirects = $7; $$ = make_function_def ($2, $6); }
501 
502 	|	FUNCTION WORD newlines group_command
503 			{ $$ = make_function_def ($2, $4); }
504 
505 	|	FUNCTION WORD newlines group_command redirections
506 			{ $4->redirects = $5; $$ = make_function_def ($2, $4); }
507 	;
508 
509 subshell:	'(' list ')'
510 			{ $2->flags |= CMD_WANT_SUBSHELL; $$ = $2; }
511 	;
512 
513 if_command:	IF list THEN list FI
514 			{ $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
515 	|	IF list THEN list ELSE list FI
516 			{ $$ = make_if_command ($2, $4, $6); }
517 	|	IF list THEN list elif_clause FI
518 			{ $$ = make_if_command ($2, $4, $5); }
519 	;
520 
521 
522 group_command:	'{' list '}'
523 			{ $$ = make_group_command ($2); }
524 	;
525 
526 elif_clause:	ELIF list THEN list
527 			{ $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
528 	|	ELIF list THEN list ELSE list
529 			{ $$ = make_if_command ($2, $4, $6); }
530 	|	ELIF list THEN list elif_clause
531 			{ $$ = make_if_command ($2, $4, $5); }
532 	;
533 
534 case_clause_1:	pattern_list_1
535 	|	case_clause_sequence pattern_list_1
536 			{ $2->next = $1; $$ = $2; }
537 	;
538 
539 pattern_list_1:	newlines pattern ')' list
540 			{ $$ = make_pattern_list ($2, $4); }
541 	|	newlines pattern ')' newlines
542 			{ $$ = make_pattern_list ($2, (COMMAND *)NULL); }
543 	|	newlines '(' pattern ')' list
544 			{ $$ = make_pattern_list ($3, $5); }
545 	|	newlines '(' pattern ')' newlines
546 			{ $$ = make_pattern_list ($3, (COMMAND *)NULL); }
547 	;
548 
549 case_clause_sequence:  pattern_list
550 	|	case_clause_sequence pattern_list
551 			{ $2->next = $1; $$ = $2; }
552 	;
553 
554 pattern_list:	newlines pattern ')' list SEMI_SEMI
555 			{ $$ = make_pattern_list ($2, $4); }
556 	|	newlines pattern ')' newlines SEMI_SEMI
557 			{ $$ = make_pattern_list ($2, (COMMAND *)NULL); }
558 	|	newlines '(' pattern ')' list SEMI_SEMI
559 			{ $$ = make_pattern_list ($3, $5); }
560 	|	newlines '(' pattern ')' newlines SEMI_SEMI
561 			{ $$ = make_pattern_list ($3, (COMMAND *)NULL); }
562 	;
563 
564 pattern:	WORD
565 			{ $$ = make_word_list ($1, (WORD_LIST *)NULL); }
566 	|	pattern '|' WORD
567 			{ $$ = make_word_list ($3, $1); }
568 	;
569 
570 /* A list allows leading or trailing newlines and
571    newlines as operators (equivalent to semicolons).
572    It must end with a newline or semicolon.
573    Lists are used within commands such as if, for, while.  */
574 
575 list:		newlines list0
576 			{
577 			  $$ = $2;
578 			  if (need_here_doc)
579 			    gather_here_documents ();
580 			 }
581 	;
582 
583 list0:		list1
584 	|	list1 '\n' newlines
585 	|	list1 '&' newlines
586 			{
587 			  if ($1->type == cm_connection)
588 			    $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
589 			  else
590 			    $$ = command_connect ($1, (COMMAND *)NULL, '&');
591 			}
592 	|	list1 ';' newlines
593 
594 	;
595 
596 list1:		list1 AND_AND newlines list1
597 			{ $$ = command_connect ($1, $4, AND_AND); }
598 	|	list1 OR_OR newlines list1
599 			{ $$ = command_connect ($1, $4, OR_OR); }
600 	|	list1 '&' newlines list1
601 			{
602 			  if ($1->type == cm_connection)
603 			    $$ = connect_async_list ($1, $4, '&');
604 			  else
605 			    $$ = command_connect ($1, $4, '&');
606 			}
607 	|	list1 ';' newlines list1
608 			{ $$ = command_connect ($1, $4, ';'); }
609 	|	list1 '\n' newlines list1
610 			{ $$ = command_connect ($1, $4, ';'); }
611 	|	pipeline
612 			{ $$ = $1; }
613 	|	BANG pipeline
614 			{
615 			  $2->flags |= CMD_INVERT_RETURN;
616 			  $$ = $2;
617 			}
618 	;
619 
620 list_terminator:'\n'
621 	|	';'
622 	|	yacc_EOF
623 	;
624 
625 newlines:
626 	|	newlines '\n'
627 	;
628 
629 /* A simple_list is a list that contains no significant newlines
630    and no leading or trailing newlines.  Newlines are allowed
631    only following operators, where they are not significant.
632 
633    This is what an inputunit consists of.  */
634 
635 simple_list:	simple_list1
636 			{
637 			  $$ = $1;
638 			  if (need_here_doc)
639 			    gather_here_documents ();
640 			}
641 	|	simple_list1 '&'
642 			{
643 			  if ($1->type == cm_connection)
644 			    $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
645 			  else
646 			    $$ = command_connect ($1, (COMMAND *)NULL, '&');
647 			  if (need_here_doc)
648 			    gather_here_documents ();
649 			}
650 	|	simple_list1 ';'
651 			{
652 			  $$ = $1;
653 			  if (need_here_doc)
654 			    gather_here_documents ();
655 			}
656 	;
657 
658 simple_list1:	simple_list1 AND_AND newlines simple_list1
659 			{ $$ = command_connect ($1, $4, AND_AND); }
660 	|	simple_list1 OR_OR newlines simple_list1
661 			{ $$ = command_connect ($1, $4, OR_OR); }
662 	|	simple_list1 '&' simple_list1
663 			{
664 			  if ($1->type == cm_connection)
665 			    $$ = connect_async_list ($1, $3, '&');
666 			  else
667 			    $$ = command_connect ($1, $3, '&');
668 			}
669 	|	simple_list1 ';' simple_list1
670 			{ $$ = command_connect ($1, $3, ';'); }
671 	|	pipeline
672 			{ $$ = $1; }
673 	|	BANG pipeline
674 			{
675 			  $2->flags |= CMD_INVERT_RETURN;
676 			  $$ = $2;
677 			}
678 	;
679 
680 pipeline:
681 		pipeline '|' newlines pipeline
682 			{ $$ = command_connect ($1, $4, '|'); }
683 	|	command
684 			{ $$ = $1; }
685 	;
686 %%
687 
688 /* Initial size to allocate for tokens, and the
689    amount to grow them by. */
690 #define TOKEN_DEFAULT_GROW_SIZE 512
691 
692 /* The token currently being read. */
693 static int current_token = 0;
694 
695 /* The last read token, or NULL.  read_token () uses this for context
696    checking. */
697 static int last_read_token = 0;
698 
699 /* The token read prior to last_read_token. */
700 static int token_before_that = 0;
701 
702 /* If non-zero, it is the token that we want read_token to return
703    regardless of what text is (or isn't) present to be read.  This
704    is reset by read_token. */
705 static int token_to_read = 0;
706 
707 /* Global var is non-zero when end of file has been reached. */
708 int EOF_Reached = 0;
709 
710 /* yy_getc () returns the next available character from input or EOF.
711    yy_ungetc (c) makes `c' the next character to read.
712    init_yy_io (get, unget, type, location) makes the function GET the
713    installed function for getting the next character, makes UNGET the
714    installed function for un-getting a character, sets the type of stream
715    (either string or file) from TYPE, and makes LOCATION point to where
716    the input is coming from. */
717 
718 /* Unconditionally returns end-of-file. */
return_EOF()719 return_EOF ()
720 {
721   return (EOF);
722 }
723 
724 /* Variable containing the current get and unget functions.
725    See ./input.h for a clearer description. */
726 BASH_INPUT bash_input;
727 
728 /* Set all of the fields in BASH_INPUT to NULL. */
729 void
initialize_bash_input()730 initialize_bash_input ()
731 {
732   bash_input.type = 0;
733   bash_input.name = (char *)NULL;
734   bash_input.location.file = (FILE *)NULL;
735   bash_input.location.string = (char *)NULL;
736   bash_input.getter = (Function *)NULL;
737   bash_input.ungetter = (Function *)NULL;
738 }
739 
740 /* Set the contents of the current bash input stream from
741    GET, UNGET, TYPE, NAME, and LOCATION. */
742 void
init_yy_io(get,unget,type,name,location)743 init_yy_io (get, unget, type, name, location)
744      Function *get, *unget;
745      int type;
746      char *name;
747      INPUT_STREAM location;
748 {
749   bash_input.type = type;
750   FREE (bash_input.name);
751 
752   if (name)
753     bash_input.name = savestring (name);
754   else
755     bash_input.name = (char *)NULL;
756 
757 #if defined (CRAY)
758   memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
759 #else
760   bash_input.location = location;
761 #endif
762   bash_input.getter = get;
763   bash_input.ungetter = unget;
764 }
765 
766 /* Call this to get the next character of input. */
yy_getc()767 yy_getc ()
768 {
769   return (*(bash_input.getter)) ();
770 }
771 
772 /* Call this to unget C.  That is, to make C the next character
773    to be read. */
yy_ungetc(c)774 yy_ungetc (c)
775      int c;
776 {
777   return (*(bash_input.ungetter)) (c);
778 }
779 
780 #if defined (BUFFERED_INPUT)
781 int
input_file_descriptor()782 input_file_descriptor ()
783 {
784   switch (bash_input.type)
785     {
786     case st_stream:
787       return (fileno (bash_input.location.file));
788     case st_bstream:
789       return (bash_input.location.buffered_fd);
790     default:
791       return (fileno (stdin));
792     }
793 }
794 #endif /* BUFFERED_INPUT */
795 
796 /* **************************************************************** */
797 /*								    */
798 /*		  Let input be read from readline ().		    */
799 /*								    */
800 /* **************************************************************** */
801 
802 #if defined (READLINE)
803 char *current_readline_prompt = (char *)NULL;
804 char *current_readline_line = (char *)NULL;
805 int current_readline_line_index = 0;
806 
807 static int
yy_readline_get()808 yy_readline_get ()
809 {
810   if (!current_readline_line)
811     {
812       SigHandler *old_sigint;
813       int line_len;
814 
815       if (!bash_readline_initialized)
816 	initialize_readline ();
817 
818 #if defined (JOB_CONTROL)
819       if (job_control)
820 	give_terminal_to (shell_pgrp);
821 #endif /* JOB_CONTROL */
822 
823       if (signal_is_ignored (SIGINT) == 0)
824 	{
825 	  old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
826 	  interrupt_immediately++;
827 	}
828 
829       if (!current_readline_prompt)
830 	current_readline_line = readline ("");
831       else
832 	current_readline_line = readline (current_readline_prompt);
833 
834       if (signal_is_ignored (SIGINT) == 0)
835 	{
836 	  interrupt_immediately--;
837 	  set_signal_handler (SIGINT, old_sigint);
838 	}
839 
840       /* Reset the prompt to whatever is in the decoded value of
841 	 prompt_string_pointer. */
842       reset_readline_prompt ();
843 
844       current_readline_line_index = 0;
845 
846       if (!current_readline_line)
847 	return (EOF);
848 
849       line_len = strlen (current_readline_line);
850       current_readline_line = xrealloc (current_readline_line, 2 + line_len);
851       current_readline_line[line_len++] = '\n';
852       current_readline_line[line_len] = '\0';
853     }
854 
855   if (!current_readline_line[current_readline_line_index])
856     {
857       free (current_readline_line);
858       current_readline_line = (char *)NULL;
859       return (yy_readline_get ());
860     }
861   else
862     {
863       int c = (unsigned char)current_readline_line[current_readline_line_index++];
864       return (c);
865     }
866 }
867 
868 static int
yy_readline_unget(c)869 yy_readline_unget (c)
870 {
871   if (current_readline_line_index && current_readline_line)
872     current_readline_line[--current_readline_line_index] = c;
873   return (c);
874 }
875 
876 void
with_input_from_stdin()877 with_input_from_stdin ()
878 {
879   INPUT_STREAM location;
880 
881   if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
882     {
883       location.string = current_readline_line;
884       init_yy_io (yy_readline_get, yy_readline_unget,
885 		  st_stdin, "readline stdin", location);
886     }
887 }
888 
889 #else  /* !READLINE */
890 
891 void
with_input_from_stdin()892 with_input_from_stdin ()
893 {
894   with_input_from_stream (stdin, "stdin");
895 }
896 #endif	/* !READLINE */
897 
898 /* **************************************************************** */
899 /*								    */
900 /*   Let input come from STRING.  STRING is zero terminated.	    */
901 /*								    */
902 /* **************************************************************** */
903 
904 static int
yy_string_get()905 yy_string_get ()
906 {
907   register unsigned char *string;
908   register int c;
909 
910   string = bash_input.location.string;
911   c = EOF;
912 
913   /* If the string doesn't exist, or is empty, EOF found. */
914   if (string && *string)
915     {
916       c = *string++;
917       bash_input.location.string = string;
918     }
919   return (c);
920 }
921 
922 static int
yy_string_unget(c)923 yy_string_unget (c)
924      int c;
925 {
926   *(--bash_input.location.string) = c;
927   return (c);
928 }
929 
930 void
with_input_from_string(string,name)931 with_input_from_string (string, name)
932      char *string;
933      char *name;
934 {
935   INPUT_STREAM location;
936 
937   location.string = string;
938 
939   init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
940 }
941 
942 /* **************************************************************** */
943 /*								    */
944 /*		     Let input come from STREAM.		    */
945 /*								    */
946 /* **************************************************************** */
947 
948 static int
yy_stream_get()949 yy_stream_get ()
950 {
951   int result = EOF;
952 
953   if (bash_input.location.file)
954 #if defined (NO_READ_RESTART_ON_SIGNAL)
955     result = (unsigned char)getc_with_restart (bash_input.location.file);
956 #else
957     result = (unsigned char)getc (bash_input.location.file);
958 #endif /* !NO_READ_RESTART_ON_SIGNAL */
959   return (result);
960 }
961 
962 static int
yy_stream_unget(c)963 yy_stream_unget (c)
964      int c;
965 {
966 #if defined (NO_READ_RESTART_ON_SIGNAL)
967   return (ungetc_with_restart (c, bash_input.location.file));
968 #else
969   return (ungetc (c, bash_input.location.file));
970 #endif
971 }
972 
973 void
with_input_from_stream(stream,name)974 with_input_from_stream (stream, name)
975      FILE *stream;
976      char *name;
977 {
978   INPUT_STREAM location;
979 
980   location.file = stream;
981   init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
982 }
983 
984 typedef struct stream_saver {
985   struct stream_saver *next;
986   BASH_INPUT bash_input;
987   int line;
988 #if defined (BUFFERED_INPUT)
989   BUFFERED_STREAM *bstream;
990 #endif /* BUFFERED_INPUT */
991 } STREAM_SAVER;
992 
993 /* The globally known line number. */
994 int line_number = 0;
995 
996 STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
997 
push_stream()998 push_stream ()
999 {
1000   STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
1001 
1002   xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
1003 
1004 #if defined (BUFFERED_INPUT)
1005   saver->bstream = (BUFFERED_STREAM *)NULL;
1006   /* If we have a buffered stream, clear out buffers[fd]. */
1007   if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
1008     {
1009       saver->bstream = buffers[bash_input.location.buffered_fd];
1010       buffers[bash_input.location.buffered_fd] = (BUFFERED_STREAM *)NULL;
1011     }
1012 #endif /* BUFFERED_INPUT */
1013 
1014   saver->line = line_number;
1015   bash_input.name = (char *)NULL;
1016   saver->next = stream_list;
1017   stream_list = saver;
1018   EOF_Reached = line_number = 0;
1019 }
1020 
pop_stream()1021 pop_stream ()
1022 {
1023   int temp;
1024 
1025   if (!stream_list)
1026     EOF_Reached = 1;
1027   else
1028     {
1029       STREAM_SAVER *saver = stream_list;
1030 
1031       EOF_Reached = 0;
1032       stream_list = stream_list->next;
1033 
1034       init_yy_io (saver->bash_input.getter,
1035 		  saver->bash_input.ungetter,
1036 		  saver->bash_input.type,
1037 		  saver->bash_input.name,
1038 		  saver->bash_input.location);
1039 
1040 #if defined (BUFFERED_INPUT)
1041       /* If we have a buffered stream, restore buffers[fd]. */
1042       /* If the input file descriptor was changed while this was on the
1043 	 save stack, update the buffered fd to the new file descriptor and
1044 	 re-establish the buffer <-> bash_input fd correspondence. */
1045       if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
1046         {
1047           if (bash_input_fd_changed)
1048 	    {
1049 	      bash_input_fd_changed = 0;
1050 	      if (default_buffered_input >= 0)
1051 		{
1052 		  bash_input.location.buffered_fd = default_buffered_input;
1053 		  saver->bstream->b_fd = default_buffered_input;
1054 		}
1055 	    }
1056 	  buffers[bash_input.location.buffered_fd] = saver->bstream;
1057         }
1058 #endif /* BUFFERED_INPUT */
1059 
1060       line_number = saver->line;
1061 
1062       FREE (saver->bash_input.name);
1063       free (saver);
1064     }
1065 }
1066 
1067 /* Return 1 if a stream of type TYPE is saved on the stack. */
1068 int
stream_on_stack(type)1069 stream_on_stack (type)
1070      int type;
1071 {
1072   register STREAM_SAVER *s;
1073 
1074   for (s = stream_list; s; s = s->next)
1075     if (s->bash_input.type == type)
1076       return 1;
1077   return 0;
1078 }
1079 
1080 
1081 /*
1082  * This is used to inhibit alias expansion and reserved word recognition
1083  * inside case statement pattern lists.  A `case statement pattern list'
1084  * is:
1085  *	everything between the `in' in a `case word in' and the next ')'
1086  *	or `esac'
1087  *	everything between a `;;' and the next `)' or `esac'
1088  */
1089 static int in_case_pattern_list = 0;
1090 
1091 #if defined (ALIAS)
1092 /*
1093  * Pseudo-global variables used in implementing token-wise alias expansion.
1094  */
1095 
1096 static int expand_next_token = 0;
1097 
1098 /*
1099  * Pushing and popping strings.  This works together with shell_getc to
1100  * implement alias expansion on a per-token basis.
1101  */
1102 
1103 typedef struct string_saver {
1104   struct string_saver *next;
1105   int expand_alias;  /* Value to set expand_alias to when string is popped. */
1106   char *saved_line;
1107   int saved_line_size, saved_line_index, saved_line_terminator;
1108 } STRING_SAVER;
1109 
1110 STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
1111 
1112 static void save_expansion ();
1113 
1114 /*
1115  * Push the current shell_input_line onto a stack of such lines and make S
1116  * the current input.  Used when expanding aliases.  EXPAND is used to set
1117  * the value of expand_next_token when the string is popped, so that the
1118  * word after the alias in the original line is handled correctly when the
1119  * alias expands to multiple words.  TOKEN is the token that was expanded
1120  * into S; it is saved and used to prevent infinite recursive expansion.
1121  */
1122 static void
push_string(s,expand,token)1123 push_string (s, expand, token)
1124      char *s;
1125      int expand;
1126      char *token;
1127 {
1128   STRING_SAVER *temp = (STRING_SAVER *) xmalloc (sizeof (STRING_SAVER));
1129 
1130   temp->expand_alias = expand;
1131   temp->saved_line = shell_input_line;
1132   temp->saved_line_size = shell_input_line_size;
1133   temp->saved_line_index = shell_input_line_index;
1134   temp->saved_line_terminator = shell_input_line_terminator;
1135   temp->next = pushed_string_list;
1136   pushed_string_list = temp;
1137 
1138   save_expansion (token);
1139 
1140   shell_input_line = s;
1141   shell_input_line_size = strlen (s);
1142   shell_input_line_index = 0;
1143   shell_input_line_terminator = '\0';
1144   expand_next_token = 0;
1145 }
1146 
1147 /*
1148  * Make the top of the pushed_string stack be the current shell input.
1149  * Only called when there is something on the stack.  Called from shell_getc
1150  * when it thinks it has consumed the string generated by an alias expansion
1151  * and needs to return to the original input line.
1152  */
1153 static void
pop_string()1154 pop_string ()
1155 {
1156   STRING_SAVER *t;
1157 
1158   FREE (shell_input_line);
1159   shell_input_line = pushed_string_list->saved_line;
1160   shell_input_line_index = pushed_string_list->saved_line_index;
1161   shell_input_line_size = pushed_string_list->saved_line_size;
1162   shell_input_line_terminator = pushed_string_list->saved_line_terminator;
1163   expand_next_token = pushed_string_list->expand_alias;
1164 
1165   t = pushed_string_list;
1166   pushed_string_list = pushed_string_list->next;
1167   free((char *)t);
1168 }
1169 
1170 static void
free_string_list()1171 free_string_list ()
1172 {
1173   register STRING_SAVER *t = pushed_string_list, *t1;
1174 
1175   while (t)
1176     {
1177       t1 = t->next;
1178       FREE (t->saved_line);
1179       free ((char *)t);
1180       t = t1;
1181     }
1182   pushed_string_list = (STRING_SAVER *)NULL;
1183 }
1184 
1185 /* This is a stack to save the values of all tokens for which alias
1186    expansion has been performed during the current call to read_token ().
1187    It is used to prevent alias expansion loops:
1188 
1189       alias foo=bar
1190       alias bar=baz
1191       alias baz=foo
1192 
1193    Ideally this would be taken care of by push and pop string, but because
1194    of when strings are popped the stack will not contain the correct
1195    strings to test against.  (The popping is done in shell_getc, so that when
1196    the current string is exhausted, shell_getc can simply pop that string off
1197    the stack, restore the previous string, and continue with the character
1198    following the token whose expansion was originally pushed on the stack.)
1199 
1200    What we really want is a record of all tokens that have been expanded for
1201    aliases during the `current' call to read_token().  This does that, at the
1202    cost of being somewhat special-purpose (OK, OK vile and unclean). */
1203 
1204 typedef struct _exp_saver {
1205       struct _exp_saver *next;
1206       char *saved_token;
1207 } EXPANSION_SAVER;
1208 
1209 EXPANSION_SAVER *expanded_token_stack = (EXPANSION_SAVER *)NULL;
1210 
1211 static void
save_expansion(s)1212 save_expansion (s)
1213      char *s;
1214 {
1215   EXPANSION_SAVER *t;
1216 
1217   t = (EXPANSION_SAVER *) xmalloc (sizeof (EXPANSION_SAVER));
1218   t->saved_token = savestring (s);
1219   t->next = expanded_token_stack;
1220   expanded_token_stack = t;
1221 }
1222 
1223 /* Return 1 if TOKEN has already been expanded in the current `stack' of
1224    expansions.  If it has been expanded already, it will appear as the value
1225    of saved_token for some entry in the stack of expansions created for the
1226    current token being expanded. */
1227 static int
token_has_been_expanded(token)1228 token_has_been_expanded (token)
1229      char *token;
1230 {
1231   register EXPANSION_SAVER *t = expanded_token_stack;
1232 
1233   while (t)
1234     {
1235       if (STREQ (token, t->saved_token))
1236 	return (1);
1237       t = t->next;
1238     }
1239   return (0);
1240 }
1241 
1242 static void
free_expansion_stack()1243 free_expansion_stack ()
1244 {
1245   register EXPANSION_SAVER *t = expanded_token_stack, *t1;
1246 
1247   while (t)
1248     {
1249       t1 = t->next;
1250       free (t->saved_token);
1251       free (t);
1252       t = t1;
1253     }
1254   expanded_token_stack = (EXPANSION_SAVER *)NULL;
1255 }
1256 
1257 #endif /* ALIAS */
1258 
1259 /* Return a line of text, taken from wherever yylex () reads input.
1260    If there is no more input, then we return NULL.  If REMOVE_QUOTED_NEWLINE
1261    is non-zero, we remove unquoted \<newline> pairs.  This is used by
1262    read_secondary_line to read here documents. */
1263 static char *
read_a_line(remove_quoted_newline)1264 read_a_line (remove_quoted_newline)
1265      int remove_quoted_newline;
1266 {
1267   static char *line_buffer = (char *)NULL;
1268   static int buffer_size = 0;
1269   int indx = 0, c, peekc, pass_next;
1270 
1271   pass_next = 0;
1272   while (1)
1273     {
1274       c = yy_getc ();
1275 
1276       /* Allow immediate exit if interrupted during input. */
1277       QUIT;
1278 
1279       if (c == 0)
1280 	continue;
1281 
1282       /* If there is no more input, then we return NULL. */
1283       if (c == EOF)
1284 	{
1285 	  if (indx == 0)
1286 	    return ((char *)NULL);
1287 	  c = '\n';
1288 	}
1289 
1290       /* `+2' in case the final character in the buffer is a newline. */
1291       if (indx + 2 > buffer_size)
1292 	if (!buffer_size)
1293 	  line_buffer = xmalloc (buffer_size = 128);
1294 	else
1295 	  line_buffer = xrealloc (line_buffer, buffer_size += 128);
1296 
1297       /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
1298 	 here document with an unquoted delimiter.  In this case,
1299 	 the line will be expanded as if it were in double quotes.
1300 	 We allow a backslash to escape the next character, but we
1301 	 need to treat the backslash specially only if a backslash
1302 	 quoting a backslash-newline pair appears in the line. */
1303       if (pass_next)
1304         {
1305 	  line_buffer[indx++] = c;
1306 	  pass_next = 0;
1307         }
1308       else if (c == '\\' && remove_quoted_newline)
1309 	{
1310 	  peekc = yy_getc ();
1311 	  if (peekc == '\n')
1312 	    continue;	/* Make the unquoted \<newline> pair disappear. */
1313 	  else
1314 	    {
1315 	      yy_ungetc (peekc);
1316 	      pass_next = 1;
1317 	      line_buffer[indx++] = c;		/* Preserve the backslash. */
1318 	    }
1319 	}
1320       else
1321 	line_buffer[indx++] = c;
1322 
1323       if (c == '\n')
1324 	{
1325 	  line_buffer[indx] = '\0';
1326 	  return (line_buffer);
1327 	}
1328     }
1329 }
1330 
1331 /* Return a line as in read_a_line (), but insure that the prompt is
1332    the secondary prompt.  This is used to read the lines of a here
1333    document.  REMOVE_QUOTED_NEWLINE is non-zero if we should remove
1334    newlines quoted with backslashes while reading the line.  It is
1335    non-zero unless the delimiter of the here document was quoted. */
1336 char *
read_secondary_line(remove_quoted_newline)1337 read_secondary_line (remove_quoted_newline)
1338      int remove_quoted_newline;
1339 {
1340   prompt_string_pointer = &ps2_prompt;
1341   prompt_again ();
1342   return (read_a_line (remove_quoted_newline));
1343 }
1344 
1345 
1346 /* **************************************************************** */
1347 /*								    */
1348 /*				YYLEX ()			    */
1349 /*								    */
1350 /* **************************************************************** */
1351 
1352 /* Reserved words.  These are only recognized as the first word of a
1353    command. */
1354 STRING_INT_ALIST word_token_alist[] = {
1355   { "if", IF },
1356   { "then", THEN },
1357   { "else", ELSE },
1358   { "elif", ELIF },
1359   { "fi", FI },
1360   { "case", CASE },
1361   { "esac", ESAC },
1362   { "for", FOR },
1363 #if defined (SELECT_COMMAND)
1364   { "select", SELECT },
1365 #endif
1366   { "while", WHILE },
1367   { "until", UNTIL },
1368   { "do", DO },
1369   { "done", DONE },
1370   { "in", IN },
1371   { "function", FUNCTION },
1372   { "{", '{' },
1373   { "}", '}' },
1374   { "!", BANG },
1375   { (char *)NULL, 0}
1376 };
1377 
1378 /* Return the next shell input character.  This always reads characters
1379    from shell_input_line; when that line is exhausted, it is time to
1380    read the next line.  This is called by read_token when the shell is
1381    processing normal command input. */
1382 static int
shell_getc(remove_quoted_newline)1383 shell_getc (remove_quoted_newline)
1384      int remove_quoted_newline;
1385 {
1386   int c;
1387 
1388   QUIT;
1389 
1390 #if defined (ALIAS)
1391   /* If shell_input_line[shell_input_line_index] == 0, but there is
1392      something on the pushed list of strings, then we don't want to go
1393      off and get another line.  We let the code down below handle it. */
1394 
1395   if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
1396 			    (pushed_string_list == (STRING_SAVER *)NULL)))
1397 #else /* !ALIAS */
1398   if (!shell_input_line || !shell_input_line[shell_input_line_index])
1399 #endif /* !ALIAS */
1400     {
1401       register int i, l;
1402 
1403       restart_read_next_line:
1404 
1405       line_number++;
1406 
1407     restart_read:
1408 
1409       /* Allow immediate exit if interrupted during input. */
1410       QUIT;
1411 
1412       i = 0;
1413       shell_input_line_terminator = 0;
1414 
1415 #if defined (JOB_CONTROL)
1416       /* This can cause a problem when reading a command as the result
1417 	 of a trap, when the trap is called from flush_child.  This call
1418 	 had better not cause jobs to disappear from the job table in
1419 	 that case, or we will have big trouble. */
1420       notify_and_cleanup ();
1421 #else /* !JOB_CONTROL */
1422       cleanup_dead_jobs ();
1423 #endif /* !JOB_CONTROL */
1424 
1425 #if defined (READLINE)
1426       if (interactive && bash_input.type != st_string && no_line_editing)
1427 #else
1428       if (interactive && bash_input.type != st_string)
1429 #endif
1430 	print_prompt ();
1431 
1432       if (bash_input.type == st_stream)
1433 	clearerr (stdin);
1434 
1435       while (c = yy_getc ())
1436 	{
1437 	  /* Allow immediate exit if interrupted during input. */
1438 	  QUIT;
1439 
1440 	  if (i + 2 > shell_input_line_size)
1441 	    shell_input_line =
1442 	      xrealloc (shell_input_line, shell_input_line_size += 256);
1443 
1444 	  if (c == EOF)
1445 	    {
1446 	      if (bash_input.type == st_stream)
1447 		clearerr (stdin);
1448 
1449 	      if (!i)
1450 		shell_input_line_terminator = EOF;
1451 
1452 	      shell_input_line[i] = '\0';
1453 	      break;
1454 	    }
1455 
1456 	  shell_input_line[i++] = c;
1457 
1458 	  if (c == '\n')
1459 	    {
1460 	      shell_input_line[--i] = '\0';
1461 	      current_command_line_count++;
1462 	      break;
1463 	    }
1464 	}
1465       shell_input_line_index = 0;
1466       shell_input_line_len = i;		/* == strlen (shell_input_line) */
1467 
1468 #if defined (HISTORY)
1469       if (interactive && shell_input_line && shell_input_line[0])
1470 	{
1471 	  char *expansions;
1472 
1473 	  expansions = pre_process_line (shell_input_line, 1, 1);
1474 
1475 	  free (shell_input_line);
1476 	  shell_input_line = expansions;
1477 	  shell_input_line_len = shell_input_line ?
1478 				 strlen (shell_input_line) :
1479 				 0;
1480 	  if (!shell_input_line_len)
1481 	    current_command_line_count--;
1482 
1483 	  /* We have to force the xrealloc below because we don't know the
1484 	     true allocated size of shell_input_line anymore. */
1485 	  shell_input_line_size = shell_input_line_len;
1486 	}
1487 #endif /* HISTORY */
1488 
1489       if (shell_input_line)
1490 	{
1491 	  /* Lines that signify the end of the shell's input should not be
1492 	     echoed. */
1493 	  if (echo_input_at_read && (shell_input_line[0] ||
1494 				     shell_input_line_terminator != EOF))
1495 	    fprintf (stderr, "%s\n", shell_input_line);
1496 	}
1497       else
1498 	{
1499 	  shell_input_line_size = 0;
1500 	  prompt_string_pointer = &current_prompt_string;
1501 	  prompt_again ();
1502 	  goto restart_read;
1503 	}
1504 
1505       /* Add the newline to the end of this string, iff the string does
1506 	 not already end in an EOF character.  */
1507       if (shell_input_line_terminator != EOF)
1508 	{
1509 	  l = shell_input_line_len;	/* was a call to strlen */
1510 
1511 	  if (l + 3 > shell_input_line_size)
1512 	    shell_input_line = xrealloc (shell_input_line,
1513 					1 + (shell_input_line_size += 2));
1514 
1515 	  shell_input_line[l] = '\n';
1516 	  shell_input_line[l + 1] = '\0';
1517 	}
1518     }
1519 
1520   c = shell_input_line[shell_input_line_index];
1521 
1522   if (c)
1523     shell_input_line_index++;
1524 
1525   if (c == '\\' && remove_quoted_newline &&
1526       shell_input_line[shell_input_line_index] == '\n')
1527     {
1528 	prompt_again ();
1529 	goto restart_read_next_line;
1530     }
1531 
1532 #if defined (ALIAS)
1533   /* If C is NULL, we have reached the end of the current input string.  If
1534      pushed_string_list is non-empty, it's time to pop to the previous string
1535      because we have fully consumed the result of the last alias expansion.
1536      Do it transparently; just return the next character of the string popped
1537      to. */
1538   if (!c && (pushed_string_list != (STRING_SAVER *)NULL))
1539     {
1540       pop_string ();
1541       c = shell_input_line[shell_input_line_index];
1542       if (c)
1543 	shell_input_line_index++;
1544     }
1545 #endif /* ALIAS */
1546 
1547   if (!c && shell_input_line_terminator == EOF)
1548     {
1549       if (shell_input_line_index != 0)
1550 	return ('\n');
1551       else
1552 	return (EOF);
1553     }
1554 
1555   return ((unsigned char)c);
1556 }
1557 
1558 /* Put C back into the input for the shell. */
1559 static void
shell_ungetc(c)1560 shell_ungetc (c)
1561      int c;
1562 {
1563   if (shell_input_line && shell_input_line_index)
1564     shell_input_line[--shell_input_line_index] = c;
1565 }
1566 
1567 /* Discard input until CHARACTER is seen. */
1568 static void
discard_until(character)1569 discard_until (character)
1570      int character;
1571 {
1572   int c;
1573 
1574   while ((c = shell_getc (0)) != EOF && c != character)
1575     ;
1576 
1577   if (c != EOF)
1578     shell_ungetc (c);
1579 }
1580 
1581 /* Place to remember the token.  We try to keep the buffer
1582    at a reasonable size, but it can grow. */
1583 static char *token = (char *)NULL;
1584 
1585 /* Current size of the token buffer. */
1586 static int token_buffer_size = 0;
1587 
1588 void
execute_prompt_command(command)1589 execute_prompt_command (command)
1590      char *command;
1591 {
1592   Function *temp_last, *temp_this;
1593   char *last_lastarg;
1594   int temp_exit_value, temp_eof_encountered;
1595 
1596   temp_last = last_shell_builtin;
1597   temp_this = this_shell_builtin;
1598   temp_exit_value = last_command_exit_value;
1599   temp_eof_encountered = eof_encountered;
1600   last_lastarg = get_string_value ("_");
1601   if (last_lastarg)
1602     last_lastarg = savestring (last_lastarg);
1603 
1604   parse_and_execute (savestring (command), "PROMPT_COMMAND", 0);
1605 
1606   last_shell_builtin = temp_last;
1607   this_shell_builtin = temp_this;
1608   last_command_exit_value = temp_exit_value;
1609   eof_encountered = temp_eof_encountered;
1610 
1611   bind_variable ("_", last_lastarg);
1612   FREE (last_lastarg);
1613 
1614   if (token_to_read == '\n')
1615     token_to_read = 0;
1616 }
1617 
1618 /* Command to read_token () explaining what we want it to do. */
1619 #define READ 0
1620 #define RESET 1
1621 #define prompt_is_ps1 \
1622       (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
1623 
1624 /* Function for yyparse to call.  yylex keeps track of
1625    the last two tokens read, and calls read_token.  */
1626 
yylex()1627 yylex ()
1628 {
1629   if (interactive && (!current_token || current_token == '\n'))
1630     {
1631       /* Before we print a prompt, we might have to check mailboxes.
1632 	 We do this only if it is time to do so. Notice that only here
1633 	 is the mail alarm reset; nothing takes place in check_mail ()
1634 	 except the checking of mail.  Please don't change this. */
1635       if (prompt_is_ps1 && time_to_check_mail ())
1636 	{
1637 	  check_mail ();
1638 	  reset_mail_timer ();
1639 	}
1640 
1641       /* Avoid printing a prompt if we're not going to read anything, e.g.
1642 	 after resetting the parser with read_token (RESET). */
1643       if (token_to_read == 0 && interactive)
1644 	prompt_again ();
1645     }
1646 
1647   token_before_that = last_read_token;
1648   last_read_token = current_token;
1649   current_token = read_token (READ);
1650   return (current_token);
1651 }
1652 
1653 /* Called from shell.c when Control-C is typed at top level.  Or
1654    by the error rule at top level. */
reset_parser()1655 reset_parser ()
1656 {
1657   read_token (RESET);
1658 }
1659 
1660 /* When non-zero, we have read the required tokens
1661    which allow ESAC to be the next one read. */
1662 static int allow_esac_as_next = 0;
1663 
1664 /* When non-zero, accept single '{' as a token itself. */
1665 static int allow_open_brace = 0;
1666 
1667 /* DELIMITERS is a stack of the nested delimiters that we have
1668    encountered so far. */
1669 static char *delimiters = (char *)NULL;
1670 
1671 /* Offset into the stack of delimiters. */
1672 int delimiter_depth = 0;
1673 
1674 /* How many slots are allocated to DELIMITERS. */
1675 static int delimiter_space = 0;
1676 
1677 void
gather_here_documents()1678 gather_here_documents ()
1679 {
1680   int r = 0;
1681   while (need_here_doc)
1682     {
1683       make_here_document (redir_stack[r++]);
1684       need_here_doc--;
1685     }
1686 }
1687 
1688 /* Macro for accessing the top delimiter on the stack.  Returns the
1689    delimiter or zero if none. */
1690 #define current_delimiter() \
1691   (delimiter_depth ? delimiters[delimiter_depth - 1] : 0)
1692 
1693 #define push_delimiter(character) \
1694   do \
1695     { \
1696       if (delimiter_depth + 2 > delimiter_space) \
1697 	delimiters = xrealloc \
1698 	  (delimiters, (delimiter_space += 10) * sizeof (char)); \
1699       delimiters[delimiter_depth] = character; \
1700       delimiter_depth++; \
1701     } \
1702   while (0)
1703 
1704 /* When non-zero, an open-brace used to create a group is awaiting a close
1705    brace partner. */
1706 static int open_brace_awaiting_satisfaction = 0;
1707 
1708 #define command_token_position(token) \
1709   (((token) == ASSIGNMENT_WORD) || \
1710    ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
1711 
1712 #define assignment_acceptable(token) command_token_position(token) && \
1713 					(in_case_pattern_list == 0)
1714 
1715 /* Check to see if TOKEN is a reserved word and return the token
1716    value if it is. */
1717 #define CHECK_FOR_RESERVED_WORD(tok) \
1718   do { \
1719     if (!dollar_present && !quoted && \
1720 	reserved_word_acceptable (last_read_token)) \
1721       { \
1722 	int i; \
1723 	for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
1724 	  if (STREQ (tok, word_token_alist[i].word)) \
1725 	    { \
1726 	      if (in_case_pattern_list && (word_token_alist[i].token != ESAC)) \
1727 		break; \
1728 \
1729 	      if (word_token_alist[i].token == ESAC) \
1730 		in_case_pattern_list = 0; \
1731 \
1732 	      if (word_token_alist[i].token == '{') \
1733 		open_brace_awaiting_satisfaction++; \
1734 \
1735 	      if (word_token_alist[i].token == '}' && open_brace_awaiting_satisfaction) \
1736 		open_brace_awaiting_satisfaction--; \
1737 \
1738 	      return (word_token_alist[i].token); \
1739 	    } \
1740       } \
1741   } while (0)
1742 
1743 /* Read the next token.  Command can be READ (normal operation) or
1744    RESET (to normalize state). */
1745 static int
read_token(command)1746 read_token (command)
1747      int command;
1748 {
1749   int character;		/* Current character. */
1750   int peek_char;		/* Temporary look-ahead character. */
1751   int result;			/* The thing to return. */
1752   WORD_DESC *the_word;		/* The value for YYLVAL when a WORD is read. */
1753 
1754   if (token_buffer_size < TOKEN_DEFAULT_GROW_SIZE)
1755     {
1756       FREE (token);
1757       token = xmalloc (token_buffer_size = TOKEN_DEFAULT_GROW_SIZE);
1758     }
1759 
1760   if (command == RESET)
1761     {
1762       delimiter_depth = 0;	/* No delimiters found so far. */
1763       open_brace_awaiting_satisfaction = 0;
1764       in_case_pattern_list = 0;
1765 
1766 #if defined (ALIAS)
1767       if (pushed_string_list)
1768 	{
1769 	  free_string_list ();
1770 	  pushed_string_list = (STRING_SAVER *)NULL;
1771 	}
1772 
1773       if (expanded_token_stack)
1774 	{
1775 	  free_expansion_stack ();
1776 	  expanded_token_stack = (EXPANSION_SAVER *)NULL;
1777 	}
1778 
1779       expand_next_token = 0;
1780 #endif /* ALIAS */
1781 
1782       if (shell_input_line)
1783 	{
1784 	  free (shell_input_line);
1785 	  shell_input_line = (char *)NULL;
1786 	  shell_input_line_size = shell_input_line_index = 0;
1787 	}
1788       last_read_token = '\n';
1789       token_to_read = '\n';
1790       return ('\n');
1791     }
1792 
1793   if (token_to_read)
1794     {
1795       int rt = token_to_read;
1796       token_to_read = 0;
1797       return (rt);
1798     }
1799 
1800 #if defined (ALIAS)
1801   /* If we hit read_token () and there are no saved strings on the
1802      pushed_string_list, then we are no longer currently expanding a
1803      token.  This can't be done in pop_stream, because pop_stream
1804      may pop the stream before the current token has finished being
1805      completely expanded (consider what happens when we alias foo to foo,
1806      and then try to expand it). */
1807   if (!pushed_string_list && expanded_token_stack)
1808     {
1809       free_expansion_stack ();
1810       expanded_token_stack = (EXPANSION_SAVER *)NULL;
1811     }
1812 
1813   /* This is a place to jump back to once we have successfully expanded a
1814      token with an alias and pushed the string with push_string () */
1815  re_read_token:
1816 
1817 #endif /* ALIAS */
1818 
1819   /* Read a single word from input.  Start by skipping blanks. */
1820   while ((character = shell_getc (1)) != EOF && whitespace (character));
1821 
1822   if (character == EOF)
1823     {
1824       EOF_Reached = 1;
1825       return (yacc_EOF);
1826     }
1827 
1828   if (character == '#' && (!interactive || interactive_comments))
1829     {
1830       /* A comment.  Discard until EOL or EOF, and then return a newline. */
1831       discard_until ('\n');
1832       shell_getc (0);
1833 
1834       /* If we're about to return an unquoted newline, we can go and collect
1835 	 the text of any pending here documents. */
1836       if (need_here_doc)
1837         gather_here_documents ();
1838 
1839 #if defined (ALIAS)
1840       expand_next_token = 0;
1841 #endif /* ALIAS */
1842 
1843       return ('\n');
1844     }
1845 
1846   if (character == '\n')
1847     {
1848       /* If we're about to return an unquoted newline, we can go and collect
1849 	 the text of any pending here document. */
1850       if (need_here_doc)
1851 	gather_here_documents ();
1852 
1853 #if defined (ALIAS)
1854       expand_next_token = 0;
1855 #endif /* ALIAS */
1856 
1857       return (character);
1858     }
1859 
1860   if (member (character, "()<>;&|"))
1861     {
1862 #if defined (ALIAS)
1863       /* Turn off alias tokenization iff this character sequence would
1864 	 not leave us ready to read a command. */
1865       if (character == '<' || character == '>')
1866 	expand_next_token = 0;
1867 #endif /* ALIAS */
1868 
1869       /* Please note that the shell does not allow whitespace to
1870 	 appear in between tokens which are character pairs, such as
1871 	 "<<" or ">>".  I believe this is the correct behaviour. */
1872       if (character == (peek_char = shell_getc (1)))
1873 	{
1874 	  switch (character)
1875 	    {
1876 	      /* If '<' then we could be at "<<" or at "<<-".  We have to
1877 		 look ahead one more character. */
1878 	    case '<':
1879 	      peek_char = shell_getc (1);
1880 	      if (peek_char == '-')
1881 		return (LESS_LESS_MINUS);
1882 	      else
1883 		{
1884 		  shell_ungetc (peek_char);
1885 		  return (LESS_LESS);
1886 		}
1887 
1888 	    case '>':
1889 	      return (GREATER_GREATER);
1890 
1891 	    case ';':
1892 	      in_case_pattern_list = 1;
1893 #if defined (ALIAS)
1894 	      expand_next_token = 0;
1895 #endif /* ALIAS */
1896 	      return (SEMI_SEMI);
1897 
1898 	    case '&':
1899 	      return (AND_AND);
1900 
1901 	    case '|':
1902 	      return (OR_OR);
1903 	    }
1904 	}
1905       else
1906 	{
1907 	  if (peek_char == '&')
1908 	    {
1909 	      switch (character)
1910 		{
1911 		case '<': return (LESS_AND);
1912 		case '>': return (GREATER_AND);
1913 		}
1914 	    }
1915 	  if (character == '<' && peek_char == '>')
1916 	    return (LESS_GREATER);
1917 	  if (character == '>' && peek_char == '|')
1918 	    return (GREATER_BAR);
1919 	  if (peek_char == '>' && character == '&')
1920 	    return (AND_GREATER);
1921 	}
1922       shell_ungetc (peek_char);
1923 
1924       /* If we look like we are reading the start of a function
1925 	 definition, then let the reader know about it so that
1926 	 we will do the right thing with `{'. */
1927       if (character == ')' &&
1928 	  last_read_token == '(' && token_before_that == WORD)
1929 	{
1930 	  allow_open_brace = 1;
1931 #if defined (ALIAS)
1932 	  expand_next_token = 0;
1933 #endif /* ALIAS */
1934 	}
1935 
1936       if (in_case_pattern_list && (character == ')'))
1937 	in_case_pattern_list = 0;
1938 
1939 #if defined (PROCESS_SUBSTITUTION)
1940       /* Check for the constructs which introduce process substitution.
1941 	 Shells running in `posix mode' don't do process substitution. */
1942       if (posixly_correct ||
1943 	  (((character == '>' || character == '<') && peek_char == '(') == 0))
1944 #endif /* PROCESS_SUBSTITUTION */
1945 	return (character);
1946     }
1947 
1948   /* Hack <&- (close stdin) case. */
1949   if (character == '-')
1950     {
1951       switch (last_read_token)
1952 	{
1953 	case LESS_AND:
1954 	case GREATER_AND:
1955 	  return (character);
1956 	}
1957     }
1958 
1959   /* Okay, if we got this far, we have to read a word.  Read one,
1960      and then check it against the known ones. */
1961   {
1962     /* Index into the token that we are building. */
1963     int token_index = 0;
1964 
1965     /* ALL_DIGITS becomes zero when we see a non-digit. */
1966     int all_digits = digit (character);
1967 
1968     /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
1969     int dollar_present = 0;
1970 
1971     /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
1972     int quoted = 0;
1973 
1974     /* Non-zero means to ignore the value of the next character, and just
1975        to add it no matter what. */
1976     int pass_next_character = 0;
1977 
1978     /* Non-zero means parsing a dollar-paren construct.  It is the count of
1979        un-quoted closes we need to see. */
1980     int dollar_paren_level = 0;
1981 
1982     /* Non-zero means parsing a dollar-bracket construct ($[...]).  It is
1983        the count of un-quoted `]' characters we need to see. */
1984     int dollar_bracket_level = 0;
1985 
1986     /* Non-zero means parsing a `${' construct.  It is the count of
1987        un-quoted `}' we need to see. */
1988     int dollar_brace_level = 0;
1989 
1990     /* A level variable for parsing '${ ... }' constructs inside of double
1991        quotes. */
1992     int delimited_brace_level = 0;
1993 
1994     /* A boolean variable denoting whether or not we are currently parsing
1995        a double-quoted string embedded in a $( ) or ${ } construct. */
1996     int embedded_quoted_string = 0;
1997 
1998     /* Another level variable.  This one is for dollar_parens inside of
1999        double-quotes. */
2000     int delimited_paren_level = 0;
2001 
2002     /* The current delimiting character. */
2003     int cd;
2004 
2005     for (;;)
2006       {
2007 	if (character == EOF)
2008 	  goto got_token;
2009 
2010 	if (pass_next_character)
2011 	  {
2012 	    pass_next_character = 0;
2013 	    goto got_character;
2014 	  }
2015 
2016 	cd = current_delimiter ();
2017 
2018 	if (cd && character == '\\' && cd != '\'')
2019 	  {
2020 	    peek_char = shell_getc (0);
2021 	    if (peek_char != '\\')
2022 	      shell_ungetc (peek_char);
2023 	    else
2024 	      {
2025 		token[token_index++] = character;
2026 		goto got_character;
2027 	      }
2028 	  }
2029 
2030 	/* Handle backslashes.  Quote lots of things when not inside of
2031 	   double-quotes, quote some things inside of double-quotes. */
2032 
2033 	if (character == '\\' && (!delimiter_depth || cd != '\''))
2034 	  {
2035 	    peek_char = shell_getc (0);
2036 
2037 	    /* Backslash-newline is ignored in all cases excepting
2038 	       when quoted with single quotes. */
2039 	    if (peek_char == '\n')
2040 	      {
2041 		character = '\n';
2042 		goto next_character;
2043 	      }
2044 	    else
2045 	      {
2046 		shell_ungetc (peek_char);
2047 
2048 		/* If the next character is to be quoted, do it now. */
2049 		if (!cd || cd == '`' ||
2050 		    (cd == '"' && member (peek_char, slashify_in_quotes)))
2051 		  {
2052 		    pass_next_character++;
2053 		    quoted = 1;
2054 		    goto got_character;
2055 		  }
2056 	      }
2057 	  }
2058 
2059 	/* This is a hack, in its present form.  If a backquote substitution
2060 	   appears within double quotes, everything within the backquotes
2061 	   should be read as part of a single word.  Jesus.  Now I see why
2062 	   Korn introduced the $() form. */
2063 	if (delimiter_depth && (cd == '"') && (character == '`'))
2064 	  {
2065 	    push_delimiter (character);
2066 	    goto got_character;
2067 	  }
2068 
2069 	cd = current_delimiter ();		/* XXX - may not need */
2070 	if (delimiter_depth)
2071 	  {
2072 	    if (character == cd)
2073 	      {
2074 	      	/* If we see a double quote while parsing a double-quoted
2075 		  $( ) or ${ }, and we have not seen ) or }, respectively,
2076 	      	   note that we are in the middle of reading an embedded
2077 		   quoted string. */
2078 		if ((delimited_paren_level || delimited_brace_level) &&
2079 		    (character == '"'))
2080 		  {
2081 		    embedded_quoted_string = !embedded_quoted_string;
2082 		    goto got_character;
2083 		  }
2084 
2085 		delimiter_depth--;
2086 		goto got_character;
2087 	      }
2088 	  }
2089 
2090 	if (cd != '\'')
2091 	  {
2092 #if defined (PROCESS_SUBSTITUTION)
2093 	    if (character == '$' || character == '<' || character == '>')
2094 #else
2095 	    if (character == '$')
2096 #endif /* !PROCESS_SUBSTITUTION */
2097 	      {
2098 	      	/* If we're in the middle of parsing a $( ) or ${ }
2099 	      	   construct with an embedded quoted string, don't
2100 	      	   bother looking at this character any further. */
2101 	      	if (embedded_quoted_string)
2102 	      	  goto got_character;
2103 
2104 		peek_char = shell_getc (1);
2105 		shell_ungetc (peek_char);
2106 		if (peek_char == '(')
2107 		  {
2108 		    if (!delimiter_depth)
2109 		      dollar_paren_level++;
2110 		    else
2111 		      delimited_paren_level++;
2112 
2113 		    pass_next_character++;
2114 		    goto got_character;
2115 		  }
2116 		else if (peek_char == '[' && character == '$')
2117 		  {
2118 		    if (!delimiter_depth)
2119 		      dollar_bracket_level++;
2120 
2121 		    pass_next_character++;
2122 		    goto got_character;
2123 		  }
2124 		/* This handles ${...} constructs. */
2125 		else if (peek_char == '{' && character == '$')
2126 		  {
2127 		    if (!delimiter_depth)
2128 		      dollar_brace_level++;
2129 		    else
2130 		      delimited_brace_level++;
2131 
2132 		    pass_next_character++;
2133 		    goto got_character;
2134 		  }
2135 	      }
2136 
2137 	    /* If we are parsing a $() or $[] construct, we need to balance
2138 	       parens and brackets inside the construct.  This whole function
2139 	       could use a rewrite. */
2140 	    if (character == '(' && !embedded_quoted_string)
2141 	      {
2142 		if (delimiter_depth && delimited_paren_level)
2143 		  delimited_paren_level++;
2144 
2145 		if (!delimiter_depth && dollar_paren_level)
2146 		  dollar_paren_level++;
2147 	      }
2148 
2149 	    if (character == '[')
2150 	      {
2151 		if (!delimiter_depth && dollar_bracket_level)
2152 		  dollar_bracket_level++;
2153 	      }
2154 
2155 	    if (character == '{' && !embedded_quoted_string)
2156 	      {
2157 	      	if (delimiter_depth && delimited_brace_level)
2158 	      	  delimited_brace_level++;
2159 
2160 	      	if (!delimiter_depth && dollar_brace_level)
2161 	      	  dollar_brace_level++;
2162 	      }
2163 
2164 	    /* This code needs to take into account whether we are inside a
2165 	       case statement pattern list, and whether this paren is supposed
2166 	       to terminate it (hey, it could happen).  It's not as simple
2167 	       as just using in_case_pattern_list, because we're not parsing
2168 	       anything while we're reading a $( ) construct.  Maybe we
2169 	       should move that whole mess into the yacc parser. */
2170 	    if (character == ')' && !embedded_quoted_string)
2171 	      {
2172 		if (delimiter_depth && delimited_paren_level)
2173 		  delimited_paren_level--;
2174 
2175 		if (!delimiter_depth && dollar_paren_level)
2176 		  {
2177 		    dollar_paren_level--;
2178 		    goto got_character;
2179 		  }
2180 	      }
2181 
2182 	    if (character == ']')
2183 	      {
2184 		if (!delimiter_depth && dollar_bracket_level)
2185 		  {
2186 		    dollar_bracket_level--;
2187 		    goto got_character;
2188 		  }
2189 	      }
2190 
2191 	    if (character == '}' && !embedded_quoted_string)
2192 	      {
2193 		if (delimiter_depth && delimited_brace_level)
2194 		  delimited_brace_level--;
2195 
2196 		if (!delimiter_depth && dollar_brace_level)
2197 		  {
2198 		    dollar_brace_level--;
2199 		    goto got_character;
2200 		  }
2201 	      }
2202 	  }
2203 
2204 	if (!dollar_paren_level && !dollar_bracket_level &&
2205 	    !dollar_brace_level && !delimiter_depth &&
2206 	    member (character, " \t\n;&()|<>"))
2207 	  {
2208 	    shell_ungetc (character);
2209 	    goto got_token;
2210 	  }
2211 
2212 	if (!delimiter_depth)
2213 	  {
2214 	    if (character == '"' || character == '`' || character == '\'')
2215 	      {
2216 		push_delimiter (character);
2217 
2218 		quoted = 1;
2219 		goto got_character;
2220 	      }
2221 	  }
2222 
2223 	if (all_digits)
2224 	  all_digits = digit (character);
2225 	if (character == '$')
2226 	  dollar_present = 1;
2227 
2228       got_character:
2229 
2230 	if (character == CTLESC || character == CTLNUL)
2231 	  token[token_index++] = CTLESC;
2232 
2233 	token[token_index++] = character;
2234 
2235 	if (token_index == (token_buffer_size - 1))
2236 	  {
2237 	    token_buffer_size += TOKEN_DEFAULT_GROW_SIZE;
2238 	    token = xrealloc (token, token_buffer_size);
2239 	  }
2240 	next_character:
2241 	if (character == '\n' && interactive && bash_input.type != st_string)
2242 	  prompt_again ();
2243 
2244 	/* We want to remove quoted newlines (that is, a \<newline> pair)
2245 	   unless we are within single quotes or pass_next_character is
2246 	   set (the shell equivalent of literal-next). */
2247 	character = shell_getc
2248 	  ((current_delimiter () != '\'') && (!pass_next_character));
2249       }
2250 
2251   got_token:
2252 
2253     token[token_index] = '\0';
2254 
2255     if ((delimiter_depth || dollar_paren_level || dollar_bracket_level) &&
2256 	character == EOF)
2257       {
2258 	char reporter = '\0';
2259 
2260 	if (!delimiter_depth)
2261 	  {
2262 	    if (dollar_paren_level)
2263 	      reporter = ')';
2264 	    else if (dollar_bracket_level)
2265 	      reporter = ']';
2266 	  }
2267 
2268 	if (!reporter)
2269 	  reporter = current_delimiter ();
2270 
2271 	report_error ("unexpected EOF while looking for `%c'", reporter);
2272 	return (-1);
2273       }
2274 
2275     if (all_digits)
2276       {
2277 	/* Check to see what thing we should return.  If the last_read_token
2278 	   is a `<', or a `&', or the character which ended this token is
2279 	   a '>' or '<', then, and ONLY then, is this input token a NUMBER.
2280 	   Otherwise, it is just a word, and should be returned as such. */
2281 
2282 	if (character == '<' || character == '>' ||
2283 	    last_read_token == LESS_AND || last_read_token == GREATER_AND)
2284 	  {
2285 	    yylval.number = atoi (token);
2286 	    return (NUMBER);
2287 	  }
2288       }
2289 
2290     /* Handle special case.  IN is recognized if the last token
2291        was WORD and the token before that was FOR or CASE. */
2292     if ((last_read_token == WORD) &&
2293 #if defined (SELECT_COMMAND)
2294 	((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
2295 #else
2296 	((token_before_that == FOR) || (token_before_that == CASE)) &&
2297 #endif
2298 	(token[0] == 'i' && token[1] == 'n' && !token[2]))
2299       {
2300 	if (token_before_that == CASE)
2301 	  {
2302 	    in_case_pattern_list = 1;
2303 	    allow_esac_as_next++;
2304 	  }
2305 	return (IN);
2306       }
2307 
2308     /* Ditto for DO in the FOR case. */
2309 #if defined (SELECT_COMMAND)
2310     if ((last_read_token == WORD) && ((token_before_that == FOR) || (token_before_that == SELECT)) &&
2311 #else
2312     if ((last_read_token == WORD) && (token_before_that == FOR) &&
2313 #endif
2314 	(token[0] == 'd' && token[1] == 'o' && !token[2]))
2315       return (DO);
2316 
2317     /* Ditto for ESAC in the CASE case.
2318        Specifically, this handles "case word in esac", which is a legal
2319        construct, certainly because someone will pass an empty arg to the
2320        case construct, and we don't want it to barf.  Of course, we should
2321        insist that the case construct has at least one pattern in it, but
2322        the designers disagree. */
2323     if (allow_esac_as_next)
2324       {
2325 	allow_esac_as_next--;
2326 	if (STREQ (token, "esac"))
2327 	  {
2328 	    in_case_pattern_list = 0;
2329 	    return (ESAC);
2330 	  }
2331       }
2332 
2333     /* Ditto for `{' in the FUNCTION case. */
2334     if (allow_open_brace)
2335       {
2336 	allow_open_brace = 0;
2337 	if (token[0] == '{' && !token[1])
2338 	  {
2339 	    open_brace_awaiting_satisfaction++;
2340 	    return ('{');
2341 	  }
2342       }
2343 
2344     if (posixly_correct)
2345       CHECK_FOR_RESERVED_WORD (token);
2346 
2347 #if defined (ALIAS)
2348     /* OK, we have a token.  Let's try to alias expand it, if (and only if)
2349        it's eligible.
2350 
2351        It is eligible for expansion if the shell is in interactive mode, and
2352        the token is unquoted and the last token read was a command
2353        separator (or expand_next_token is set), and we are currently
2354        processing an alias (pushed_string_list is non-empty) and this
2355        token is not the same as the current or any previously
2356        processed alias.
2357 
2358        Special cases that disqualify:
2359 	 In a pattern list in a case statement (in_case_pattern_list). */
2360     if (interactive_shell && !quoted && !in_case_pattern_list &&
2361 	(expand_next_token || command_token_position (last_read_token)))
2362       {
2363 	char *alias_expand_word (), *expanded;
2364 
2365 	if (expanded_token_stack && token_has_been_expanded (token))
2366 	  goto no_expansion;
2367 
2368 	expanded = alias_expand_word (token);
2369 	if (expanded)
2370 	  {
2371 	    int len = strlen (expanded), expand_next;
2372 
2373 	    /* Erase the current token. */
2374 	    token_index = 0;
2375 
2376 	    expand_next = (expanded[len - 1] == ' ') ||
2377 			  (expanded[len - 1] == '\t');
2378 
2379 	    push_string (expanded, expand_next, token);
2380 	    goto re_read_token;
2381 	  }
2382 	else
2383 	  /* This is an eligible token that does not have an expansion. */
2384 no_expansion:
2385 	  expand_next_token = 0;
2386       }
2387     else
2388       {
2389 	expand_next_token = 0;
2390       }
2391 #endif /* ALIAS */
2392 
2393     if (!posixly_correct)
2394       CHECK_FOR_RESERVED_WORD (token);
2395 
2396     /* What if we are attempting to satisfy an open-brace grouper? */
2397     if (open_brace_awaiting_satisfaction && token[0] == '}' && !token[1])
2398       {
2399 	open_brace_awaiting_satisfaction--;
2400 	return ('}');
2401       }
2402 
2403     the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
2404     the_word->word = xmalloc (1 + token_index);
2405     strcpy (the_word->word, token);
2406     the_word->dollar_present = dollar_present;
2407     the_word->quoted = quoted;
2408     the_word->assignment = assignment (token);
2409 
2410     yylval.word = the_word;
2411     result = WORD;
2412 
2413     /* A word is an assignment if it appears at the beginning of a
2414        simple command, or after another assignment word.  This is
2415        context-dependent, so it cannot be handled in the grammar. */
2416     if (assignment_acceptable (last_read_token) && the_word->assignment)
2417       result = ASSIGNMENT_WORD;
2418 
2419     if (last_read_token == FUNCTION)
2420       allow_open_brace = 1;
2421   }
2422   return (result);
2423 }
2424 
2425 /* Return 1 if TOKEN is a token that after being read would allow
2426    a reserved word to be seen, else 0. */
2427 static int
reserved_word_acceptable(token)2428 reserved_word_acceptable (token)
2429      int token;
2430 {
2431 #if 0
2432   if (member (token, "\n;()|&{") ||
2433 #else
2434   if (token == '\n' || token == ';' || token == '(' || token == ')' ||
2435       token == '|' || token == '&' || token == '{' ||
2436 #endif
2437       token == '}' ||			/* XXX */
2438       token == AND_AND ||
2439       token == BANG ||
2440       token == DO ||
2441       token == ELIF ||
2442       token == ELSE ||
2443       token == FI ||
2444       token == IF ||
2445       token == OR_OR ||
2446       token == SEMI_SEMI ||
2447       token == THEN ||
2448       token == UNTIL ||
2449       token == WHILE ||
2450       token == DONE ||		/* XXX these two are experimental */
2451       token == ESAC ||
2452       token == 0)
2453     return (1);
2454   else
2455     return (0);
2456 }
2457 
2458 /* Return the index of TOKEN in the alist of reserved words, or -1 if
2459    TOKEN is not a shell reserved word. */
2460 int
find_reserved_word(token)2461 find_reserved_word (token)
2462      char *token;
2463 {
2464   int i;
2465   for (i = 0; word_token_alist[i].word != (char *)NULL; i++)
2466     if (STREQ (token, word_token_alist[i].word))
2467       return i;
2468   return -1;
2469 }
2470 
2471 #if defined (READLINE)
2472 /* Called after each time readline is called.  This insures that whatever
2473    the new prompt string is gets propagated to readline's local prompt
2474    variable. */
2475 static void
reset_readline_prompt()2476 reset_readline_prompt ()
2477 {
2478   if (prompt_string_pointer)
2479     {
2480       char *temp_prompt;
2481 
2482       temp_prompt = *prompt_string_pointer
2483 			? decode_prompt_string (*prompt_string_pointer)
2484 			: (char *)NULL;
2485 
2486       if (temp_prompt == 0)
2487 	{
2488 	  temp_prompt = xmalloc (1);
2489 	  temp_prompt[0] = '\0';
2490 	}
2491 
2492       FREE (current_readline_prompt);
2493 
2494       current_readline_prompt = temp_prompt;
2495     }
2496 }
2497 #endif /* READLINE */
2498 
2499 #if defined (HISTORY)
2500 /* A list of tokens which can be followed by newlines, but not by
2501    semi-colons.  When concatenating multiple lines of history, the
2502    newline separator for such tokens is replaced with a space. */
2503 static int no_semi_successors[] = {
2504   '\n', '{', '(', ')', ';', '&', '|',
2505   CASE, DO, ELSE, IF, IN, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR,
2506   0
2507 };
2508 
2509 /* If we are not within a delimited expression, try to be smart
2510    about which separators can be semi-colons and which must be
2511    newlines. */
2512 char *
history_delimiting_chars()2513 history_delimiting_chars ()
2514 {
2515   if (!delimiter_depth)
2516     {
2517       register int i;
2518 
2519       for (i = 0; no_semi_successors[i]; i++)
2520 	{
2521 	  if (token_before_that == no_semi_successors[i])
2522 	    return (" ");
2523 	}
2524       return ("; ");
2525     }
2526   else
2527     return ("\n");
2528 }
2529 #endif /* HISTORY */
2530 
2531 /* Issue a prompt, or prepare to issue a prompt when the next character
2532    is read. */
2533 static void
prompt_again()2534 prompt_again ()
2535 {
2536   char *temp_prompt;
2537 
2538   if (!interactive)	/* XXX */
2539     return;
2540 
2541   ps1_prompt = get_string_value ("PS1");
2542   ps2_prompt = get_string_value ("PS2");
2543 
2544   if (!prompt_string_pointer)
2545     prompt_string_pointer = &ps1_prompt;
2546 
2547   temp_prompt = (*prompt_string_pointer)
2548 			? decode_prompt_string (*prompt_string_pointer)
2549 			: (char *)NULL;
2550 
2551   if (temp_prompt == 0)
2552     {
2553       temp_prompt = xmalloc (1);
2554       temp_prompt[0] = '\0';
2555     }
2556 
2557   current_prompt_string = *prompt_string_pointer;
2558   prompt_string_pointer = &ps2_prompt;
2559 
2560 #if defined (READLINE)
2561   if (!no_line_editing)
2562     {
2563       FREE (current_readline_prompt);
2564       current_readline_prompt = temp_prompt;
2565     }
2566   else
2567 #endif	/* READLINE */
2568     {
2569       FREE (current_decoded_prompt);
2570       current_decoded_prompt = temp_prompt;
2571     }
2572 }
2573 
2574 static void
print_prompt()2575 print_prompt ()
2576 {
2577   fprintf (stderr, "%s", current_decoded_prompt);
2578   fflush (stderr);
2579 }
2580 
2581 /* Return a string which will be printed as a prompt.  The string
2582    may contain special characters which are decoded as follows:
2583 
2584 	\t	the time
2585 	\d	the date
2586 	\n	CRLF
2587 	\s	the name of the shell
2588 	\w	the current working directory
2589 	\W	the last element of PWD
2590 	\u	your username
2591 	\h	the hostname
2592 	\#	the command number of this command
2593 	\!	the history number of this command
2594 	\$	a $ or a # if you are root
2595 	\<octal> character code in octal
2596 	\\	a backslash
2597 */
2598 #define PROMPT_GROWTH 50
2599 char *
decode_prompt_string(string)2600 decode_prompt_string (string)
2601      char *string;
2602 {
2603   int result_size = PROMPT_GROWTH;
2604   int result_index = 0;
2605   char *result;
2606   int c;
2607   char *temp = (char *)NULL;
2608   WORD_LIST *list;
2609 
2610 #if defined (PROMPT_STRING_DECODE)
2611 
2612   result = xmalloc (PROMPT_GROWTH);
2613   result[0] = 0;
2614 
2615   while (c = *string++)
2616     {
2617       if (posixly_correct && c == '!')
2618 	{
2619 	  if (*string == '!')
2620 	    {
2621 	      temp = savestring ("!");
2622 	      goto add_string;
2623 	    }
2624 	  else
2625 	    {
2626 #if !defined (HISTORY)
2627 		temp = savestring ("1");
2628 #else /* HISTORY */
2629 		temp = itos (history_number ());
2630 #endif /* HISTORY */
2631 		string--;	/* add_string increments string again. */
2632 		goto add_string;
2633 	    }
2634 	}
2635       if (c == '\\')
2636 	{
2637 	  c = *string;
2638 
2639 	  switch (c)
2640 	    {
2641 	    case '0':
2642 	    case '1':
2643 	    case '2':
2644 	    case '3':
2645 	    case '4':
2646 	    case '5':
2647 	    case '6':
2648 	    case '7':
2649 	      {
2650 		char octal_string[4];
2651 		int n;
2652 
2653 		strncpy (octal_string, string, 3);
2654 		octal_string[3] = '\0';
2655 
2656 		n = read_octal (octal_string);
2657 		temp = xmalloc (3);
2658 
2659 		if (n == CTLESC || n == CTLNUL)
2660 		  {
2661 		    string += 3;
2662 		    temp[0] = CTLESC;
2663 		    temp[1] = n;
2664 		    temp[2] = '\0';
2665 		  }
2666 		else if (n == -1)
2667 		  {
2668 		    temp[0] = '\\';
2669 		    temp[1] = '\0';
2670 		  }
2671 		else
2672 		  {
2673 		    string += 3;
2674 		    temp[0] = n;
2675 		    temp[1] = '\0';
2676 		  }
2677 
2678 		c = 0;
2679 		goto add_string;
2680 	      }
2681 
2682 	    case 't':
2683 	    case 'd':
2684 	      /* Make the current time/date into a string. */
2685 	      {
2686 		time_t the_time = time (0);
2687 		char *ttemp = ctime (&the_time);
2688 		temp = savestring (ttemp);
2689 
2690 		if (c == 't')
2691 		  {
2692 		    strcpy (temp, temp + 11);
2693 		    temp[8] = '\0';
2694 		  }
2695 		else
2696 		  temp[10] = '\0';
2697 
2698 		goto add_string;
2699 	      }
2700 
2701 	    case 'n':
2702 	      if (!no_line_editing)
2703 		temp = savestring ("\r\n");
2704 	      else
2705 		temp = savestring ("\n");
2706 	      goto add_string;
2707 
2708 	    case 's':
2709 	      {
2710 		temp = base_pathname (shell_name);
2711 		temp = savestring (temp);
2712 		goto add_string;
2713 	      }
2714 
2715 	    case 'w':
2716 	    case 'W':
2717 	      {
2718 		/* Use the value of PWD because it is much more effecient. */
2719 #define EFFICIENT
2720 #if defined(EFFICIENT)
2721 		char *polite_directory_format (), t_string[MAXPATHLEN];
2722 
2723 		temp = get_string_value ("PWD");
2724 
2725 		if (!temp)
2726 		  getwd (t_string);
2727 		else
2728 		  strcpy (t_string, temp);
2729 #else
2730 		getwd (t_string);
2731 #endif	/* EFFICIENT */
2732 
2733 		if (c == 'W')
2734 		  {
2735 		    char *dir = (char *)strrchr (t_string, '/');
2736 		    if (dir && dir != t_string)
2737 		      strcpy (t_string, dir + 1);
2738 		    temp = savestring (t_string);
2739 		  }
2740 		else
2741 		  temp = savestring (polite_directory_format (t_string));
2742 		goto add_string;
2743 	      }
2744 
2745 	    case 'u':
2746 	      {
2747 		temp = savestring (current_user.user_name);
2748 		goto add_string;
2749 	      }
2750 
2751 	    case 'h':
2752 	      {
2753 		char *t_string;
2754 
2755 		temp = savestring (current_host_name);
2756 		if (t_string = (char *)strchr (temp, '.'))
2757 		  *t_string = '\0';
2758 		goto add_string;
2759 	      }
2760 
2761 	    case '#':
2762 	      {
2763 		temp = itos (current_command_number);
2764 		goto add_string;
2765 	      }
2766 
2767 	    case '!':
2768 	      {
2769 #if !defined (HISTORY)
2770 		temp = savestring ("1");
2771 #else /* HISTORY */
2772 		temp = itos (history_number ());
2773 #endif /* HISTORY */
2774 		goto add_string;
2775 	      }
2776 
2777 	    case '$':
2778 	      temp = savestring (geteuid () == 0 ? "#" : "$");
2779 	      goto add_string;
2780 
2781 #if defined (READLINE)
2782 	    case '[':
2783 	    case ']':
2784 	      temp = xmalloc(3);
2785 	      temp[0] = '\001';
2786 	      temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
2787 	      temp[2] = '\0';
2788 	      goto add_string;
2789 #endif
2790 
2791 	    case '\\':
2792 	      temp = savestring ("\\");
2793 	      goto add_string;
2794 
2795 	    default:
2796 	      temp = savestring ("\\ ");
2797 	      temp[1] = c;
2798 
2799 	    add_string:
2800 	      if (c)
2801 		string++;
2802 	      result =
2803 		sub_append_string (temp, result, &result_index, &result_size);
2804 	      temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
2805 	      result[result_index] = '\0';
2806 	      break;
2807 	    }
2808 	}
2809       else
2810 	{
2811 	  while (3 + result_index > result_size)
2812 	    result = xrealloc (result, result_size += PROMPT_GROWTH);
2813 
2814 	  result[result_index++] = c;
2815 	  result[result_index] = '\0';
2816 	}
2817     }
2818 #else /* !PROMPT_STRING_DECODE */
2819   result = savestring (string);
2820 #endif /* !PROMPT_STRING_DECODE */
2821 
2822   /* Perform variable and parameter expansion and command substitution on
2823      the prompt string. */
2824   list = expand_string_unsplit (result, 1);
2825   free (result);
2826   result = string_list (list);
2827   dispose_words (list);
2828 
2829   return (result);
2830 }
2831 
2832 /* Report a syntax error, and restart the parser.  Call here for fatal
2833    errors. */
yyerror()2834 yyerror ()
2835 {
2836   report_syntax_error ((char *)NULL);
2837   reset_parser ();
2838 }
2839 
2840 /* Report a syntax error with line numbers, etc.
2841    Call here for recoverable errors.  If you have a message to print,
2842    then place it in MESSAGE, otherwise pass NULL and this will figure
2843    out an appropriate message for you. */
2844 static void
report_syntax_error(message)2845 report_syntax_error (message)
2846      char *message;
2847 {
2848   if (message)
2849     {
2850       if (!interactive)
2851 	{
2852 	  char *name = bash_input.name ? bash_input.name : "stdin";
2853 	  report_error ("%s: line %d: `%s'", name, line_number, message);
2854 	}
2855       else
2856 	{
2857 	  if (EOF_Reached)
2858 	    EOF_Reached = 0;
2859 	  report_error ("%s", message);
2860 	}
2861 
2862       last_command_exit_value = EX_USAGE;
2863       return;
2864     }
2865 
2866   if (shell_input_line && *shell_input_line)
2867     {
2868       char *t = shell_input_line;
2869       register int i = shell_input_line_index;
2870       int token_end = 0;
2871 
2872       if (!t[i] && i)
2873 	i--;
2874 
2875       while (i && (t[i] == ' ' || t[i] == '\t' || t[i] == '\n'))
2876 	i--;
2877 
2878       if (i)
2879 	token_end = i + 1;
2880 
2881       while (i && !member (t[i], " \n\t;|&"))
2882 	i--;
2883 
2884       while (i != token_end && member (t[i], " \t\n"))
2885 	i++;
2886 
2887       if (token_end)
2888 	{
2889 	  char *error_token;
2890 	  error_token = xmalloc (1 + (token_end - i));
2891 	  strncpy (error_token, t + i, token_end - i);
2892 	  error_token[token_end - i] = '\0';
2893 
2894 	  report_error ("syntax error near unexpected token `%s'", error_token);
2895 	  free (error_token);
2896 	}
2897       else if ((i == 0) && (token_end == 0))	/* a 1-character token */
2898 	{
2899 	  char etoken[2];
2900 	  etoken[0] = t[i];
2901 	  etoken[1] = '\0';
2902 
2903 	  report_error ("syntax error near unexpected token `%s'", etoken);
2904 	}
2905 
2906       if (!interactive)
2907 	{
2908 	  char *temp = savestring (shell_input_line);
2909 	  char *name = bash_input.name ? bash_input.name : "stdin";
2910 	  int l = strlen (temp);
2911 
2912 	  while (l && temp[l - 1] == '\n')
2913 	    temp[--l] = '\0';
2914 
2915 	  report_error ("%s: line %d: `%s'", name, line_number, temp);
2916 	  free (temp);
2917 	}
2918     }
2919   else
2920     {
2921       char *name, *msg;
2922       if (!interactive)
2923 	name = bash_input.name ? bash_input.name : "stdin";
2924       if (EOF_Reached)
2925 	msg = "syntax error: unexpected end of file";
2926       else
2927 	msg = "syntax error";
2928       if (!interactive)
2929 	report_error ("%s: line %d: %s", name, line_number, msg);
2930       else
2931 	{
2932 	  /* This file uses EOF_Reached only for error reporting
2933 	     when the shell is interactive.  Other mechanisms are
2934 	     used to decide whether or not to exit. */
2935 	  EOF_Reached = 0;
2936 	  report_error (msg);
2937 	}
2938     }
2939   last_command_exit_value = EX_USAGE;
2940 }
2941 
2942 /* ??? Needed function. ??? We have to be able to discard the constructs
2943    created during parsing.  In the case of error, we want to return
2944    allocated objects to the memory pool.  In the case of no error, we want
2945    to throw away the information about where the allocated objects live.
2946    (dispose_command () will actually free the command. */
discard_parser_constructs(error_p)2947 discard_parser_constructs (error_p)
2948      int error_p;
2949 {
2950 }
2951 
2952 /* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
2953 
2954 /* A flag denoting whether or not ignoreeof is set. */
2955 int ignoreeof = 0;
2956 
2957 /* The number of times that we have encountered an EOF character without
2958    another character intervening.  When this gets above the limit, the
2959    shell terminates. */
2960 int eof_encountered = 0;
2961 
2962 /* The limit for eof_encountered. */
2963 int eof_encountered_limit = 10;
2964 
2965 /* If we have EOF as the only input unit, this user wants to leave
2966    the shell.  If the shell is not interactive, then just leave.
2967    Otherwise, if ignoreeof is set, and we haven't done this the
2968    required number of times in a row, print a message. */
2969 static void
handle_eof_input_unit()2970 handle_eof_input_unit ()
2971 {
2972   if (interactive)
2973     {
2974       /* shell.c may use this to decide whether or not to write out the
2975 	 history, among other things.  We use it only for error reporting
2976 	 in this file. */
2977       if (EOF_Reached)
2978 	EOF_Reached = 0;
2979 
2980       /* If the user wants to "ignore" eof, then let her do so, kind of. */
2981       if (ignoreeof)
2982 	{
2983 	  if (eof_encountered < eof_encountered_limit)
2984 	    {
2985 	      fprintf (stderr, "Use \"%s\" to leave the shell.\n",
2986 		       login_shell ? "logout" : "exit");
2987 	      eof_encountered++;
2988 	      /* Reset the prompt string to be $PS1. */
2989 	      prompt_string_pointer = (char **)NULL;
2990 	      prompt_again ();
2991 	      last_read_token = current_token = '\n';
2992 	      return;
2993 	    }
2994 	}
2995 
2996       /* In this case EOF should exit the shell.  Do it now. */
2997       reset_parser ();
2998       exit_builtin ((WORD_LIST *)NULL);
2999     }
3000   else
3001     {
3002       /* We don't write history files, etc., for non-interactive shells. */
3003       EOF_Reached = 1;
3004     }
3005 }
3006