]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
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 | ||
8868edaf | 5 | /* Copyright (C) 1987-2020 Free Software Foundation, Inc. |
726f6388 JA |
6 | |
7 | This file is part of GNU Bash, the Bourne Again SHell. | |
8 | ||
3185942a JA |
9 | Bash is free software: you can redistribute it and/or modify |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation, either version 3 of the License, or | |
12 | (at your option) any later version. | |
726f6388 | 13 | |
3185942a JA |
14 | Bash is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
726f6388 JA |
18 | |
19 | You should have received a copy of the GNU General Public License | |
3185942a JA |
20 | along with Bash. If not, see <http://www.gnu.org/licenses/>. |
21 | */ | |
726f6388 | 22 | |
ccc6cda3 JA |
23 | #include "config.h" |
24 | ||
cce855bc | 25 | #include "bashtypes.h" |
726f6388 | 26 | |
ccc6cda3 JA |
27 | #if defined (HAVE_UNISTD_H) |
28 | # include <unistd.h> | |
29 | #endif | |
30 | ||
cce855bc JA |
31 | #include <stdio.h> |
32 | ||
726f6388 JA |
33 | #include "shell.h" |
34 | ||
8868edaf CR |
35 | static PATTERN_LIST *copy_case_clause PARAMS((PATTERN_LIST *)); |
36 | static PATTERN_LIST *copy_case_clauses PARAMS((PATTERN_LIST *)); | |
37 | static FOR_COM *copy_for_command PARAMS((FOR_COM *)); | |
f73dda09 | 38 | #if defined (ARITH_FOR_COMMAND) |
8868edaf | 39 | static ARITH_FOR_COM *copy_arith_for_command PARAMS((ARITH_FOR_COM *)); |
f73dda09 | 40 | #endif |
8868edaf CR |
41 | static GROUP_COM *copy_group_command PARAMS((GROUP_COM *)); |
42 | static SUBSHELL_COM *copy_subshell_command PARAMS((SUBSHELL_COM *)); | |
43 | static COPROC_COM *copy_coproc_command PARAMS((COPROC_COM *)); | |
44 | static CASE_COM *copy_case_command PARAMS((CASE_COM *)); | |
45 | static WHILE_COM *copy_while_command PARAMS((WHILE_COM *)); | |
46 | static IF_COM *copy_if_command PARAMS((IF_COM *)); | |
f73dda09 | 47 | #if defined (DPAREN_ARITHMETIC) |
8868edaf | 48 | static ARITH_COM *copy_arith_command PARAMS((ARITH_COM *)); |
f73dda09 JA |
49 | #endif |
50 | #if defined (COND_COMMAND) | |
8868edaf | 51 | static COND_COM *copy_cond_command PARAMS((COND_COM *)); |
f73dda09 | 52 | #endif |
8868edaf | 53 | static SIMPLE_COM *copy_simple_command PARAMS((SIMPLE_COM *)); |
f73dda09 | 54 | |
726f6388 | 55 | WORD_DESC * |
cce855bc JA |
56 | copy_word (w) |
57 | WORD_DESC *w; | |
726f6388 | 58 | { |
ccc6cda3 JA |
59 | WORD_DESC *new_word; |
60 | ||
7117c2d2 | 61 | new_word = make_bare_word (w->word); |
28ef6c31 | 62 | new_word->flags = w->flags; |
726f6388 JA |
63 | return (new_word); |
64 | } | |
65 | ||
ccc6cda3 | 66 | /* Copy the chain of words in LIST. Return a pointer to |
726f6388 JA |
67 | the new chain. */ |
68 | WORD_LIST * | |
69 | copy_word_list (list) | |
70 | WORD_LIST *list; | |
71 | { | |
d233b485 | 72 | WORD_LIST *new_list, *tl; |
726f6388 | 73 | |
d233b485 CR |
74 | for (new_list = tl = (WORD_LIST *)NULL; list; list = list->next) |
75 | { | |
76 | if (new_list == 0) | |
77 | new_list = tl = make_word_list (copy_word (list->word), new_list); | |
78 | else | |
79 | { | |
80 | tl->next = make_word_list (copy_word (list->word), (WORD_LIST *)NULL); | |
81 | tl = tl->next; | |
82 | } | |
83 | } | |
7117c2d2 | 84 | |
d233b485 | 85 | return (new_list); |
726f6388 JA |
86 | } |
87 | ||
88 | static PATTERN_LIST * | |
89 | copy_case_clause (clause) | |
90 | PATTERN_LIST *clause; | |
91 | { | |
ccc6cda3 JA |
92 | PATTERN_LIST *new_clause; |
93 | ||
94 | new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST)); | |
726f6388 JA |
95 | new_clause->patterns = copy_word_list (clause->patterns); |
96 | new_clause->action = copy_command (clause->action); | |
3185942a | 97 | new_clause->flags = clause->flags; |
726f6388 JA |
98 | return (new_clause); |
99 | } | |
100 | ||
101 | static PATTERN_LIST * | |
102 | copy_case_clauses (clauses) | |
103 | PATTERN_LIST *clauses; | |
104 | { | |
ccc6cda3 | 105 | PATTERN_LIST *new_list, *new_clause; |
726f6388 | 106 | |
ccc6cda3 | 107 | for (new_list = (PATTERN_LIST *)NULL; clauses; clauses = clauses->next) |
726f6388 | 108 | { |
ccc6cda3 | 109 | new_clause = copy_case_clause (clauses); |
726f6388 JA |
110 | new_clause->next = new_list; |
111 | new_list = new_clause; | |
726f6388 JA |
112 | } |
113 | return (REVERSE_LIST (new_list, PATTERN_LIST *)); | |
114 | } | |
115 | ||
116 | /* Copy a single redirect. */ | |
117 | REDIRECT * | |
118 | copy_redirect (redirect) | |
119 | REDIRECT *redirect; | |
120 | { | |
ccc6cda3 JA |
121 | REDIRECT *new_redirect; |
122 | ||
123 | new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT)); | |
0001803f | 124 | #if 0 |
726f6388 | 125 | FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT))); |
0001803f CR |
126 | #else |
127 | *new_redirect = *redirect; /* let the compiler do the fast structure copy */ | |
128 | #endif | |
129 | ||
130 | if (redirect->rflags & REDIR_VARASSIGN) | |
131 | new_redirect->redirector.filename = copy_word (redirect->redirector.filename); | |
132 | ||
726f6388 JA |
133 | switch (redirect->instruction) |
134 | { | |
135 | case r_reading_until: | |
136 | case r_deblank_reading_until: | |
13db572a | 137 | new_redirect->here_doc_eof = redirect->here_doc_eof ? savestring (redirect->here_doc_eof) : 0; |
ccc6cda3 | 138 | /*FALLTHROUGH*/ |
7117c2d2 | 139 | case r_reading_string: |
726f6388 JA |
140 | case r_appending_to: |
141 | case r_output_direction: | |
142 | case r_input_direction: | |
143 | case r_inputa_direction: | |
144 | case r_err_and_out: | |
3185942a | 145 | case r_append_err_and_out: |
726f6388 JA |
146 | case r_input_output: |
147 | case r_output_force: | |
148 | case r_duplicating_input_word: | |
149 | case r_duplicating_output_word: | |
7117c2d2 JA |
150 | case r_move_input_word: |
151 | case r_move_output_word: | |
ccc6cda3 | 152 | new_redirect->redirectee.filename = copy_word (redirect->redirectee.filename); |
726f6388 | 153 | break; |
d166f048 JA |
154 | case r_duplicating_input: |
155 | case r_duplicating_output: | |
7117c2d2 JA |
156 | case r_move_input: |
157 | case r_move_output: | |
d166f048 JA |
158 | case r_close_this: |
159 | break; | |
726f6388 JA |
160 | } |
161 | return (new_redirect); | |
162 | } | |
ccc6cda3 | 163 | |
726f6388 JA |
164 | REDIRECT * |
165 | copy_redirects (list) | |
166 | REDIRECT *list; | |
167 | { | |
ccc6cda3 | 168 | REDIRECT *new_list, *temp; |
726f6388 | 169 | |
ccc6cda3 | 170 | for (new_list = (REDIRECT *)NULL; list; list = list->next) |
726f6388 | 171 | { |
ccc6cda3 | 172 | temp = copy_redirect (list); |
726f6388 JA |
173 | temp->next = new_list; |
174 | new_list = temp; | |
726f6388 JA |
175 | } |
176 | return (REVERSE_LIST (new_list, REDIRECT *)); | |
177 | } | |
ccc6cda3 | 178 | |
726f6388 JA |
179 | static FOR_COM * |
180 | copy_for_command (com) | |
181 | FOR_COM *com; | |
182 | { | |
ccc6cda3 JA |
183 | FOR_COM *new_for; |
184 | ||
185 | new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM)); | |
726f6388 | 186 | new_for->flags = com->flags; |
b80f6443 | 187 | new_for->line = com->line; |
726f6388 JA |
188 | new_for->name = copy_word (com->name); |
189 | new_for->map_list = copy_word_list (com->map_list); | |
190 | new_for->action = copy_command (com->action); | |
191 | return (new_for); | |
192 | } | |
193 | ||
bb70624e JA |
194 | #if defined (ARITH_FOR_COMMAND) |
195 | static ARITH_FOR_COM * | |
196 | copy_arith_for_command (com) | |
197 | ARITH_FOR_COM *com; | |
198 | { | |
199 | ARITH_FOR_COM *new_arith_for; | |
200 | ||
201 | new_arith_for = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM)); | |
202 | new_arith_for->flags = com->flags; | |
203 | new_arith_for->line = com->line; | |
204 | new_arith_for->init = copy_word_list (com->init); | |
205 | new_arith_for->test = copy_word_list (com->test); | |
206 | new_arith_for->step = copy_word_list (com->step); | |
207 | new_arith_for->action = copy_command (com->action); | |
208 | return (new_arith_for); | |
209 | } | |
210 | #endif /* ARITH_FOR_COMMAND */ | |
211 | ||
726f6388 JA |
212 | static GROUP_COM * |
213 | copy_group_command (com) | |
214 | GROUP_COM *com; | |
215 | { | |
ccc6cda3 | 216 | GROUP_COM *new_group; |
726f6388 | 217 | |
ccc6cda3 | 218 | new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM)); |
726f6388 JA |
219 | new_group->command = copy_command (com->command); |
220 | return (new_group); | |
221 | } | |
222 | ||
bb70624e JA |
223 | static SUBSHELL_COM * |
224 | copy_subshell_command (com) | |
225 | SUBSHELL_COM *com; | |
226 | { | |
227 | SUBSHELL_COM *new_subshell; | |
228 | ||
229 | new_subshell = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM)); | |
230 | new_subshell->command = copy_command (com->command); | |
231 | new_subshell->flags = com->flags; | |
d233b485 | 232 | new_subshell->line = com->line; |
bb70624e JA |
233 | return (new_subshell); |
234 | } | |
235 | ||
3185942a JA |
236 | static COPROC_COM * |
237 | copy_coproc_command (com) | |
238 | COPROC_COM *com; | |
239 | { | |
240 | COPROC_COM *new_coproc; | |
241 | ||
242 | new_coproc = (COPROC_COM *)xmalloc (sizeof (COPROC_COM)); | |
243 | new_coproc->name = savestring (com->name); | |
244 | new_coproc->command = copy_command (com->command); | |
245 | new_coproc->flags = com->flags; | |
246 | return (new_coproc); | |
247 | } | |
248 | ||
726f6388 JA |
249 | static CASE_COM * |
250 | copy_case_command (com) | |
251 | CASE_COM *com; | |
252 | { | |
ccc6cda3 | 253 | CASE_COM *new_case; |
726f6388 | 254 | |
ccc6cda3 | 255 | new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM)); |
726f6388 | 256 | new_case->flags = com->flags; |
b80f6443 | 257 | new_case->line = com->line; |
726f6388 JA |
258 | new_case->word = copy_word (com->word); |
259 | new_case->clauses = copy_case_clauses (com->clauses); | |
260 | return (new_case); | |
261 | } | |
262 | ||
263 | static WHILE_COM * | |
264 | copy_while_command (com) | |
265 | WHILE_COM *com; | |
266 | { | |
ccc6cda3 | 267 | WHILE_COM *new_while; |
726f6388 | 268 | |
ccc6cda3 | 269 | new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM)); |
726f6388 JA |
270 | new_while->flags = com->flags; |
271 | new_while->test = copy_command (com->test); | |
272 | new_while->action = copy_command (com->action); | |
273 | return (new_while); | |
274 | } | |
275 | ||
276 | static IF_COM * | |
277 | copy_if_command (com) | |
278 | IF_COM *com; | |
279 | { | |
ccc6cda3 | 280 | IF_COM *new_if; |
726f6388 | 281 | |
ccc6cda3 | 282 | new_if = (IF_COM *)xmalloc (sizeof (IF_COM)); |
726f6388 JA |
283 | new_if->flags = com->flags; |
284 | new_if->test = copy_command (com->test); | |
285 | new_if->true_case = copy_command (com->true_case); | |
7117c2d2 | 286 | new_if->false_case = com->false_case ? copy_command (com->false_case) : com->false_case; |
726f6388 JA |
287 | return (new_if); |
288 | } | |
289 | ||
cce855bc JA |
290 | #if defined (DPAREN_ARITHMETIC) |
291 | static ARITH_COM * | |
292 | copy_arith_command (com) | |
293 | ARITH_COM *com; | |
294 | { | |
295 | ARITH_COM *new_arith; | |
296 | ||
297 | new_arith = (ARITH_COM *)xmalloc (sizeof (ARITH_COM)); | |
298 | new_arith->flags = com->flags; | |
299 | new_arith->exp = copy_word_list (com->exp); | |
300 | new_arith->line = com->line; | |
301 | ||
302 | return (new_arith); | |
303 | } | |
304 | #endif | |
305 | ||
306 | #if defined (COND_COMMAND) | |
307 | static COND_COM * | |
308 | copy_cond_command (com) | |
309 | COND_COM *com; | |
310 | { | |
311 | COND_COM *new_cond; | |
312 | ||
313 | new_cond = (COND_COM *)xmalloc (sizeof (COND_COM)); | |
314 | new_cond->flags = com->flags; | |
315 | new_cond->line = com->line; | |
bc4cd23c JA |
316 | new_cond->type = com->type; |
317 | new_cond->op = com->op ? copy_word (com->op) : com->op; | |
cce855bc JA |
318 | new_cond->left = com->left ? copy_cond_command (com->left) : (COND_COM *)NULL; |
319 | new_cond->right = com->right ? copy_cond_command (com->right) : (COND_COM *)NULL; | |
320 | ||
321 | return (new_cond); | |
322 | } | |
323 | #endif | |
324 | ||
726f6388 JA |
325 | static SIMPLE_COM * |
326 | copy_simple_command (com) | |
327 | SIMPLE_COM *com; | |
328 | { | |
cce855bc | 329 | SIMPLE_COM *new_simple; |
726f6388 | 330 | |
cce855bc | 331 | new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); |
726f6388 JA |
332 | new_simple->flags = com->flags; |
333 | new_simple->words = copy_word_list (com->words); | |
7117c2d2 | 334 | new_simple->redirects = com->redirects ? copy_redirects (com->redirects) : (REDIRECT *)NULL; |
726f6388 JA |
335 | new_simple->line = com->line; |
336 | return (new_simple); | |
337 | } | |
338 | ||
b80f6443 JA |
339 | FUNCTION_DEF * |
340 | copy_function_def_contents (old, new_def) | |
341 | FUNCTION_DEF *old, *new_def; | |
342 | { | |
343 | new_def->name = copy_word (old->name); | |
344 | new_def->command = old->command ? copy_command (old->command) : old->command; | |
345 | new_def->flags = old->flags; | |
346 | new_def->line = old->line; | |
347 | new_def->source_file = old->source_file ? savestring (old->source_file) : old->source_file; | |
348 | return (new_def); | |
349 | } | |
350 | ||
351 | FUNCTION_DEF * | |
726f6388 JA |
352 | copy_function_def (com) |
353 | FUNCTION_DEF *com; | |
354 | { | |
ccc6cda3 | 355 | FUNCTION_DEF *new_def; |
726f6388 | 356 | |
ccc6cda3 | 357 | new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF)); |
b80f6443 | 358 | new_def = copy_function_def_contents (com, new_def); |
726f6388 JA |
359 | return (new_def); |
360 | } | |
361 | ||
362 | /* Copy the command structure in COMMAND. Return a pointer to the | |
363 | copy. Don't you forget to dispose_command () on this pointer | |
364 | later! */ | |
365 | COMMAND * | |
366 | copy_command (command) | |
367 | COMMAND *command; | |
368 | { | |
ccc6cda3 | 369 | COMMAND *new_command; |
726f6388 | 370 | |
ccc6cda3 JA |
371 | if (command == NULL) |
372 | return (command); | |
726f6388 | 373 | |
ccc6cda3 JA |
374 | new_command = (COMMAND *)xmalloc (sizeof (COMMAND)); |
375 | FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND)); | |
376 | new_command->flags = command->flags; | |
377 | new_command->line = command->line; | |
726f6388 | 378 | |
ccc6cda3 JA |
379 | if (command->redirects) |
380 | new_command->redirects = copy_redirects (command->redirects); | |
381 | ||
382 | switch (command->type) | |
383 | { | |
384 | case cm_for: | |
385 | new_command->value.For = copy_for_command (command->value.For); | |
386 | break; | |
726f6388 | 387 | |
bb70624e JA |
388 | #if defined (ARITH_FOR_COMMAND) |
389 | case cm_arith_for: | |
390 | new_command->value.ArithFor = copy_arith_for_command (command->value.ArithFor); | |
391 | break; | |
392 | #endif | |
393 | ||
726f6388 | 394 | #if defined (SELECT_COMMAND) |
ccc6cda3 JA |
395 | case cm_select: |
396 | new_command->value.Select = | |
397 | (SELECT_COM *)copy_for_command ((FOR_COM *)command->value.Select); | |
398 | break; | |
726f6388 JA |
399 | #endif |
400 | ||
ccc6cda3 JA |
401 | case cm_group: |
402 | new_command->value.Group = copy_group_command (command->value.Group); | |
403 | break; | |
726f6388 | 404 | |
bb70624e | 405 | case cm_subshell: |
28ef6c31 JA |
406 | new_command->value.Subshell = copy_subshell_command (command->value.Subshell); |
407 | break; | |
bb70624e | 408 | |
3185942a JA |
409 | case cm_coproc: |
410 | new_command->value.Coproc = copy_coproc_command (command->value.Coproc); | |
411 | break; | |
412 | ||
ccc6cda3 JA |
413 | case cm_case: |
414 | new_command->value.Case = copy_case_command (command->value.Case); | |
415 | break; | |
416 | ||
417 | case cm_until: | |
418 | case cm_while: | |
419 | new_command->value.While = copy_while_command (command->value.While); | |
420 | break; | |
421 | ||
422 | case cm_if: | |
423 | new_command->value.If = copy_if_command (command->value.If); | |
424 | break; | |
425 | ||
cce855bc JA |
426 | #if defined (DPAREN_ARITHMETIC) |
427 | case cm_arith: | |
28ef6c31 JA |
428 | new_command->value.Arith = copy_arith_command (command->value.Arith); |
429 | break; | |
cce855bc JA |
430 | #endif |
431 | ||
432 | #if defined (COND_COMMAND) | |
433 | case cm_cond: | |
434 | new_command->value.Cond = copy_cond_command (command->value.Cond); | |
435 | break; | |
436 | #endif | |
437 | ||
ccc6cda3 JA |
438 | case cm_simple: |
439 | new_command->value.Simple = copy_simple_command (command->value.Simple); | |
440 | break; | |
441 | ||
442 | case cm_connection: | |
443 | { | |
444 | CONNECTION *new_connection; | |
445 | ||
446 | new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION)); | |
447 | new_connection->connector = command->value.Connection->connector; | |
448 | new_connection->first = copy_command (command->value.Connection->first); | |
449 | new_connection->second = copy_command (command->value.Connection->second); | |
450 | new_command->value.Connection = new_connection; | |
726f6388 JA |
451 | break; |
452 | } | |
ccc6cda3 JA |
453 | |
454 | case cm_function_def: | |
455 | new_command->value.Function_def = copy_function_def (command->value.Function_def); | |
456 | break; | |
726f6388 JA |
457 | } |
458 | return (new_command); | |
459 | } |