/* dispose_command.c -- dispose of a COMMAND structure. */ /* 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 "bashansi.h" #include "shell.h" extern sh_obj_cache_t wdcache, wlcache; /* Dispose of the command structure passed. */ void dispose_command (command) COMMAND *command; { if (command == 0) return; if (command->redirects) dispose_redirects (command->redirects); switch (command->type) { case cm_for: #if defined (SELECT_COMMAND) case cm_select: #endif { register FOR_COM *c; #if defined (SELECT_COMMAND) if (command->type == cm_select) c = (FOR_COM *)command->value.Select; else #endif c = command->value.For; dispose_word (c->name); dispose_words (c->map_list); dispose_command (c->action); free (c); break; } #if defined (ARITH_FOR_COMMAND) case cm_arith_for: { register ARITH_FOR_COM *c; c = command->value.ArithFor; dispose_words (c->init); dispose_words (c->test); dispose_words (c->step); dispose_command (c->action); free (c); break; } #endif /* ARITH_FOR_COMMAND */ case cm_group: { dispose_command (command->value.Group->command); free (command->value.Group); break; } case cm_subshell: { dispose_command (command->value.Subshell->command); free (command->value.Subshell); break; } case cm_coproc: { free (command->value.Coproc->name); dispose_command (command->value.Coproc->command); free (command->value.Coproc); break; } case cm_case: { register CASE_COM *c; PATTERN_LIST *t, *p; c = command->value.Case; dispose_word (c->word); for (p = c->clauses; p; ) { dispose_words (p->patterns); dispose_command (p->action); t = p; p = p->next; free (t); } free (c); break; } case cm_until: case cm_while: { register WHILE_COM *c; c = command->value.While; dispose_command (c->test); dispose_command (c->action); free (c); break; } case cm_if: { register IF_COM *c; c = command->value.If; dispose_command (c->test); dispose_command (c->true_case); dispose_command (c->false_case); free (c); break; } case cm_simple: { register SIMPLE_COM *c; c = command->value.Simple; dispose_words (c->words); dispose_redirects (c->redirects); free (c); break; } case cm_connection: { register CONNECTION *c; c = command->value.Connection; dispose_command (c->first); dispose_command (c->second); free (c); break; } #if defined (DPAREN_ARITHMETIC) case cm_arith: { register ARITH_COM *c; c = command->value.Arith; dispose_words (c->exp); free (c); break; } #endif /* DPAREN_ARITHMETIC */ #if defined (COND_COMMAND) case cm_cond: { register COND_COM *c; c = command->value.Cond; dispose_cond_node (c); break; } #endif /* COND_COMMAND */ case cm_function_def: { register FUNCTION_DEF *c; c = command->value.Function_def; dispose_function_def (c); break; } default: command_error ("dispose_command", CMDERR_BADTYPE, command->type, 0); break; } free (command); } #if defined (COND_COMMAND) /* How to free a node in a conditional command. */ void dispose_cond_node (cond) COND_COM *cond; { if (cond) { if (cond->left) dispose_cond_node (cond->left); if (cond->right) dispose_cond_node (cond->right); if (cond->op) dispose_word (cond->op); free (cond); } } #endif /* COND_COMMAND */ void dispose_function_def_contents (c) FUNCTION_DEF *c; { dispose_word (c->name); dispose_command (c->command); FREE (c->source_file); } void dispose_function_def (c) FUNCTION_DEF *c; { dispose_function_def_contents (c); free (c); } /* How to free a WORD_DESC. */ void dispose_word (w) WORD_DESC *w; { FREE (w->word); ocache_free (wdcache, WORD_DESC, w); } /* Free a WORD_DESC, but not the word contained within. */ void dispose_word_desc (w) WORD_DESC *w; { w->word = 0; ocache_free (wdcache, WORD_DESC, w); } /* How to get rid of a linked list of words. A WORD_LIST. */ void dispose_words (list) WORD_LIST *list; { WORD_LIST *t; while (list) { t = list; list = list->next; dispose_word (t->word); #if 0 free (t); #else ocache_free (wlcache, WORD_LIST, t); #endif } } #ifdef INCLUDE_UNUSED /* How to dispose of an array of pointers to char. This is identical to free_array in stringlib.c. */ void dispose_word_array (array) char **array; { register int count; if (array == 0) return; for (count = 0; array[count]; count++) free (array[count]); free (array); } #endif /* How to dispose of an list of redirections. A REDIRECT. */ void dispose_redirects (list) REDIRECT *list; { register REDIRECT *t; while (list) { t = list; list = list->next; if (t->rflags & REDIR_VARASSIGN) dispose_word (t->redirector.filename); switch (t->instruction) { case r_reading_until: case r_deblank_reading_until: free (t->here_doc_eof); /*FALLTHROUGH*/ case r_reading_string: case r_output_direction: case r_input_direction: case r_inputa_direction: case r_appending_to: 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: dispose_word (t->redirectee.filename); /* FALLTHROUGH */ default: break; } free (t); } }