Imported from ../bash-2.01.tar.gz.
[platform/upstream/bash.git] / copy_cmd.c
1 /* copy_command.c -- copy a COMMAND structure.  This is needed
2    primarily for making function definitions, but I'm not sure
3    that anyone else will need it.  */
4
5 /* Copyright (C) 1987,1991 Free Software Foundation, Inc.
6
7    This file is part of GNU Bash, the Bourne Again SHell.
8
9    Bash is free software; you can redistribute it and/or modify it
10    under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 1, or (at your option)
12    any later version.
13
14    Bash is distributed in the hope that it will be useful, but WITHOUT
15    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17    License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with Bash; see the file COPYING.  If not, write to the Free
21    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include "config.h"
24
25 #include <stdio.h>
26
27 #if defined (HAVE_UNISTD_H)
28 #  include <unistd.h>
29 #endif
30
31 #include "shell.h"
32
33 WORD_DESC *
34 copy_word (word)
35      WORD_DESC *word;
36 {
37   WORD_DESC *new_word;
38
39   new_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
40   FASTCOPY ((char *)word, (char *)new_word, sizeof (WORD_DESC));
41   new_word->word = savestring (word->word);
42   return (new_word);
43 }
44
45 /* Copy the chain of words in LIST.  Return a pointer to
46    the new chain. */
47 WORD_LIST *
48 copy_word_list (list)
49      WORD_LIST *list;
50 {
51   WORD_LIST *new_list, *temp;
52
53   for (new_list = (WORD_LIST *)NULL; list; list = list->next)
54     {
55       temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
56       temp->next = new_list;
57       new_list = temp;
58       new_list->word = copy_word (list->word);
59     }
60   return (REVERSE_LIST (new_list, WORD_LIST *));
61 }
62
63 static PATTERN_LIST *
64 copy_case_clause (clause)
65      PATTERN_LIST *clause;
66 {
67   PATTERN_LIST *new_clause;
68
69   new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
70   new_clause->patterns = copy_word_list (clause->patterns);
71   new_clause->action = copy_command (clause->action);
72   return (new_clause);
73 }
74
75 static PATTERN_LIST *
76 copy_case_clauses (clauses)
77      PATTERN_LIST *clauses;
78 {
79   PATTERN_LIST *new_list, *new_clause;
80
81   for (new_list = (PATTERN_LIST *)NULL; clauses; clauses = clauses->next)
82     {
83       new_clause = copy_case_clause (clauses);
84       new_clause->next = new_list;
85       new_list = new_clause;
86     }
87   return (REVERSE_LIST (new_list, PATTERN_LIST *));
88 }
89
90 /* Copy a single redirect. */
91 REDIRECT *
92 copy_redirect (redirect)
93      REDIRECT *redirect;
94 {
95   REDIRECT *new_redirect;
96
97   new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT));
98   FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT)));
99   switch (redirect->instruction)
100     {
101     case r_reading_until:
102     case r_deblank_reading_until:
103       new_redirect->here_doc_eof = savestring (redirect->here_doc_eof);
104       /*FALLTHROUGH*/
105     case r_appending_to:
106     case r_output_direction:
107     case r_input_direction:
108     case r_inputa_direction:
109     case r_err_and_out:
110     case r_input_output:
111     case r_output_force:
112     case r_duplicating_input_word:
113     case r_duplicating_output_word:
114       new_redirect->redirectee.filename = copy_word (redirect->redirectee.filename);
115       break;
116     case r_duplicating_input:
117     case r_duplicating_output:
118     case r_close_this:
119       break;
120     }
121   return (new_redirect);
122 }
123
124 REDIRECT *
125 copy_redirects (list)
126      REDIRECT *list;
127 {
128   REDIRECT *new_list, *temp;
129
130   for (new_list = (REDIRECT *)NULL; list; list = list->next)
131     {
132       temp = copy_redirect (list);
133       temp->next = new_list;
134       new_list = temp;
135     }
136   return (REVERSE_LIST (new_list, REDIRECT *));
137 }
138
139 static FOR_COM *
140 copy_for_command (com)
141      FOR_COM *com;
142 {
143   FOR_COM *new_for;
144
145   new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM));
146   new_for->flags = com->flags;
147   new_for->name = copy_word (com->name);
148   new_for->map_list = copy_word_list (com->map_list);
149   new_for->action = copy_command (com->action);
150   return (new_for);
151 }
152
153 static GROUP_COM *
154 copy_group_command (com)
155      GROUP_COM *com;
156 {
157   GROUP_COM *new_group;
158
159   new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
160   new_group->command = copy_command (com->command);
161   return (new_group);
162 }
163
164 static CASE_COM *
165 copy_case_command (com)
166      CASE_COM *com;
167 {
168   CASE_COM *new_case;
169
170   new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM));
171   new_case->flags = com->flags;
172   new_case->word = copy_word (com->word);
173   new_case->clauses = copy_case_clauses (com->clauses);
174   return (new_case);
175 }
176
177 static WHILE_COM *
178 copy_while_command (com)
179      WHILE_COM *com;
180 {
181   WHILE_COM *new_while;
182
183   new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
184   new_while->flags = com->flags;
185   new_while->test = copy_command (com->test);
186   new_while->action = copy_command (com->action);
187   return (new_while);
188 }
189
190 static IF_COM *
191 copy_if_command (com)
192      IF_COM *com;
193 {
194   IF_COM *new_if;
195
196   new_if = (IF_COM *)xmalloc (sizeof (IF_COM));
197   new_if->flags = com->flags;
198   new_if->test = copy_command (com->test);
199   new_if->true_case = copy_command (com->true_case);
200   new_if->false_case = copy_command (com->false_case);
201   return (new_if);
202 }
203
204 static SIMPLE_COM *
205 copy_simple_command (com)
206      SIMPLE_COM *com;
207 {
208   SIMPLE_COM *new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
209
210   new_simple->flags = com->flags;
211   new_simple->words = copy_word_list (com->words);
212   new_simple->redirects = copy_redirects (com->redirects);
213   new_simple->line = com->line;
214   return (new_simple);
215 }
216
217 static FUNCTION_DEF *
218 copy_function_def (com)
219      FUNCTION_DEF *com;
220 {
221   FUNCTION_DEF *new_def;
222
223   new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
224   new_def->name = copy_word (com->name);
225   new_def->command = copy_command (com->command);
226   return (new_def);
227 }
228
229 /* Copy the command structure in COMMAND.  Return a pointer to the
230    copy.  Don't you forget to dispose_command () on this pointer
231    later! */
232 COMMAND *
233 copy_command (command)
234      COMMAND *command;
235 {
236   COMMAND *new_command;
237
238   if (command == NULL)
239     return (command);
240
241   new_command = (COMMAND *)xmalloc (sizeof (COMMAND));
242   FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND));
243   new_command->flags = command->flags;
244   new_command->line = command->line;
245
246   if (command->redirects)
247     new_command->redirects = copy_redirects (command->redirects);
248
249   switch (command->type)
250     {
251       case cm_for:
252         new_command->value.For = copy_for_command (command->value.For);
253         break;
254
255 #if defined (SELECT_COMMAND)
256       case cm_select:
257         new_command->value.Select =
258           (SELECT_COM *)copy_for_command ((FOR_COM *)command->value.Select);
259         break;
260 #endif
261
262       case cm_group:
263         new_command->value.Group = copy_group_command (command->value.Group);
264         break;
265
266       case cm_case:
267         new_command->value.Case = copy_case_command (command->value.Case);
268         break;
269
270       case cm_until:
271       case cm_while:
272         new_command->value.While = copy_while_command (command->value.While);
273         break;
274
275       case cm_if:
276         new_command->value.If = copy_if_command (command->value.If);
277         break;
278
279       case cm_simple:
280         new_command->value.Simple = copy_simple_command (command->value.Simple);
281         break;
282
283       case cm_connection:
284         {
285           CONNECTION *new_connection;
286
287           new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION));
288           new_connection->connector = command->value.Connection->connector;
289           new_connection->first = copy_command (command->value.Connection->first);
290           new_connection->second = copy_command (command->value.Connection->second);
291           new_command->value.Connection = new_connection;
292           break;
293         }
294
295       case cm_function_def:
296         new_command->value.Function_def = copy_function_def (command->value.Function_def);
297         break;
298     }
299   return (new_command);
300 }