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 35static PATTERN_LIST *copy_case_clause __P((PATTERN_LIST *)); 36static PATTERN_LIST *copy_case_clauses __P((PATTERN_LIST *)); 37static FOR_COM *copy_for_command __P((FOR_COM *)); 38#if defined (ARITH_FOR_COMMAND) 39static ARITH_FOR_COM *copy_arith_for_command __P((ARITH_FOR_COM *)); 40#endif 41static GROUP_COM *copy_group_command __P((GROUP_COM *)); 42static SUBSHELL_COM *copy_subshell_command __P((SUBSHELL_COM *)); 43static CASE_COM *copy_case_command __P((CASE_COM *)); 44static WHILE_COM *copy_while_command __P((WHILE_COM *)); 45static IF_COM *copy_if_command __P((IF_COM *)); 46#if defined (DPAREN_ARITHMETIC) 47static ARITH_COM *copy_arith_command __P((ARITH_COM *)); 48#endif 49#if defined (COND_COMMAND) 50static COND_COM *copy_cond_command __P((COND_COM *)); 51#endif 52static SIMPLE_COM *copy_simple_command __P((SIMPLE_COM *)); 53 54WORD_DESC * 55copy_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. */ 67WORD_LIST * 68copy_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 79static PATTERN_LIST * 80copy_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 91static PATTERN_LIST * 92copy_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. */ 107REDIRECT * 108copy_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 145REDIRECT * 146copy_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 160static FOR_COM * 161copy_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) 176static ARITH_FOR_COM * 177copy_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 193static GROUP_COM * 194copy_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 204static SUBSHELL_COM * 205copy_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 216static CASE_COM * 217copy_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 230static WHILE_COM * 231copy_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 243static IF_COM * 244copy_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) 258static ARITH_COM * 259copy_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) 274static COND_COM * 275copy_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 292static SIMPLE_COM * 293copy_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 306FUNCTION_DEF * 307copy_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 318FUNCTION_DEF * 319copy_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! */ 332COMMAND * 333copy_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} 423