| 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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
|---|
| 22 |
|
|---|
| 23 | #include "config.h"
|
|---|
| 24 |
|
|---|
| 25 | #include "bashtypes.h"
|
|---|
| 26 |
|
|---|
| 27 | #if defined (HAVE_UNISTD_H)
|
|---|
| 28 | # include <unistd.h>
|
|---|
| 29 | #endif
|
|---|
| 30 |
|
|---|
| 31 | #include <stdio.h>
|
|---|
| 32 |
|
|---|
| 33 | #include "shell.h"
|
|---|
| 34 |
|
|---|
| 35 | static PATTERN_LIST *copy_case_clause __P((PATTERN_LIST *));
|
|---|
| 36 | static PATTERN_LIST *copy_case_clauses __P((PATTERN_LIST *));
|
|---|
| 37 | static FOR_COM *copy_for_command __P((FOR_COM *));
|
|---|
| 38 | #if defined (ARITH_FOR_COMMAND)
|
|---|
| 39 | static ARITH_FOR_COM *copy_arith_for_command __P((ARITH_FOR_COM *));
|
|---|
| 40 | #endif
|
|---|
| 41 | static GROUP_COM *copy_group_command __P((GROUP_COM *));
|
|---|
| 42 | static SUBSHELL_COM *copy_subshell_command __P((SUBSHELL_COM *));
|
|---|
| 43 | static CASE_COM *copy_case_command __P((CASE_COM *));
|
|---|
| 44 | static WHILE_COM *copy_while_command __P((WHILE_COM *));
|
|---|
| 45 | static IF_COM *copy_if_command __P((IF_COM *));
|
|---|
| 46 | #if defined (DPAREN_ARITHMETIC)
|
|---|
| 47 | static ARITH_COM *copy_arith_command __P((ARITH_COM *));
|
|---|
| 48 | #endif
|
|---|
| 49 | #if defined (COND_COMMAND)
|
|---|
| 50 | static COND_COM *copy_cond_command __P((COND_COM *));
|
|---|
| 51 | #endif
|
|---|
| 52 | static SIMPLE_COM *copy_simple_command __P((SIMPLE_COM *));
|
|---|
| 53 |
|
|---|
| 54 | WORD_DESC *
|
|---|
| 55 | copy_word (w)
|
|---|
| 56 | WORD_DESC *w;
|
|---|
| 57 | {
|
|---|
| 58 | WORD_DESC *new_word;
|
|---|
| 59 |
|
|---|
| 60 | new_word = make_bare_word (w->word);
|
|---|
| 61 | new_word->flags = w->flags;
|
|---|
| 62 | return (new_word);
|
|---|
| 63 | }
|
|---|
| 64 |
|
|---|
| 65 | /* Copy the chain of words in LIST. Return a pointer to
|
|---|
| 66 | the new chain. */
|
|---|
| 67 | WORD_LIST *
|
|---|
| 68 | copy_word_list (list)
|
|---|
| 69 | WORD_LIST *list;
|
|---|
| 70 | {
|
|---|
| 71 | WORD_LIST *new_list;
|
|---|
| 72 |
|
|---|
| 73 | for (new_list = (WORD_LIST *)NULL; list; list = list->next)
|
|---|
| 74 | new_list = make_word_list (copy_word (list->word), new_list);
|
|---|
| 75 |
|
|---|
| 76 | return (REVERSE_LIST (new_list, WORD_LIST *));
|
|---|
| 77 | }
|
|---|
| 78 |
|
|---|
| 79 | static PATTERN_LIST *
|
|---|
| 80 | copy_case_clause (clause)
|
|---|
| 81 | PATTERN_LIST *clause;
|
|---|
| 82 | {
|
|---|
| 83 | PATTERN_LIST *new_clause;
|
|---|
| 84 |
|
|---|
| 85 | new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
|
|---|
| 86 | new_clause->patterns = copy_word_list (clause->patterns);
|
|---|
| 87 | new_clause->action = copy_command (clause->action);
|
|---|
| 88 | return (new_clause);
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | static PATTERN_LIST *
|
|---|
| 92 | copy_case_clauses (clauses)
|
|---|
| 93 | PATTERN_LIST *clauses;
|
|---|
| 94 | {
|
|---|
| 95 | PATTERN_LIST *new_list, *new_clause;
|
|---|
| 96 |
|
|---|
| 97 | for (new_list = (PATTERN_LIST *)NULL; clauses; clauses = clauses->next)
|
|---|
| 98 | {
|
|---|
| 99 | new_clause = copy_case_clause (clauses);
|
|---|
| 100 | new_clause->next = new_list;
|
|---|
| 101 | new_list = new_clause;
|
|---|
| 102 | }
|
|---|
| 103 | return (REVERSE_LIST (new_list, PATTERN_LIST *));
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 | /* Copy a single redirect. */
|
|---|
| 107 | REDIRECT *
|
|---|
| 108 | copy_redirect (redirect)
|
|---|
| 109 | REDIRECT *redirect;
|
|---|
| 110 | {
|
|---|
| 111 | REDIRECT *new_redirect;
|
|---|
| 112 |
|
|---|
| 113 | new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT));
|
|---|
| 114 | FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT)));
|
|---|
| 115 | switch (redirect->instruction)
|
|---|
| 116 | {
|
|---|
| 117 | case r_reading_until:
|
|---|
| 118 | case r_deblank_reading_until:
|
|---|
| 119 | new_redirect->here_doc_eof = savestring (redirect->here_doc_eof);
|
|---|
| 120 | /*FALLTHROUGH*/
|
|---|
| 121 | case r_reading_string:
|
|---|
| 122 | case r_appending_to:
|
|---|
| 123 | case r_output_direction:
|
|---|
| 124 | case r_input_direction:
|
|---|
| 125 | case r_inputa_direction:
|
|---|
| 126 | case r_err_and_out:
|
|---|
| 127 | case r_input_output:
|
|---|
| 128 | case r_output_force:
|
|---|
| 129 | case r_duplicating_input_word:
|
|---|
| 130 | case r_duplicating_output_word:
|
|---|
| 131 | case r_move_input_word:
|
|---|
| 132 | case r_move_output_word:
|
|---|
| 133 | new_redirect->redirectee.filename = copy_word (redirect->redirectee.filename);
|
|---|
| 134 | break;
|
|---|
| 135 | case r_duplicating_input:
|
|---|
| 136 | case r_duplicating_output:
|
|---|
| 137 | case r_move_input:
|
|---|
| 138 | case r_move_output:
|
|---|
| 139 | case r_close_this:
|
|---|
| 140 | break;
|
|---|
| 141 | }
|
|---|
| 142 | return (new_redirect);
|
|---|
| 143 | }
|
|---|
| 144 |
|
|---|
| 145 | REDIRECT *
|
|---|
| 146 | copy_redirects (list)
|
|---|
| 147 | REDIRECT *list;
|
|---|
| 148 | {
|
|---|
| 149 | REDIRECT *new_list, *temp;
|
|---|
| 150 |
|
|---|
| 151 | for (new_list = (REDIRECT *)NULL; list; list = list->next)
|
|---|
| 152 | {
|
|---|
| 153 | temp = copy_redirect (list);
|
|---|
| 154 | temp->next = new_list;
|
|---|
| 155 | new_list = temp;
|
|---|
| 156 | }
|
|---|
| 157 | return (REVERSE_LIST (new_list, REDIRECT *));
|
|---|
| 158 | }
|
|---|
| 159 |
|
|---|
| 160 | static FOR_COM *
|
|---|
| 161 | copy_for_command (com)
|
|---|
| 162 | FOR_COM *com;
|
|---|
| 163 | {
|
|---|
| 164 | FOR_COM *new_for;
|
|---|
| 165 |
|
|---|
| 166 | new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM));
|
|---|
| 167 | new_for->flags = com->flags;
|
|---|
| 168 | new_for->line = com->line;
|
|---|
| 169 | new_for->name = copy_word (com->name);
|
|---|
| 170 | new_for->map_list = copy_word_list (com->map_list);
|
|---|
| 171 | new_for->action = copy_command (com->action);
|
|---|
| 172 | return (new_for);
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | #if defined (ARITH_FOR_COMMAND)
|
|---|
| 176 | static ARITH_FOR_COM *
|
|---|
| 177 | copy_arith_for_command (com)
|
|---|
| 178 | ARITH_FOR_COM *com;
|
|---|
| 179 | {
|
|---|
| 180 | ARITH_FOR_COM *new_arith_for;
|
|---|
| 181 |
|
|---|
| 182 | new_arith_for = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM));
|
|---|
| 183 | new_arith_for->flags = com->flags;
|
|---|
| 184 | new_arith_for->line = com->line;
|
|---|
| 185 | new_arith_for->init = copy_word_list (com->init);
|
|---|
| 186 | new_arith_for->test = copy_word_list (com->test);
|
|---|
| 187 | new_arith_for->step = copy_word_list (com->step);
|
|---|
| 188 | new_arith_for->action = copy_command (com->action);
|
|---|
| 189 | return (new_arith_for);
|
|---|
| 190 | }
|
|---|
| 191 | #endif /* ARITH_FOR_COMMAND */
|
|---|
| 192 |
|
|---|
| 193 | static GROUP_COM *
|
|---|
| 194 | copy_group_command (com)
|
|---|
| 195 | GROUP_COM *com;
|
|---|
| 196 | {
|
|---|
| 197 | GROUP_COM *new_group;
|
|---|
| 198 |
|
|---|
| 199 | new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
|
|---|
| 200 | new_group->command = copy_command (com->command);
|
|---|
| 201 | return (new_group);
|
|---|
| 202 | }
|
|---|
| 203 |
|
|---|
| 204 | static SUBSHELL_COM *
|
|---|
| 205 | copy_subshell_command (com)
|
|---|
| 206 | SUBSHELL_COM *com;
|
|---|
| 207 | {
|
|---|
| 208 | SUBSHELL_COM *new_subshell;
|
|---|
| 209 |
|
|---|
| 210 | new_subshell = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
|
|---|
| 211 | new_subshell->command = copy_command (com->command);
|
|---|
| 212 | new_subshell->flags = com->flags;
|
|---|
| 213 | return (new_subshell);
|
|---|
| 214 | }
|
|---|
| 215 |
|
|---|
| 216 | static CASE_COM *
|
|---|
| 217 | copy_case_command (com)
|
|---|
| 218 | CASE_COM *com;
|
|---|
| 219 | {
|
|---|
| 220 | CASE_COM *new_case;
|
|---|
| 221 |
|
|---|
| 222 | new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM));
|
|---|
| 223 | new_case->flags = com->flags;
|
|---|
| 224 | new_case->line = com->line;
|
|---|
| 225 | new_case->word = copy_word (com->word);
|
|---|
| 226 | new_case->clauses = copy_case_clauses (com->clauses);
|
|---|
| 227 | return (new_case);
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | static WHILE_COM *
|
|---|
| 231 | copy_while_command (com)
|
|---|
| 232 | WHILE_COM *com;
|
|---|
| 233 | {
|
|---|
| 234 | WHILE_COM *new_while;
|
|---|
| 235 |
|
|---|
| 236 | new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
|
|---|
| 237 | new_while->flags = com->flags;
|
|---|
| 238 | new_while->test = copy_command (com->test);
|
|---|
| 239 | new_while->action = copy_command (com->action);
|
|---|
| 240 | return (new_while);
|
|---|
| 241 | }
|
|---|
| 242 |
|
|---|
| 243 | static IF_COM *
|
|---|
| 244 | copy_if_command (com)
|
|---|
| 245 | IF_COM *com;
|
|---|
| 246 | {
|
|---|
| 247 | IF_COM *new_if;
|
|---|
| 248 |
|
|---|
| 249 | new_if = (IF_COM *)xmalloc (sizeof (IF_COM));
|
|---|
| 250 | new_if->flags = com->flags;
|
|---|
| 251 | new_if->test = copy_command (com->test);
|
|---|
| 252 | new_if->true_case = copy_command (com->true_case);
|
|---|
| 253 | new_if->false_case = com->false_case ? copy_command (com->false_case) : com->false_case;
|
|---|
| 254 | return (new_if);
|
|---|
| 255 | }
|
|---|
| 256 |
|
|---|
| 257 | #if defined (DPAREN_ARITHMETIC)
|
|---|
| 258 | static ARITH_COM *
|
|---|
| 259 | copy_arith_command (com)
|
|---|
| 260 | ARITH_COM *com;
|
|---|
| 261 | {
|
|---|
| 262 | ARITH_COM *new_arith;
|
|---|
| 263 |
|
|---|
| 264 | new_arith = (ARITH_COM *)xmalloc (sizeof (ARITH_COM));
|
|---|
| 265 | new_arith->flags = com->flags;
|
|---|
| 266 | new_arith->exp = copy_word_list (com->exp);
|
|---|
| 267 | new_arith->line = com->line;
|
|---|
| 268 |
|
|---|
| 269 | return (new_arith);
|
|---|
| 270 | }
|
|---|
| 271 | #endif
|
|---|
| 272 |
|
|---|
| 273 | #if defined (COND_COMMAND)
|
|---|
| 274 | static COND_COM *
|
|---|
| 275 | copy_cond_command (com)
|
|---|
| 276 | COND_COM *com;
|
|---|
| 277 | {
|
|---|
| 278 | COND_COM *new_cond;
|
|---|
| 279 |
|
|---|
| 280 | new_cond = (COND_COM *)xmalloc (sizeof (COND_COM));
|
|---|
| 281 | new_cond->flags = com->flags;
|
|---|
| 282 | new_cond->line = com->line;
|
|---|
| 283 | new_cond->type = com->type;
|
|---|
| 284 | new_cond->op = com->op ? copy_word (com->op) : com->op;
|
|---|
| 285 | new_cond->left = com->left ? copy_cond_command (com->left) : (COND_COM *)NULL;
|
|---|
| 286 | new_cond->right = com->right ? copy_cond_command (com->right) : (COND_COM *)NULL;
|
|---|
| 287 |
|
|---|
| 288 | return (new_cond);
|
|---|
| 289 | }
|
|---|
| 290 | #endif
|
|---|
| 291 |
|
|---|
| 292 | static SIMPLE_COM *
|
|---|
| 293 | copy_simple_command (com)
|
|---|
| 294 | SIMPLE_COM *com;
|
|---|
| 295 | {
|
|---|
| 296 | SIMPLE_COM *new_simple;
|
|---|
| 297 |
|
|---|
| 298 | new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
|
|---|
| 299 | new_simple->flags = com->flags;
|
|---|
| 300 | new_simple->words = copy_word_list (com->words);
|
|---|
| 301 | new_simple->redirects = com->redirects ? copy_redirects (com->redirects) : (REDIRECT *)NULL;
|
|---|
| 302 | new_simple->line = com->line;
|
|---|
| 303 | return (new_simple);
|
|---|
| 304 | }
|
|---|
| 305 |
|
|---|
| 306 | FUNCTION_DEF *
|
|---|
| 307 | copy_function_def_contents (old, new_def)
|
|---|
| 308 | FUNCTION_DEF *old, *new_def;
|
|---|
| 309 | {
|
|---|
| 310 | new_def->name = copy_word (old->name);
|
|---|
| 311 | new_def->command = old->command ? copy_command (old->command) : old->command;
|
|---|
| 312 | new_def->flags = old->flags;
|
|---|
| 313 | new_def->line = old->line;
|
|---|
| 314 | new_def->source_file = old->source_file ? savestring (old->source_file) : old->source_file;
|
|---|
| 315 | return (new_def);
|
|---|
| 316 | }
|
|---|
| 317 |
|
|---|
| 318 | FUNCTION_DEF *
|
|---|
| 319 | copy_function_def (com)
|
|---|
| 320 | FUNCTION_DEF *com;
|
|---|
| 321 | {
|
|---|
| 322 | FUNCTION_DEF *new_def;
|
|---|
| 323 |
|
|---|
| 324 | new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
|
|---|
| 325 | new_def = copy_function_def_contents (com, new_def);
|
|---|
| 326 | return (new_def);
|
|---|
| 327 | }
|
|---|
| 328 |
|
|---|
| 329 | /* Copy the command structure in COMMAND. Return a pointer to the
|
|---|
| 330 | copy. Don't you forget to dispose_command () on this pointer
|
|---|
| 331 | later! */
|
|---|
| 332 | COMMAND *
|
|---|
| 333 | copy_command (command)
|
|---|
| 334 | COMMAND *command;
|
|---|
| 335 | {
|
|---|
| 336 | COMMAND *new_command;
|
|---|
| 337 |
|
|---|
| 338 | if (command == NULL)
|
|---|
| 339 | return (command);
|
|---|
| 340 |
|
|---|
| 341 | new_command = (COMMAND *)xmalloc (sizeof (COMMAND));
|
|---|
| 342 | FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND));
|
|---|
| 343 | new_command->flags = command->flags;
|
|---|
| 344 | new_command->line = command->line;
|
|---|
| 345 |
|
|---|
| 346 | if (command->redirects)
|
|---|
| 347 | new_command->redirects = copy_redirects (command->redirects);
|
|---|
| 348 |
|
|---|
| 349 | switch (command->type)
|
|---|
| 350 | {
|
|---|
| 351 | case cm_for:
|
|---|
| 352 | new_command->value.For = copy_for_command (command->value.For);
|
|---|
| 353 | break;
|
|---|
| 354 |
|
|---|
| 355 | #if defined (ARITH_FOR_COMMAND)
|
|---|
| 356 | case cm_arith_for:
|
|---|
| 357 | new_command->value.ArithFor = copy_arith_for_command (command->value.ArithFor);
|
|---|
| 358 | break;
|
|---|
| 359 | #endif
|
|---|
| 360 |
|
|---|
| 361 | #if defined (SELECT_COMMAND)
|
|---|
| 362 | case cm_select:
|
|---|
| 363 | new_command->value.Select =
|
|---|
| 364 | (SELECT_COM *)copy_for_command ((FOR_COM *)command->value.Select);
|
|---|
| 365 | break;
|
|---|
| 366 | #endif
|
|---|
| 367 |
|
|---|
| 368 | case cm_group:
|
|---|
| 369 | new_command->value.Group = copy_group_command (command->value.Group);
|
|---|
| 370 | break;
|
|---|
| 371 |
|
|---|
| 372 | case cm_subshell:
|
|---|
| 373 | new_command->value.Subshell = copy_subshell_command (command->value.Subshell);
|
|---|
| 374 | break;
|
|---|
| 375 |
|
|---|
| 376 | case cm_case:
|
|---|
| 377 | new_command->value.Case = copy_case_command (command->value.Case);
|
|---|
| 378 | break;
|
|---|
| 379 |
|
|---|
| 380 | case cm_until:
|
|---|
| 381 | case cm_while:
|
|---|
| 382 | new_command->value.While = copy_while_command (command->value.While);
|
|---|
| 383 | break;
|
|---|
| 384 |
|
|---|
| 385 | case cm_if:
|
|---|
| 386 | new_command->value.If = copy_if_command (command->value.If);
|
|---|
| 387 | break;
|
|---|
| 388 |
|
|---|
| 389 | #if defined (DPAREN_ARITHMETIC)
|
|---|
| 390 | case cm_arith:
|
|---|
| 391 | new_command->value.Arith = copy_arith_command (command->value.Arith);
|
|---|
| 392 | break;
|
|---|
| 393 | #endif
|
|---|
| 394 |
|
|---|
| 395 | #if defined (COND_COMMAND)
|
|---|
| 396 | case cm_cond:
|
|---|
| 397 | new_command->value.Cond = copy_cond_command (command->value.Cond);
|
|---|
| 398 | break;
|
|---|
| 399 | #endif
|
|---|
| 400 |
|
|---|
| 401 | case cm_simple:
|
|---|
| 402 | new_command->value.Simple = copy_simple_command (command->value.Simple);
|
|---|
| 403 | break;
|
|---|
| 404 |
|
|---|
| 405 | case cm_connection:
|
|---|
| 406 | {
|
|---|
| 407 | CONNECTION *new_connection;
|
|---|
| 408 |
|
|---|
| 409 | new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION));
|
|---|
| 410 | new_connection->connector = command->value.Connection->connector;
|
|---|
| 411 | new_connection->first = copy_command (command->value.Connection->first);
|
|---|
| 412 | new_connection->second = copy_command (command->value.Connection->second);
|
|---|
| 413 | new_command->value.Connection = new_connection;
|
|---|
| 414 | break;
|
|---|
| 415 | }
|
|---|
| 416 |
|
|---|
| 417 | case cm_function_def:
|
|---|
| 418 | new_command->value.Function_def = copy_function_def (command->value.Function_def);
|
|---|
| 419 | break;
|
|---|
| 420 | }
|
|---|
| 421 | return (new_command);
|
|---|
| 422 | }
|
|---|