/* copy_command.c -- copy a COMMAND structure. This is needed primarily for making function definitions, but I'm not sure that anyone else will need it. */ /* Copyright (C) 1987-2009 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. Bash is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bash is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bash. If not, see . */ #include "config.h" #include "bashtypes.h" #if defined (HAVE_UNISTD_H) # include #endif #include #include "shell.h" static PATTERN_LIST *copy_case_clause __P((PATTERN_LIST *)); static PATTERN_LIST *copy_case_clauses __P((PATTERN_LIST *)); static FOR_COM *copy_for_command __P((FOR_COM *)); #if defined (ARITH_FOR_COMMAND) static ARITH_FOR_COM *copy_arith_for_command __P((ARITH_FOR_COM *)); #endif static GROUP_COM *copy_group_command __P((GROUP_COM *)); static SUBSHELL_COM *copy_subshell_command __P((SUBSHELL_COM *)); static COPROC_COM *copy_coproc_command __P((COPROC_COM *)); static CASE_COM *copy_case_command __P((CASE_COM *)); static WHILE_COM *copy_while_command __P((WHILE_COM *)); static IF_COM *copy_if_command __P((IF_COM *)); #if defined (DPAREN_ARITHMETIC) static ARITH_COM *copy_arith_command __P((ARITH_COM *)); #endif #if defined (COND_COMMAND) static COND_COM *copy_cond_command __P((COND_COM *)); #endif static SIMPLE_COM *copy_simple_command __P((SIMPLE_COM *)); WORD_DESC * copy_word (w) WORD_DESC *w; { WORD_DESC *new_word; new_word = make_bare_word (w->word); new_word->flags = w->flags; return (new_word); } /* Copy the chain of words in LIST. Return a pointer to the new chain. */ WORD_LIST * copy_word_list (list) WORD_LIST *list; { WORD_LIST *new_list; for (new_list = (WORD_LIST *)NULL; list; list = list->next) new_list = make_word_list (copy_word (list->word), new_list); return (REVERSE_LIST (new_list, WORD_LIST *)); } static PATTERN_LIST * copy_case_clause (clause) PATTERN_LIST *clause; { PATTERN_LIST *new_clause; new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST)); new_clause->patterns = copy_word_list (clause->patterns); new_clause->action = copy_command (clause->action); new_clause->flags = clause->flags; return (new_clause); } static PATTERN_LIST * copy_case_clauses (clauses) PATTERN_LIST *clauses; { PATTERN_LIST *new_list, *new_clause; for (new_list = (PATTERN_LIST *)NULL; clauses; clauses = clauses->next) { new_clause = copy_case_clause (clauses); new_clause->next = new_list; new_list = new_clause; } return (REVERSE_LIST (new_list, PATTERN_LIST *)); } /* Copy a single redirect. */ REDIRECT * copy_redirect (redirect) REDIRECT *redirect; { REDIRECT *new_redirect; new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT)); #if 0 FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT))); #else *new_redirect = *redirect; /* let the compiler do the fast structure copy */ #endif if (redirect->rflags & REDIR_VARASSIGN) new_redirect->redirector.filename = copy_word (redirect->redirector.filename); switch (redirect->instruction) { case r_reading_until: case r_deblank_reading_until: new_redirect->here_doc_eof = redirect->here_doc_eof ? savestring (redirect->here_doc_eof) : 0; /*FALLTHROUGH*/ case r_reading_string: case r_appending_to: case r_output_direction: case r_input_direction: case r_inputa_direction: case r_err_and_out: case r_append_err_and_out: case r_input_output: case r_output_force: case r_duplicating_input_word: case r_duplicating_output_word: case r_move_input_word: case r_move_output_word: new_redirect->redirectee.filename = copy_word (redirect->redirectee.filename); break; case r_duplicating_input: case r_duplicating_output: case r_move_input: case r_move_output: case r_close_this: break; } return (new_redirect); } REDIRECT * copy_redirects (list) REDIRECT *list; { REDIRECT *new_list, *temp; for (new_list = (REDIRECT *)NULL; list; list = list->next) { temp = copy_redirect (list); temp->next = new_list; new_list = temp; } return (REVERSE_LIST (new_list, REDIRECT *)); } static FOR_COM * copy_for_command (com) FOR_COM *com; { FOR_COM *new_for; new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM)); new_for->flags = com->flags; new_for->line = com->line; new_for->name = copy_word (com->name); new_for->map_list = copy_word_list (com->map_list); new_for->action = copy_command (com->action); return (new_for); } #if defined (ARITH_FOR_COMMAND) static ARITH_FOR_COM * copy_arith_for_command (com) ARITH_FOR_COM *com; { ARITH_FOR_COM *new_arith_for; new_arith_for = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM)); new_arith_for->flags = com->flags; new_arith_for->line = com->line; new_arith_for->init = copy_word_list (com->init); new_arith_for->test = copy_word_list (com->test); new_arith_for->step = copy_word_list (com->step); new_arith_for->action = copy_command (com->action); return (new_arith_for); } #endif /* ARITH_FOR_COMMAND */ static GROUP_COM * copy_group_command (com) GROUP_COM *com; { GROUP_COM *new_group; new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM)); new_group->command = copy_command (com->command); return (new_group); } static SUBSHELL_COM * copy_subshell_command (com) SUBSHELL_COM *com; { SUBSHELL_COM *new_subshell; new_subshell = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM)); new_subshell->command = copy_command (com->command); new_subshell->flags = com->flags; return (new_subshell); } static COPROC_COM * copy_coproc_command (com) COPROC_COM *com; { COPROC_COM *new_coproc; new_coproc = (COPROC_COM *)xmalloc (sizeof (COPROC_COM)); new_coproc->name = savestring (com->name); new_coproc->command = copy_command (com->command); new_coproc->flags = com->flags; return (new_coproc); } static CASE_COM * copy_case_command (com) CASE_COM *com; { CASE_COM *new_case; new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM)); new_case->flags = com->flags; new_case->line = com->line; new_case->word = copy_word (com->word); new_case->clauses = copy_case_clauses (com->clauses); return (new_case); } static WHILE_COM * copy_while_command (com) WHILE_COM *com; { WHILE_COM *new_while; new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM)); new_while->flags = com->flags; new_while->test = copy_command (com->test); new_while->action = copy_command (com->action); return (new_while); } static IF_COM * copy_if_command (com) IF_COM *com; { IF_COM *new_if; new_if = (IF_COM *)xmalloc (sizeof (IF_COM)); new_if->flags = com->flags; new_if->test = copy_command (com->test); new_if->true_case = copy_command (com->true_case); new_if->false_case = com->false_case ? copy_command (com->false_case) : com->false_case; return (new_if); } #if defined (DPAREN_ARITHMETIC) static ARITH_COM * copy_arith_command (com) ARITH_COM *com; { ARITH_COM *new_arith; new_arith = (ARITH_COM *)xmalloc (sizeof (ARITH_COM)); new_arith->flags = com->flags; new_arith->exp = copy_word_list (com->exp); new_arith->line = com->line; return (new_arith); } #endif #if defined (COND_COMMAND) static COND_COM * copy_cond_command (com) COND_COM *com; { COND_COM *new_cond; new_cond = (COND_COM *)xmalloc (sizeof (COND_COM)); new_cond->flags = com->flags; new_cond->line = com->line; new_cond->type = com->type; new_cond->op = com->op ? copy_word (com->op) : com->op; new_cond->left = com->left ? copy_cond_command (com->left) : (COND_COM *)NULL; new_cond->right = com->right ? copy_cond_command (com->right) : (COND_COM *)NULL; return (new_cond); } #endif static SIMPLE_COM * copy_simple_command (com) SIMPLE_COM *com; { SIMPLE_COM *new_simple; new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); new_simple->flags = com->flags; new_simple->words = copy_word_list (com->words); new_simple->redirects = com->redirects ? copy_redirects (com->redirects) : (REDIRECT *)NULL; new_simple->line = com->line; return (new_simple); } FUNCTION_DEF * copy_function_def_contents (old, new_def) FUNCTION_DEF *old, *new_def; { new_def->name = copy_word (old->name); new_def->command = old->command ? copy_command (old->command) : old->command; new_def->flags = old->flags; new_def->line = old->line; new_def->source_file = old->source_file ? savestring (old->source_file) : old->source_file; return (new_def); } FUNCTION_DEF * copy_function_def (com) FUNCTION_DEF *com; { FUNCTION_DEF *new_def; new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF)); new_def = copy_function_def_contents (com, new_def); return (new_def); } /* Copy the command structure in COMMAND. Return a pointer to the copy. Don't you forget to dispose_command () on this pointer later! */ COMMAND * copy_command (command) COMMAND *command; { COMMAND *new_command; if (command == NULL) return (command); new_command = (COMMAND *)xmalloc (sizeof (COMMAND)); FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND)); new_command->flags = command->flags; new_command->line = command->line; if (command->redirects) new_command->redirects = copy_redirects (command->redirects); switch (command->type) { case cm_for: new_command->value.For = copy_for_command (command->value.For); break; #if defined (ARITH_FOR_COMMAND) case cm_arith_for: new_command->value.ArithFor = copy_arith_for_command (command->value.ArithFor); break; #endif #if defined (SELECT_COMMAND) case cm_select: new_command->value.Select = (SELECT_COM *)copy_for_command ((FOR_COM *)command->value.Select); break; #endif case cm_group: new_command->value.Group = copy_group_command (command->value.Group); break; case cm_subshell: new_command->value.Subshell = copy_subshell_command (command->value.Subshell); break; case cm_coproc: new_command->value.Coproc = copy_coproc_command (command->value.Coproc); break; case cm_case: new_command->value.Case = copy_case_command (command->value.Case); break; case cm_until: case cm_while: new_command->value.While = copy_while_command (command->value.While); break; case cm_if: new_command->value.If = copy_if_command (command->value.If); break; #if defined (DPAREN_ARITHMETIC) case cm_arith: new_command->value.Arith = copy_arith_command (command->value.Arith); break; #endif #if defined (COND_COMMAND) case cm_cond: new_command->value.Cond = copy_cond_command (command->value.Cond); break; #endif case cm_simple: new_command->value.Simple = copy_simple_command (command->value.Simple); break; case cm_connection: { CONNECTION *new_connection; new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION)); new_connection->connector = command->value.Connection->connector; new_connection->first = copy_command (command->value.Connection->first); new_connection->second = copy_command (command->value.Connection->second); new_command->value.Connection = new_connection; break; } case cm_function_def: new_command->value.Function_def = copy_function_def (command->value.Function_def); break; } return (new_command); }