source: vendor/bash/3.1-p17/make_cmd.c

Last change on this file was 3231, checked in by bird, 18 years ago

eol style.

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