06b3c5bdb0
This patch renames the .c source files in gdbsupport to .cc. In the gdb directory, there is an argument against renaming the source files, which is that it makes using some git commands more difficult to do archeology. Some commands have some kind of "follow" option that makes git try to follow renames, but it doesn't work in all situations. Given that we have just moved the gdbsupport directory, that argument doesn't hold for source files in that directory. I therefore suggest renaming them to .cc, so that they are automatically recognized as C++ by various tools and editors. The original motivation behind this is that when building gdbsupport with clang, I get: CC agent.o clang: error: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Werror,-Wdeprecated] In the gdb/ directory, we make clang happy by passing "-x c++". We could do this in gdbsupport too, but I think that renaming the files is a better long-term solution. gdbserver still does its own build of gdbsupport, so a few changes in its Makefile are necessary. gdbsupport/ChangeLog: * Makefile.am: Rename source files from .c to .cc. (CC, CFLAGS): Don't override. (AM_CFLAGS): Rename to ... (AM_CXXFLAGS): ... this. * Makefile.in: Re-generate. * %.c: Rename to %.cc. gdbserver/ChangeLog: * Makefile.in: Rename gdbsupport source files from .c to .cc.
145 lines
4.9 KiB
C++
145 lines
4.9 KiB
C++
/* Cleanup routines for GDB, the GNU debugger.
|
|
|
|
Copyright (C) 1986-2020 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program 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.
|
|
|
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "common-defs.h"
|
|
#include "cleanups.h"
|
|
|
|
/* The cleanup list records things that have to be undone
|
|
if an error happens (descriptors to be closed, memory to be freed, etc.)
|
|
Each link in the chain records a function to call and an
|
|
argument to give it.
|
|
|
|
Use make_cleanup to add an element to the cleanup chain.
|
|
Use do_cleanups to do all cleanup actions back to a given
|
|
point in the chain. Use discard_cleanups to remove cleanups
|
|
from the chain back to a given point, not doing them.
|
|
|
|
If the argument is pointer to allocated memory, then you need
|
|
to additionally set the 'free_arg' member to a function that will
|
|
free that memory. This function will be called both when the cleanup
|
|
is executed and when it's discarded. */
|
|
|
|
struct cleanup
|
|
{
|
|
struct cleanup *next;
|
|
void (*function) (void *);
|
|
void (*free_arg) (void *);
|
|
void *arg;
|
|
};
|
|
|
|
/* Used to mark the end of a cleanup chain.
|
|
The value is chosen so that it:
|
|
- is non-NULL so that make_cleanup never returns NULL,
|
|
- causes a segv if dereferenced
|
|
[though this won't catch errors that a value of, say,
|
|
((struct cleanup *) -1) will]
|
|
- displays as something useful when printed in gdb.
|
|
This is const for a bit of extra robustness.
|
|
It is initialized to coax gcc into putting it into .rodata.
|
|
All fields are initialized to survive -Wextra. */
|
|
static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 };
|
|
|
|
/* Handy macro to use when referring to sentinel_cleanup. */
|
|
#define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup)
|
|
|
|
/* Chain of cleanup actions established with make_final_cleanup,
|
|
to be executed when gdb exits. */
|
|
static struct cleanup *final_cleanup_chain = SENTINEL_CLEANUP;
|
|
|
|
/* Main worker routine to create a cleanup.
|
|
PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
|
|
FUNCTION is the function to call to perform the cleanup.
|
|
ARG is passed to FUNCTION when called.
|
|
FREE_ARG, if non-NULL, is called after the cleanup is performed.
|
|
|
|
The result is a pointer to the previous chain pointer
|
|
to be passed later to do_cleanups or discard_cleanups. */
|
|
|
|
static struct cleanup *
|
|
make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
|
|
void *arg, void (*free_arg) (void *))
|
|
{
|
|
struct cleanup *newobj = XNEW (struct cleanup);
|
|
struct cleanup *old_chain = *pmy_chain;
|
|
|
|
newobj->next = *pmy_chain;
|
|
newobj->function = function;
|
|
newobj->free_arg = free_arg;
|
|
newobj->arg = arg;
|
|
*pmy_chain = newobj;
|
|
|
|
gdb_assert (old_chain != NULL);
|
|
return old_chain;
|
|
}
|
|
|
|
/* Worker routine to create a cleanup without a destructor.
|
|
PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
|
|
FUNCTION is the function to call to perform the cleanup.
|
|
ARG is passed to FUNCTION when called.
|
|
|
|
The result is a pointer to the previous chain pointer
|
|
to be passed later to do_cleanups or discard_cleanups. */
|
|
|
|
static struct cleanup *
|
|
make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
|
|
void *arg)
|
|
{
|
|
return make_my_cleanup2 (pmy_chain, function, arg, NULL);
|
|
}
|
|
|
|
/* Add a new cleanup to the final cleanup_chain,
|
|
and return the previous chain pointer
|
|
to be passed later to do_cleanups or discard_cleanups.
|
|
Args are FUNCTION to clean up with, and ARG to pass to it. */
|
|
|
|
struct cleanup *
|
|
make_final_cleanup (make_cleanup_ftype *function, void *arg)
|
|
{
|
|
return make_my_cleanup (&final_cleanup_chain, function, arg);
|
|
}
|
|
|
|
/* Worker routine to perform cleanups.
|
|
PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
|
|
OLD_CHAIN is the result of a "make" cleanup routine.
|
|
Cleanups are performed until we get back to the old end of the chain. */
|
|
|
|
static void
|
|
do_my_cleanups (struct cleanup **pmy_chain,
|
|
struct cleanup *old_chain)
|
|
{
|
|
struct cleanup *ptr;
|
|
|
|
while ((ptr = *pmy_chain) != old_chain)
|
|
{
|
|
*pmy_chain = ptr->next; /* Do this first in case of recursion. */
|
|
(*ptr->function) (ptr->arg);
|
|
if (ptr->free_arg)
|
|
(*ptr->free_arg) (ptr->arg);
|
|
xfree (ptr);
|
|
}
|
|
}
|
|
|
|
/* Discard final cleanups and do the actions they describe. */
|
|
|
|
void
|
|
do_final_cleanups ()
|
|
{
|
|
do_my_cleanups (&final_cleanup_chain, SENTINEL_CLEANUP);
|
|
}
|