]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/cleanups.c
* cleanups.h: New file.
[thirdparty/binutils-gdb.git] / gdb / cleanups.c
CommitLineData
c27f5738
DE
1/* Cleanup routines for GDB, the GNU debugger.
2
3 Copyright (C) 1986, 1988-2012 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21
22/* Chain of cleanup actions established with make_cleanup,
23 to be executed if an error happens. */
24
25/* Cleaned up after a failed command. */
26static struct cleanup *cleanup_chain;
27
28/* Cleaned up when gdb exits. */
29static struct cleanup *final_cleanup_chain;
30
31/* Main worker routine to create a cleanup.
32 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
33 FUNCTION is the function to call to perform the cleanup.
34 ARG is passed to FUNCTION when called.
35 FREE_ARG, if non-NULL, is called after the cleanup is performed.
36
37 The result is a pointer to the previous chain pointer
38 to be passed later to do_cleanups or discard_cleanups. */
39
40struct cleanup *
41make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
42 void *arg, void (*free_arg) (void *))
43{
44 struct cleanup *new
45 = (struct cleanup *) xmalloc (sizeof (struct cleanup));
46 struct cleanup *old_chain = *pmy_chain;
47
48 new->next = *pmy_chain;
49 new->function = function;
50 new->free_arg = free_arg;
51 new->arg = arg;
52 *pmy_chain = new;
53
54 return old_chain;
55}
56
57/* Worker routine to create a cleanup without a destructor.
58 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
59 FUNCTION is the function to call to perform the cleanup.
60 ARG is passed to FUNCTION when called.
61
62 The result is a pointer to the previous chain pointer
63 to be passed later to do_cleanups or discard_cleanups. */
64
65struct cleanup *
66make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
67 void *arg)
68{
69 return make_my_cleanup2 (pmy_chain, function, arg, NULL);
70}
71
72/* Add a new cleanup to the cleanup_chain,
73 and return the previous chain pointer
74 to be passed later to do_cleanups or discard_cleanups.
75 Args are FUNCTION to clean up with, and ARG to pass to it. */
76
77struct cleanup *
78make_cleanup (make_cleanup_ftype *function, void *arg)
79{
80 return make_my_cleanup (&cleanup_chain, function, arg);
81}
82
83/* Same as make_cleanup except also includes TDOR, a destructor to free ARG.
84 DTOR is invoked when the cleanup is performed or when it is discarded. */
85
86struct cleanup *
87make_cleanup_dtor (make_cleanup_ftype *function, void *arg,
88 void (*dtor) (void *))
89{
90 return make_my_cleanup2 (&cleanup_chain,
91 function, arg, dtor);
92}
93
94/* Same as make_cleanup except the cleanup is added to final_cleanup_chain. */
95
96struct cleanup *
97make_final_cleanup (make_cleanup_ftype *function, void *arg)
98{
99 return make_my_cleanup (&final_cleanup_chain, function, arg);
100}
101
102/* Worker routine to perform cleanups.
103 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
104 OLD_CHAIN is the result of a "make" cleanup routine.
105 Cleanups are performed until we get back to the old end of the chain. */
106
107static void
108do_my_cleanups (struct cleanup **pmy_chain,
109 struct cleanup *old_chain)
110{
111 struct cleanup *ptr;
112
113 while ((ptr = *pmy_chain) != old_chain)
114 {
115 *pmy_chain = ptr->next; /* Do this first in case of recursion. */
116 (*ptr->function) (ptr->arg);
117 if (ptr->free_arg)
118 (*ptr->free_arg) (ptr->arg);
119 xfree (ptr);
120 }
121}
122
123/* Discard cleanups and do the actions they describe
124 until we get back to the point OLD_CHAIN in the cleanup_chain. */
125
126void
127do_cleanups (struct cleanup *old_chain)
128{
129 do_my_cleanups (&cleanup_chain, old_chain);
130}
131
132/* Discard cleanups and do the actions they describe
133 until we get back to the point OLD_CHAIN in the final_cleanup_chain. */
134
135void
136do_final_cleanups (struct cleanup *old_chain)
137{
138 do_my_cleanups (&final_cleanup_chain, old_chain);
139}
140
141/* Main worker routine to discard cleanups.
142 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
143 OLD_CHAIN is the result of a "make" cleanup routine.
144 Cleanups are discarded until we get back to the old end of the chain. */
145
146void
147discard_my_cleanups (struct cleanup **pmy_chain,
148 struct cleanup *old_chain)
149{
150 struct cleanup *ptr;
151
152 while ((ptr = *pmy_chain) != old_chain)
153 {
154 *pmy_chain = ptr->next;
155 if (ptr->free_arg)
156 (*ptr->free_arg) (ptr->arg);
157 xfree (ptr);
158 }
159}
160
161/* Discard cleanups, not doing the actions they describe,
162 until we get back to the point OLD_CHAIN in the cleanup chain. */
163
164void
165discard_cleanups (struct cleanup *old_chain)
166{
167 discard_my_cleanups (&cleanup_chain, old_chain);
168}
169
170/* Discard final cleanups, not doing the actions they describe,
171 until we get back to the point OLD_CHAIN in the final cleanup chain. */
172
173void
174discard_final_cleanups (struct cleanup *old_chain)
175{
176 discard_my_cleanups (&final_cleanup_chain, old_chain);
177}
178
179/* Main worker routine to save cleanups.
180 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
181 The chain is emptied and the result is a pointer to the old chain. */
182
183struct cleanup *
184save_my_cleanups (struct cleanup **pmy_chain)
185{
186 struct cleanup *old_chain = *pmy_chain;
187
188 *pmy_chain = 0;
189 return old_chain;
190}
191
192/* Set the cleanup_chain to 0, and return the old cleanup_chain. */
193
194struct cleanup *
195save_cleanups (void)
196{
197 return save_my_cleanups (&cleanup_chain);
198}
199
200/* Set the final_cleanup_chain to 0, and return the old
201 final_cleanup_chain. */
202
203struct cleanup *
204save_final_cleanups (void)
205{
206 return save_my_cleanups (&final_cleanup_chain);
207}
208
209/* Main worker routine to save cleanups.
210 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
211 The chain is restored from CHAIN. */
212
213void
214restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain)
215{
216 *pmy_chain = chain;
217}
218
219/* Restore the cleanup chain from a previously saved chain. */
220
221void
222restore_cleanups (struct cleanup *chain)
223{
224 restore_my_cleanups (&cleanup_chain, chain);
225}
226
227/* Restore the final cleanup chain from a previously saved chain. */
228
229void
230restore_final_cleanups (struct cleanup *chain)
231{
232 restore_my_cleanups (&final_cleanup_chain, chain);
233}
234
235/* Provide a known function that does nothing, to use as a base for
236 a possibly long chain of cleanups. This is useful where we
237 use the cleanup chain for handling normal cleanups as well as dealing
238 with cleanups that need to be done as a result of a call to error().
239 In such cases, we may not be certain where the first cleanup is, unless
240 we have a do-nothing one to always use as the base. */
241
242void
243null_cleanup (void *arg)
244{
245}