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