gdb/copyright.py: Do not update gdbsupport/Makefile.in
[deliverable/binutils-gdb.git] / gdbsupport / cleanups.cc
CommitLineData
c27f5738
DE
1/* Cleanup routines for GDB, the GNU debugger.
2
3666a048 3 Copyright (C) 1986-2021 Free Software Foundation, Inc.
c27f5738
DE
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
e3180625
GB
20#include "common-defs.h"
21#include "cleanups.h"
b10faa68
DE
22
23/* The cleanup list records things that have to be undone
24 if an error happens (descriptors to be closed, memory to be freed, etc.)
25 Each link in the chain records a function to call and an
26 argument to give it.
27
28 Use make_cleanup to add an element to the cleanup chain.
29 Use do_cleanups to do all cleanup actions back to a given
30 point in the chain. Use discard_cleanups to remove cleanups
31 from the chain back to a given point, not doing them.
32
33 If the argument is pointer to allocated memory, then you need
34 to additionally set the 'free_arg' member to a function that will
35 free that memory. This function will be called both when the cleanup
36 is executed and when it's discarded. */
37
38struct cleanup
39{
40 struct cleanup *next;
41 void (*function) (void *);
42 void (*free_arg) (void *);
43 void *arg;
44};
45
46/* Used to mark the end of a cleanup chain.
47 The value is chosen so that it:
48 - is non-NULL so that make_cleanup never returns NULL,
49 - causes a segv if dereferenced
50 [though this won't catch errors that a value of, say,
51 ((struct cleanup *) -1) will]
52 - displays as something useful when printed in gdb.
53 This is const for a bit of extra robustness.
54 It is initialized to coax gcc into putting it into .rodata.
55 All fields are initialized to survive -Wextra. */
56static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 };
57
58/* Handy macro to use when referring to sentinel_cleanup. */
59#define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup)
c27f5738 60
b10faa68
DE
61/* Chain of cleanup actions established with make_final_cleanup,
62 to be executed when gdb exits. */
63static struct cleanup *final_cleanup_chain = SENTINEL_CLEANUP;
c27f5738
DE
64
65/* Main worker routine to create a cleanup.
66 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
67 FUNCTION is the function to call to perform the cleanup.
68 ARG is passed to FUNCTION when called.
69 FREE_ARG, if non-NULL, is called after the cleanup is performed.
70
71 The result is a pointer to the previous chain pointer
72 to be passed later to do_cleanups or discard_cleanups. */
73
58d5e2c3 74static struct cleanup *
c27f5738
DE
75make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
76 void *arg, void (*free_arg) (void *))
77{
8d749320 78 struct cleanup *newobj = XNEW (struct cleanup);
c27f5738
DE
79 struct cleanup *old_chain = *pmy_chain;
80
fe978cb0
PA
81 newobj->next = *pmy_chain;
82 newobj->function = function;
83 newobj->free_arg = free_arg;
84 newobj->arg = arg;
85 *pmy_chain = newobj;
c27f5738 86
b10faa68 87 gdb_assert (old_chain != NULL);
c27f5738
DE
88 return old_chain;
89}
90
91/* Worker routine to create a cleanup without a destructor.
92 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
93 FUNCTION is the function to call to perform the cleanup.
94 ARG is passed to FUNCTION when called.
95
96 The result is a pointer to the previous chain pointer
97 to be passed later to do_cleanups or discard_cleanups. */
98
58d5e2c3 99static struct cleanup *
c27f5738
DE
100make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
101 void *arg)
102{
103 return make_my_cleanup2 (pmy_chain, function, arg, NULL);
104}
105
fe7b42e5 106/* Add a new cleanup to the final cleanup_chain,
c27f5738
DE
107 and return the previous chain pointer
108 to be passed later to do_cleanups or discard_cleanups.
109 Args are FUNCTION to clean up with, and ARG to pass to it. */
110
c27f5738
DE
111struct cleanup *
112make_final_cleanup (make_cleanup_ftype *function, void *arg)
113{
114 return make_my_cleanup (&final_cleanup_chain, function, arg);
115}
116
117/* Worker routine to perform cleanups.
118 PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
119 OLD_CHAIN is the result of a "make" cleanup routine.
120 Cleanups are performed until we get back to the old end of the chain. */
121
122static void
123do_my_cleanups (struct cleanup **pmy_chain,
124 struct cleanup *old_chain)
125{
126 struct cleanup *ptr;
127
128 while ((ptr = *pmy_chain) != old_chain)
129 {
130 *pmy_chain = ptr->next; /* Do this first in case of recursion. */
131 (*ptr->function) (ptr->arg);
132 if (ptr->free_arg)
133 (*ptr->free_arg) (ptr->arg);
134 xfree (ptr);
135 }
136}
137
fe7b42e5 138/* Discard final cleanups and do the actions they describe. */
c27f5738
DE
139
140void
fe7b42e5 141do_final_cleanups ()
c27f5738 142{
fe7b42e5 143 do_my_cleanups (&final_cleanup_chain, SENTINEL_CLEANUP);
c27f5738 144}
This page took 1.196084 seconds and 4 git commands to generate.