]> git.ipfire.org Git - thirdparty/bash.git/blame_incremental - make_cmd.c
Bash-5.3: updated translations and gettext gmo files
[thirdparty/bash.git] / make_cmd.c
... / ...
CommitLineData
1/* make_cmd.c -- Functions for making instances of the various
2 parser constructs. */
3
4/* Copyright (C) 1989-2023 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "config.h"
23
24#include <stdio.h>
25#include "bashtypes.h"
26#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
27# include <sys/file.h>
28#endif
29#include "filecntl.h"
30#include "bashansi.h"
31#if defined (HAVE_UNISTD_H)
32# include <unistd.h>
33#endif
34
35#include "bashintl.h"
36
37#include "shell.h"
38#include "execute_cmd.h"
39#include "parser.h"
40#include "flags.h"
41#include "input.h"
42
43#if defined (JOB_CONTROL)
44#include "jobs.h"
45#endif
46
47#include "shmbutil.h"
48
49int here_doc_first_line = 0;
50
51/* Object caching */
52sh_obj_cache_t wdcache = {0, 0, 0};
53sh_obj_cache_t wlcache = {0, 0, 0};
54
55#define WDCACHESIZE 128
56#define WLCACHESIZE 128
57
58static COMMAND *make_for_or_select (enum command_type, WORD_DESC *, WORD_LIST *, COMMAND *, int);
59#if defined (ARITH_FOR_COMMAND)
60static WORD_LIST *make_arith_for_expr (char *);
61#endif
62static COMMAND *make_until_or_while (enum command_type, COMMAND *, COMMAND *);
63
64void
65cmd_init (void)
66{
67 ocache_create (wdcache, WORD_DESC, WDCACHESIZE);
68 ocache_create (wlcache, WORD_LIST, WLCACHESIZE);
69}
70
71WORD_DESC *
72alloc_word_desc (void)
73{
74 WORD_DESC *temp;
75
76 ocache_alloc (wdcache, WORD_DESC, temp);
77 temp->flags = 0;
78 temp->word = 0;
79 return temp;
80}
81
82WORD_DESC *
83make_bare_word (const char *string)
84{
85 WORD_DESC *temp;
86
87 temp = alloc_word_desc ();
88
89 if (*string)
90 temp->word = savestring (string);
91 else
92 {
93 temp->word = (char *)xmalloc (1);
94 temp->word[0] = '\0';
95 }
96
97 return (temp);
98}
99
100WORD_DESC *
101make_word_flags (WORD_DESC *w, const char *string)
102{
103 register int i;
104 size_t slen;
105 DECLARE_MBSTATE;
106
107 i = 0;
108 slen = strlen (string);
109 while (i < slen)
110 {
111 switch (string[i])
112 {
113 case '$':
114 w->flags |= W_HASDOLLAR;
115 break;
116 case '\\':
117 break; /* continue the loop */
118 case '\'':
119 case '`':
120 case '"':
121 w->flags |= W_QUOTED;
122 break;
123 }
124
125 ADVANCE_CHAR (string, slen, i);
126 }
127
128 return (w);
129}
130
131WORD_DESC *
132make_word (const char *string)
133{
134 WORD_DESC *temp;
135
136 temp = make_bare_word (string);
137 return (make_word_flags (temp, string));
138}
139
140WORD_DESC *
141make_word_from_token (int token)
142{
143 char tokenizer[2];
144
145 tokenizer[0] = token;
146 tokenizer[1] = '\0';
147
148 return (make_word (tokenizer));
149}
150
151WORD_LIST *
152make_word_list (WORD_DESC *word, WORD_LIST *wlink)
153{
154 WORD_LIST *temp;
155
156 ocache_alloc (wlcache, WORD_LIST, temp);
157
158 temp->word = word;
159 temp->next = wlink;
160 return (temp);
161}
162
163COMMAND *
164make_command (enum command_type type, SIMPLE_COM *pointer)
165{
166 COMMAND *temp;
167
168 temp = (COMMAND *)xmalloc (sizeof (COMMAND));
169 temp->type = type;
170 temp->value.Simple = pointer;
171 temp->value.Simple->flags = temp->flags = 0;
172 temp->redirects = (REDIRECT *)NULL;
173 return (temp);
174}
175
176COMMAND *
177command_connect (COMMAND *com1, COMMAND *com2, int connector)
178{
179 CONNECTION *temp;
180
181 temp = (CONNECTION *)xmalloc (sizeof (CONNECTION));
182 temp->connector = connector;
183 temp->first = com1;
184 temp->second = com2;
185 return (make_command (cm_connection, (SIMPLE_COM *)temp));
186}
187
188static COMMAND *
189make_for_or_select (enum command_type type, WORD_DESC *name, WORD_LIST *map_list, COMMAND *action, int lineno)
190{
191 FOR_COM *temp;
192
193 temp = (FOR_COM *)xmalloc (sizeof (FOR_COM));
194 temp->flags = 0;
195 temp->name = name;
196 temp->line = lineno;
197 temp->map_list = map_list;
198 temp->action = action;
199 return (make_command (type, (SIMPLE_COM *)temp));
200}
201
202COMMAND *
203make_for_command (WORD_DESC *name, WORD_LIST *map_list, COMMAND *action, int lineno)
204{
205 return (make_for_or_select (cm_for, name, map_list, action, lineno));
206}
207
208COMMAND *
209make_select_command (WORD_DESC *name, WORD_LIST *map_list, COMMAND *action, int lineno)
210{
211#if defined (SELECT_COMMAND)
212 return (make_for_or_select (cm_select, name, map_list, action, lineno));
213#else
214 set_exit_status (2);
215 return ((COMMAND *)NULL);
216#endif
217}
218
219#if defined (ARITH_FOR_COMMAND)
220static WORD_LIST *
221make_arith_for_expr (char *s)
222{
223 WORD_LIST *result;
224 WORD_DESC *wd;
225
226 if (s == 0 || *s == '\0')
227 return ((WORD_LIST *)NULL);
228 wd = make_word (s);
229 wd->flags |= W_NOGLOB|W_NOSPLIT|W_QUOTED|W_NOTILDE|W_NOPROCSUB; /* no word splitting or globbing */
230 result = make_word_list (wd, (WORD_LIST *)NULL);
231 return result;
232}
233#endif
234
235/* Note that this function calls dispose_words on EXPRS, since it doesn't
236 use the word list directly. We free it here rather than at the caller
237 because no other function in this file requires that the caller free
238 any arguments. */
239COMMAND *
240make_arith_for_command (WORD_LIST *exprs, COMMAND *action, int lineno)
241{
242#if defined (ARITH_FOR_COMMAND)
243 ARITH_FOR_COM *temp;
244 WORD_LIST *init, *test, *step;
245 char *s, *t, *start;
246 int nsemi, i;
247
248 init = test = step = (WORD_LIST *)NULL;
249 /* Parse the string into the three component sub-expressions. */
250 start = t = s = exprs->word->word;
251 for (nsemi = 0; ;)
252 {
253 /* skip whitespace at the start of each sub-expression. */
254 while (whitespace (*s))
255 s++;
256 start = s;
257 /* skip to the semicolon or EOS */
258 i = skip_to_delim (start, 0, ";", SD_NOJMP|SD_NOPROCSUB);
259 s = start + i;
260
261 t = (i > 0) ? substring (start, 0, i) : (char *)NULL;
262
263 nsemi++;
264 switch (nsemi)
265 {
266 case 1:
267 init = make_arith_for_expr (t);
268 break;
269 case 2:
270 test = make_arith_for_expr (t);
271 break;
272 case 3:
273 step = make_arith_for_expr (t);
274 break;
275 }
276
277 FREE (t);
278 if (*s == '\0')
279 break;
280 s++; /* skip over semicolon */
281 }
282
283 if (nsemi != 3)
284 {
285 if (nsemi < 3)
286 parser_error (lineno, _("syntax error: arithmetic expression required"));
287 else
288 parser_error (lineno, _("syntax error: `;' unexpected"));
289 parser_error (lineno, _("syntax error: `((%s))'"), exprs->word->word);
290 free (init);
291 free (test);
292 free (step);
293 set_exit_status (2);
294 return ((COMMAND *)NULL);
295 }
296
297 temp = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM));
298 temp->flags = 0;
299 temp->line = lineno;
300 temp->init = init ? init : make_arith_for_expr ("1");
301 temp->test = test ? test : make_arith_for_expr ("1");
302 temp->step = step ? step : make_arith_for_expr ("1");
303 temp->action = action;
304
305 dispose_words (exprs);
306 return (make_command (cm_arith_for, (SIMPLE_COM *)temp));
307#else
308 dispose_words (exprs);
309 set_exit_status (2);
310 return ((COMMAND *)NULL);
311#endif /* ARITH_FOR_COMMAND */
312}
313
314COMMAND *
315make_group_command (COMMAND *command)
316{
317 GROUP_COM *temp;
318
319 temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
320 temp->command = command;
321 return (make_command (cm_group, (SIMPLE_COM *)temp));
322}
323
324COMMAND *
325make_case_command (WORD_DESC *word, PATTERN_LIST *clauses, int lineno)
326{
327 CASE_COM *temp;
328
329 temp = (CASE_COM *)xmalloc (sizeof (CASE_COM));
330 temp->flags = 0;
331 temp->line = lineno;
332 temp->word = word;
333 temp->clauses = REVERSE_LIST (clauses, PATTERN_LIST *);
334 return (make_command (cm_case, (SIMPLE_COM *)temp));
335}
336
337PATTERN_LIST *
338make_pattern_list (WORD_LIST *patterns, COMMAND *action)
339{
340 PATTERN_LIST *temp;
341
342 temp = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
343 temp->patterns = REVERSE_LIST (patterns, WORD_LIST *);
344 temp->action = action;
345 temp->next = NULL;
346 temp->flags = 0;
347 return (temp);
348}
349
350COMMAND *
351make_if_command (COMMAND *test, COMMAND *true_case, COMMAND *false_case)
352{
353 IF_COM *temp;
354
355 temp = (IF_COM *)xmalloc (sizeof (IF_COM));
356 temp->flags = 0;
357 temp->test = test;
358 temp->true_case = true_case;
359 temp->false_case = false_case;
360 return (make_command (cm_if, (SIMPLE_COM *)temp));
361}
362
363static COMMAND *
364make_until_or_while (enum command_type which, COMMAND *test, COMMAND *action)
365{
366 WHILE_COM *temp;
367
368 temp = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
369 temp->flags = 0;
370 temp->test = test;
371 temp->action = action;
372 return (make_command (which, (SIMPLE_COM *)temp));
373}
374
375COMMAND *
376make_while_command (COMMAND *test, COMMAND *action)
377{
378 return (make_until_or_while (cm_while, test, action));
379}
380
381COMMAND *
382make_until_command (COMMAND *test, COMMAND *action)
383{
384 return (make_until_or_while (cm_until, test, action));
385}
386
387COMMAND *
388make_arith_command (WORD_LIST *exp)
389{
390#if defined (DPAREN_ARITHMETIC)
391 COMMAND *command;
392 ARITH_COM *temp;
393
394 command = (COMMAND *)xmalloc (sizeof (COMMAND));
395 command->value.Arith = temp = (ARITH_COM *)xmalloc (sizeof (ARITH_COM));
396
397 temp->flags = 0;
398 temp->line = line_number;
399 temp->exp = exp;
400
401 command->type = cm_arith;
402 command->redirects = (REDIRECT *)NULL;
403 command->flags = 0;
404
405 return (command);
406#else
407 set_exit_status (2);
408 return ((COMMAND *)NULL);
409#endif
410}
411
412#if defined (COND_COMMAND)
413struct cond_com *
414make_cond_node (int type, WORD_DESC *op, struct cond_com *left, struct cond_com *right)
415{
416 COND_COM *temp;
417
418 temp = (COND_COM *)xmalloc (sizeof (COND_COM));
419 temp->flags = 0;
420 temp->line = line_number;
421 temp->type = type;
422 temp->op = op;
423 temp->left = left;
424 temp->right = right;
425
426 return (temp);
427}
428#endif
429
430COMMAND *
431make_cond_command (COND_COM *cond_node)
432{
433#if defined (COND_COMMAND)
434 COMMAND *command;
435
436 command = (COMMAND *)xmalloc (sizeof (COMMAND));
437 command->value.Cond = cond_node;
438
439 command->type = cm_cond;
440 command->redirects = (REDIRECT *)NULL;
441 command->flags = 0;
442 command->line = cond_node ? cond_node->line : 0;
443
444 return (command);
445#else
446 set_exit_status (2);
447 return ((COMMAND *)NULL);
448#endif
449}
450
451COMMAND *
452make_bare_simple_command (int line)
453{
454 COMMAND *command;
455 SIMPLE_COM *temp;
456
457 command = (COMMAND *)xmalloc (sizeof (COMMAND));
458 command->value.Simple = temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
459
460 temp->flags = 0;
461 temp->line = line;
462 temp->words = (WORD_LIST *)NULL;
463 temp->redirects = (REDIRECT *)NULL;
464
465 command->type = cm_simple;
466 command->redirects = (REDIRECT *)NULL;
467 command->flags = 0;
468
469 return (command);
470}
471
472/* Return a command which is the connection of the word or redirection
473 in ELEMENT, and the command * or NULL in COMMAND. */
474COMMAND *
475make_simple_command (ELEMENT element, COMMAND *command, int line)
476{
477 /* If we are starting from scratch, then make the initial command
478 structure. Also note that we have to fill in all the slots, since
479 malloc doesn't return zeroed space. */
480 if (command == 0)
481 {
482 command = make_bare_simple_command (line);
483 parser_state |= PST_REDIRLIST;
484 }
485
486 if (element.word)
487 {
488 command->value.Simple->words = make_word_list (element.word, command->value.Simple->words);
489 parser_state &= ~PST_REDIRLIST;
490 }
491 else if (element.redirect)
492 {
493 REDIRECT *r = element.redirect;
494 /* Due to the way <> is implemented, there may be more than a single
495 redirection in element.redirect. We just follow the chain as far
496 as it goes, and hook onto the end. */
497 while (r->next)
498 r = r->next;
499 r->next = command->value.Simple->redirects;
500 command->value.Simple->redirects = element.redirect;
501 }
502
503 return (command);
504}
505
506/* Because we are Bourne compatible, we read the input for this
507 << or <<- redirection now, from wherever input is coming from.
508 We store the input read into a WORD_DESC. Replace the text of
509 the redirectee.word with the new input text. If <<- is on,
510 then remove leading TABS from each line. */
511void
512make_here_document (REDIRECT *temp, int lineno)
513{
514 int kill_leading;
515 size_t redir_len;
516 char *redir_word, *document, *full_line;
517 int document_index, delim_unquoted;
518 size_t document_size;
519
520 if (temp->instruction != r_deblank_reading_until &&
521 temp->instruction != r_reading_until)
522 {
523 internal_error (_("make_here_document: bad instruction type %d"), temp->instruction);
524 return;
525 }
526
527 kill_leading = temp->instruction == r_deblank_reading_until;
528
529 full_line = document = (char *)NULL;
530 document_index = 0;
531 document_size = 0;
532
533 delim_unquoted = (temp->redirectee.filename->flags & W_QUOTED) == 0;
534
535 /* Quote removal is the only expansion performed on the delimiter
536 for here documents, making it an extremely special case. */
537 /* "If any part of word is quoted, the delimiter shall be formed by
538 performing quote removal on word." */
539 if (delim_unquoted == 0)
540 redir_word = string_quote_removal (temp->redirectee.filename->word, 0);
541 else
542 redir_word = savestring (temp->redirectee.filename->word);
543
544 /* redirection_expand will return NULL if the expansion results in
545 multiple words or no words. Check for that here, and just abort
546 this here document if it does. */
547 if (redir_word)
548 redir_len = strlen (redir_word);
549 else
550 {
551 temp->here_doc_eof = (char *)xmalloc (1);
552 temp->here_doc_eof[0] = '\0';
553 goto document_done;
554 }
555
556 free (temp->redirectee.filename->word);
557 temp->here_doc_eof = redir_word;
558
559 /* Read lines from wherever lines are coming from.
560 For each line read, if kill_leading, then kill the
561 leading tab characters.
562 If the line matches redir_word exactly, then we have
563 manufactured the document. Otherwise, add the line to the
564 list of lines in the document. */
565
566 /* If the here-document delimiter was quoted, the lines should
567 be read verbatim from the input. If it was not quoted, we
568 need to perform backslash-quoted newline removal. */
569 while (full_line = read_secondary_line (delim_unquoted))
570 {
571 register char *line;
572 size_t len;
573
574 here_doc_first_line = 0;
575 line = full_line;
576
577 /* if read_secondary_line uses shell_getc, that handles incrementing
578 line_number where necessary. */
579 if (heredoc_string == 0)
580 line_number++;
581
582 /* If set -v is in effect, echo the line read. read_secondary_line/
583 read_a_line leaves the newline at the end, so don't print another. */
584 if (echo_input_at_read)
585 fprintf (stderr, "%s", line);
586
587 if (kill_leading && *line)
588 {
589 /* Hack: To be compatible with some Bourne shells, we
590 check the word before stripping the whitespace. This
591 is a hack, though. */
592 if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
593 break;
594
595 while (*line == '\t')
596 line++;
597 }
598
599 if (*line == 0)
600 continue;
601
602 if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
603 break;
604
605 /* Backwards compatibility here */
606 if (STREQN (line, redir_word, redir_len) && (parser_state & PST_EOFTOKEN) && shell_eof_token && strchr (line+redir_len, shell_eof_token))
607 {
608 shell_ungets (line + redir_len);
609 full_line = 0;
610 break;
611 }
612
613 len = strlen (line);
614 if (len + document_index >= document_size)
615 {
616 document_size = document_size ? 2 * (document_size + len) : len + 2;
617 document = (char *)xrealloc (document, document_size);
618 }
619
620 /* len is guaranteed to be > 0 because of the check for line
621 being an empty string before the call to strlen. */
622 FASTCOPY (line, document + document_index, len);
623 document_index += len;
624 }
625
626 if (full_line == 0)
627 internal_warning (_("here-document at line %d delimited by end-of-file (wanted `%s')"), lineno, redir_word);
628
629document_done:
630 if (document)
631 document[document_index] = '\0';
632 else
633 {
634 document = (char *)xmalloc (1);
635 document[0] = '\0';
636 }
637 temp->redirectee.filename->word = document;
638 here_doc_first_line = 0;
639}
640
641/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION.
642 INSTRUCTION is the instruction type, SOURCE is a file descriptor,
643 and DEST is a file descriptor or a WORD_DESC *. */
644REDIRECT *
645make_redirection (REDIRECTEE source, enum r_instruction instruction, REDIRECTEE dest_and_filename, int flags)
646{
647 REDIRECT *temp;
648 WORD_DESC *w;
649 size_t wlen;
650 intmax_t lfd;
651
652 temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
653
654 /* First do the common cases. */
655 temp->redirector = source;
656 temp->redirectee = dest_and_filename;
657 temp->here_doc_eof = 0;
658 temp->instruction = instruction;
659 temp->flags = 0;
660 temp->rflags = flags;
661 temp->next = (REDIRECT *)NULL;
662
663 switch (instruction)
664 {
665
666 case r_output_direction: /* >foo */
667 case r_output_force: /* >| foo */
668 case r_err_and_out: /* &>filename */
669 temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
670 break;
671
672 case r_appending_to: /* >>foo */
673 case r_append_err_and_out: /* &>> filename */
674 temp->flags = O_APPEND | O_WRONLY | O_CREAT;
675 break;
676
677 case r_input_direction: /* <foo */
678 case r_inputa_direction: /* foo & makes this. */
679 temp->flags = O_RDONLY;
680 break;
681
682 case r_input_output: /* <>foo */
683 temp->flags = O_RDWR | O_CREAT;
684 break;
685
686 case r_deblank_reading_until: /* <<-foo */
687 case r_reading_until: /* << foo */
688 case r_reading_string: /* <<< foo */
689 case r_close_this: /* <&- */
690 case r_duplicating_input: /* 1<&2 */
691 case r_duplicating_output: /* 1>&2 */
692 break;
693
694 /* the parser doesn't pass these. */
695 case r_move_input: /* 1<&2- */
696 case r_move_output: /* 1>&2- */
697 case r_move_input_word: /* 1<&$foo- */
698 case r_move_output_word: /* 1>&$foo- */
699 break;
700
701 /* The way the lexer works we have to do this here. */
702 case r_duplicating_input_word: /* 1<&$foo */
703 case r_duplicating_output_word: /* 1>&$foo */
704 w = dest_and_filename.filename;
705 wlen = strlen (w->word) - 1;
706 if (w->word[wlen] == '-') /* Yuck */
707 {
708 w->word[wlen] = '\0';
709 if (all_digits (w->word) && valid_number (w->word, &lfd) && lfd == (int)lfd)
710 {
711 dispose_word (w);
712 temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input : r_move_output;
713 temp->redirectee.dest = lfd;
714 }
715 else
716 temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input_word : r_move_output_word;
717 }
718
719 break;
720
721 default:
722 programming_error (_("make_redirection: redirection instruction `%d' out of range"), instruction);
723 abort ();
724 break;
725 }
726 return (temp);
727}
728
729COMMAND *
730make_function_def (WORD_DESC *name, COMMAND *command, int lineno, int lstart)
731{
732 FUNCTION_DEF *temp;
733#if defined (ARRAY_VARS)
734 SHELL_VAR *bash_source_v;
735 ARRAY *bash_source_a;
736#endif
737
738 temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
739 temp->command = command;
740 temp->name = name;
741 temp->line = lineno;
742 temp->flags = 0;
743 command->line = lstart;
744
745 /* Information used primarily for debugging and error messages. */
746 temp->source_file = 0;
747#if defined (ARRAY_VARS)
748 GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
749 if (bash_source_a && array_num_elements (bash_source_a) > 0)
750 temp->source_file = array_reference (bash_source_a, 0);
751#endif
752 /* Assume that shell functions without a source file before the shell is
753 initialized come from the environment. Otherwise default to "main"
754 (usually functions being defined interactively) */
755 if (temp->source_file == 0)
756 {
757 if (shell_initialized == 0)
758 temp->source_file = "environment";
759 else if (interactive_shell)
760 temp->source_file = "main";
761 else if (interactive == 0) /* assume -c command */
762 temp->source_file = dollar_vars[0];
763 else
764 temp->source_file = shell_name; /* this clause is never hit */
765 }
766
767#if defined (DEBUGGER)
768 bind_function_def (name->word, temp, 0);
769#endif
770
771 temp->source_file = temp->source_file ? savestring (temp->source_file) : 0;
772
773 return (make_command (cm_function_def, (SIMPLE_COM *)temp));
774}
775
776COMMAND *
777make_subshell_command (COMMAND *command)
778{
779 SUBSHELL_COM *temp;
780
781 temp = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
782 temp->command = command;
783 temp->flags = CMD_WANT_SUBSHELL;
784 temp->line = line_number;
785 return (make_command (cm_subshell, (SIMPLE_COM *)temp));
786}
787
788COMMAND *
789make_coproc_command (char *name, COMMAND *command)
790{
791 COPROC_COM *temp;
792
793 temp = (COPROC_COM *)xmalloc (sizeof (COPROC_COM));
794 temp->name = savestring (name);
795 temp->command = command;
796 temp->flags = CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
797 return (make_command (cm_coproc, (SIMPLE_COM *)temp));
798}
799
800/* Reverse the word list and redirection list in the simple command
801 has just been parsed. It seems simpler to do this here the one
802 time then by any other method that I can think of. */
803COMMAND *
804clean_simple_command (COMMAND *command)
805{
806 if (command->type != cm_simple)
807 command_error ("clean_simple_command", CMDERR_BADTYPE, command->type, 0);
808 else
809 {
810 command->value.Simple->words =
811 REVERSE_LIST (command->value.Simple->words, WORD_LIST *);
812 command->value.Simple->redirects =
813 REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
814 }
815
816 parser_state &= ~PST_REDIRLIST;
817 return (command);
818}
819
820/* The Yacc grammar productions have a problem, in that they take a
821 list followed by an ampersand (`&') and do a simple command connection,
822 making the entire list effectively asynchronous, instead of just
823 the last command. This means that when the list is executed, all
824 the commands have stdin set to /dev/null when job control is not
825 active, instead of just the last. This is wrong, and needs fixing
826 up. This function takes the `&' and applies it to the last command
827 in the list. This is done only for lists connected by `;'; it makes
828 `;' bind `tighter' than `&'. */
829COMMAND *
830connect_async_list (COMMAND *command, COMMAND *command2, int connector)
831{
832 COMMAND *t, *t1, *t2;
833
834 t1 = command;
835 t = command->value.Connection->second;
836
837 if (!t || (command->flags & CMD_WANT_SUBSHELL) ||
838 command->value.Connection->connector != ';')
839 {
840 t = command_connect (command, command2, connector);
841 return t;
842 }
843
844 /* This is just defensive programming. The Yacc precedence rules
845 will generally hand this function a command where t points directly
846 to the command we want (e.g. given a ; b ; c ; d &, t1 will point
847 to the `a ; b ; c' list and t will be the `d'). We only want to do
848 this if the list is not being executed as a unit in the background
849 with `( ... )', so we have to check for CMD_WANT_SUBSHELL. That's
850 the only way to tell. */
851 while (((t->flags & CMD_WANT_SUBSHELL) == 0) && t->type == cm_connection &&
852 t->value.Connection->connector == ';')
853 {
854 t1 = t;
855 t = t->value.Connection->second;
856 }
857 /* Now we have t pointing to the last command in the list, and
858 t1->value.Connection->second == t. */
859 t2 = command_connect (t, command2, connector);
860 t1->value.Connection->second = t2;
861 return command;
862}