1a4c0d7ef17f2ca41514e6eea212cb10d0eeebb7
[platform/upstream/bash.git] / dispose_cmd.c
1 /* dispose_command.c -- dispose of a COMMAND structure. */
2
3 /* Copyright (C) 1987,1991 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
7    Bash is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Bash; see the file COPYING.  If not, write to the Free
19    Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24
25 #if defined (HAVE_UNISTD_H)
26 #  include <unistd.h>
27 #endif
28
29 #include "bashansi.h"
30 #include "shell.h"
31
32 extern sh_obj_cache_t wdcache, wlcache;
33
34 /* Dispose of the command structure passed. */
35 void
36 dispose_command (command)
37      COMMAND *command;
38 {
39   if (command == 0)
40     return;
41
42   if (command->redirects)
43     dispose_redirects (command->redirects);
44
45   switch (command->type)
46     {
47     case cm_for:
48 #if defined (SELECT_COMMAND)
49     case cm_select:
50 #endif
51       {
52         register FOR_COM *c;
53 #if defined (SELECT_COMMAND)
54         if (command->type == cm_select)
55           c = (FOR_COM *)command->value.Select;
56         else
57 #endif
58         c = command->value.For;
59         dispose_word (c->name);
60         dispose_words (c->map_list);
61         dispose_command (c->action);
62         free (c);
63         break;
64       }
65
66 #if defined (ARITH_FOR_COMMAND)
67     case cm_arith_for:
68       {
69         register ARITH_FOR_COM *c;
70
71         c = command->value.ArithFor;
72         dispose_words (c->init);
73         dispose_words (c->test);
74         dispose_words (c->step);
75         dispose_command (c->action);
76         free (c);
77         break;
78       }
79 #endif /* ARITH_FOR_COMMAND */
80
81     case cm_group:
82       {
83         dispose_command (command->value.Group->command);
84         free (command->value.Group);
85         break;
86       }
87
88     case cm_subshell:
89       {
90         dispose_command (command->value.Subshell->command);
91         free (command->value.Subshell);
92         break;
93       }
94
95     case cm_case:
96       {
97         register CASE_COM *c;
98         PATTERN_LIST *t, *p;
99
100         c = command->value.Case;
101         dispose_word (c->word);
102
103         for (p = c->clauses; p; )
104           {
105             dispose_words (p->patterns);
106             dispose_command (p->action);
107             t = p;
108             p = p->next;
109             free (t);
110           }
111         free (c);
112         break;
113       }
114
115     case cm_until:
116     case cm_while:
117       {
118         register WHILE_COM *c;
119
120         c = command->value.While;
121         dispose_command (c->test);
122         dispose_command (c->action);
123         free (c);
124         break;
125       }
126
127     case cm_if:
128       {
129         register IF_COM *c;
130
131         c = command->value.If;
132         dispose_command (c->test);
133         dispose_command (c->true_case);
134         dispose_command (c->false_case);
135         free (c);
136         break;
137       }
138
139     case cm_simple:
140       {
141         register SIMPLE_COM *c;
142
143         c = command->value.Simple;
144         dispose_words (c->words);
145         dispose_redirects (c->redirects);
146         free (c);
147         break;
148       }
149
150     case cm_connection:
151       {
152         register CONNECTION *c;
153
154         c = command->value.Connection;
155         dispose_command (c->first);
156         dispose_command (c->second);
157         free (c);
158         break;
159       }
160
161 #if defined (DPAREN_ARITHMETIC)
162     case cm_arith:
163       {
164         register ARITH_COM *c;
165
166         c = command->value.Arith;
167         dispose_words (c->exp);
168         free (c);
169         break;
170       }
171 #endif /* DPAREN_ARITHMETIC */
172
173 #if defined (COND_COMMAND)
174     case cm_cond:
175       {
176         register COND_COM *c;
177
178         c = command->value.Cond;
179         dispose_cond_node (c);
180         break;
181       }
182 #endif /* COND_COMMAND */
183
184     case cm_function_def:
185       {
186         register FUNCTION_DEF *c;
187
188         c = command->value.Function_def;
189         dispose_function_def (c);
190         break;
191       }
192
193     default:
194       command_error ("dispose_command", CMDERR_BADTYPE, command->type, 0);
195       break;
196     }
197   free (command);
198 }
199
200 #if defined (COND_COMMAND)
201 /* How to free a node in a conditional command. */
202 void
203 dispose_cond_node (cond)
204      COND_COM *cond;
205 {
206   if (cond)
207     {
208       if (cond->left)
209         dispose_cond_node (cond->left);
210       if (cond->right)
211         dispose_cond_node (cond->right);
212       if (cond->op)
213         dispose_word (cond->op);
214       free (cond);
215     }
216 }
217 #endif /* COND_COMMAND */
218
219 void
220 dispose_function_def_contents (c)
221      FUNCTION_DEF *c;
222 {
223   dispose_word (c->name);
224   dispose_command (c->command);
225   FREE (c->source_file);
226 }
227
228 void
229 dispose_function_def (c)
230      FUNCTION_DEF *c;
231 {
232   dispose_function_def_contents (c);
233   free (c);
234 }
235
236 /* How to free a WORD_DESC. */
237 void
238 dispose_word (w)
239      WORD_DESC *w;
240 {
241   FREE (w->word);
242 #if 0
243   free (w);
244 #else
245   ocache_free (wdcache, WORD_DESC, w);
246 #endif
247 }
248
249 /* How to get rid of a linked list of words.  A WORD_LIST. */
250 void
251 dispose_words (list)
252      WORD_LIST *list;
253 {
254   WORD_LIST *t;
255
256   while (list)
257     {
258       t = list;
259       list = list->next;
260       dispose_word (t->word);
261 #if 0
262       free (t);
263 #else
264       ocache_free (wlcache, WORD_LIST, t);
265 #endif
266     }
267 }
268
269 #ifdef INCLUDE_UNUSED
270 /* How to dispose of an array of pointers to char.  This is identical to
271    free_array in stringlib.c. */
272 void
273 dispose_word_array (array)
274      char **array;
275 {
276   register int count;
277
278   if (array == 0)
279     return;
280
281   for (count = 0; array[count]; count++)
282     free (array[count]);
283
284   free (array);
285 }
286 #endif
287
288 /* How to dispose of an list of redirections.  A REDIRECT. */
289 void
290 dispose_redirects (list)
291      REDIRECT *list;
292 {
293   register REDIRECT *t;
294
295   while (list)
296     {
297       t = list;
298       list = list->next;
299       switch (t->instruction)
300         {
301         case r_reading_until:
302         case r_deblank_reading_until:
303           free (t->here_doc_eof);
304         /*FALLTHROUGH*/
305         case r_reading_string:
306         case r_output_direction:
307         case r_input_direction:
308         case r_inputa_direction:
309         case r_appending_to:
310         case r_err_and_out:
311         case r_input_output:
312         case r_output_force:
313         case r_duplicating_input_word:
314         case r_duplicating_output_word:
315         case r_move_input_word:
316         case r_move_output_word:
317           dispose_word (t->redirectee.filename);
318           /* FALLTHROUGH */
319         default:
320           break;
321         }
322       free (t);
323     }
324 }