~ubuntu-branches/ubuntu/trusty/maloc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/vsh/bash.y

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-06-29 15:21:06 UTC
  • Revision ID: james.westby@ubuntu.com-20060629152106-kyqdw6qlc3vmqum3
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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. */
 
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
 
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
 
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. */
 
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. */
 
774
yy_ungetc (c)
 
775
     int c;
 
776
{
 
777
  return (*(bash_input.ungetter)) (c);
 
778
}
 
779
 
 
780
#if defined (BUFFERED_INPUT)
 
781
int
 
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
 
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
 
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  
 
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
 
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
 
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
 
923
yy_string_unget (c)
 
924
     int c;
 
925
{
 
926
  *(--bash_input.location.string) = c;
 
927
  return (c);
 
928
}
 
929
 
 
930
void
 
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
 
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
 
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
 
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
 
 
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
 
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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 *
 
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 *
 
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
 
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
 
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
 
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
 
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
 
 
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. */
 
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
 
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
 
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
 
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
 
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
 
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 *
 
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
 
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
 
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 *
 
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. */
 
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
 
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. */
 
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
 
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
}