This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [RFA 2/2] C++-ify break-catch-throw
On 06/05/2017 01:29 PM, Pedro Alves wrote:
> On 06/05/2017 11:36 AM, Pedro Alves wrote:
>> On 06/05/2017 11:33 AM, Pedro Alves wrote:
>>> class gdb_regex
>>> {
>>> public:
>>> // replaces old compile_rx_or_error
>>> gdb_regex (const char *rx, const char *message)
>>> {
>>
>> Maybe call it "compiled_regex" instead, since you wouldn't
>> be able to end up with a not-compiled-yet regex with this.
>>
>
> So something like this. Builds and gdb starts, but I have
> not regtested it.
>
> In a couple places, this either forces moving the regex object
> to the heap, or to wrap it in gdb::optional. In the cases
> where we already have to keep the regex string around,
> it ends up being not maximally efficient memory-wise, but I don't
> think it really matters. We're considering std::string for
> those same strings, which grows the structs more than that, anyway
> (for size/capacity).
>
> For linux-tdep.cmapping_is_anonymous_p, I was first considering
> std::aligned_storage, but switched back to gdb::optional before posting,
> because std::aligned_storage complicates the code a little bit (I mean, forces
> readers to learn about std::aligned_storage while here the redundant
> "has value" variable that gdb::optional has internally doesn't really
> matter. We could move the mapping_regexes struct to the heap too, since is
> a one-shot initialization. (I see now that I left the "tristate" comment behind.)
>
> I didn't use "compiled_regex" for struct name, simply because "gdb_regex.h"
> already existed. But I'd still consider renaming it.
>
> WDYT?
>
Forgot to "git add" the new file... Trying again.
>From 529e26f36ae5ed1f7ee7d375d54843d0b435cf83 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 5 Jun 2017 12:48:46 +0100
Subject: [PATCH] gdb_regex
---
gdb/Makefile.in | 2 ++
gdb/ada-lang.c | 30 ++++++----------
gdb/break-catch-throw.c | 21 +++++------
gdb/breakpoint.c | 19 +++-------
gdb/cli/cli-cmds.c | 21 ++---------
gdb/cli/cli-decode.c | 11 +++---
gdb/cli/cli-decode.h | 5 ++-
gdb/gdb_regex.c | 59 +++++++++++++++++++++++++++++++
gdb/gdb_regex.h | 26 +++++++++++---
gdb/linux-tdep.c | 93 +++++++++++++++++++++++++------------------------
gdb/probe.c | 19 +++++-----
gdb/skip.c | 24 +++----------
gdb/symtab.c | 42 ++++++++--------------
gdb/utils.c | 52 ---------------------------
14 files changed, 194 insertions(+), 230 deletions(-)
create mode 100644 gdb/gdb_regex.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8be73ba..2156438 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1104,6 +1104,7 @@ SFILES = \
gdb_bfd.c \
gdb-dlfcn.c \
gdb_obstack.c \
+ gdb_regex.c \
gdb_usleep.c \
gdbarch.c \
gdbarch-selftests.c \
@@ -1717,6 +1718,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
gdb_bfd.o \
gdb-dlfcn.o \
gdb_obstack.o \
+ gdb_regex.o \
gdb_usleep.o \
gdb_vecs.o \
gdbarch.o \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index f90907a..e338cd1 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13219,14 +13219,14 @@ sort_remove_dups_ada_exceptions_list (VEC(ada_exc_info) **exceptions,
gets pushed. */
static void
-ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+ada_add_standard_exceptions (gdb_regex *preg, VEC(ada_exc_info) **exceptions)
{
int i;
for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
{
if (preg == NULL
- || regexec (preg, standard_exc[i], 0, NULL, 0) == 0)
+ || preg->exec (standard_exc[i], 0, NULL, 0) == 0)
{
struct bound_minimal_symbol msymbol
= ada_lookup_simple_minsym (standard_exc[i]);
@@ -13253,7 +13253,7 @@ ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
gets pushed. */
static void
-ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
+ada_add_exceptions_from_frame (gdb_regex *preg, struct frame_info *frame,
VEC(ada_exc_info) **exceptions)
{
const struct block *block = get_frame_block (frame, 0);
@@ -13290,10 +13290,10 @@ ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
/* Return true if NAME matches PREG or if PREG is NULL. */
static bool
-name_matches_regex (const char *name, regex_t *preg)
+name_matches_regex (const char *name, gdb_regex *preg)
{
return (preg == NULL
- || regexec (preg, ada_decode (name), 0, NULL, 0) == 0);
+ || preg->exec (ada_decode (name), 0, NULL, 0) == 0);
}
/* Add all exceptions defined globally whose name name match
@@ -13316,7 +13316,7 @@ name_matches_regex (const char *name, regex_t *preg)
gets pushed. */
static void
-ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+ada_add_global_exceptions (gdb_regex *preg, VEC(ada_exc_info) **exceptions)
{
struct objfile *objfile;
struct compunit_symtab *s;
@@ -13364,7 +13364,7 @@ ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
do not match. Otherwise, all exceptions are listed. */
static VEC(ada_exc_info) *
-ada_exceptions_list_1 (regex_t *preg)
+ada_exceptions_list_1 (gdb_regex *preg)
{
VEC(ada_exc_info) *result = NULL;
struct cleanup *old_chain
@@ -13417,19 +13417,11 @@ ada_exceptions_list_1 (regex_t *preg)
VEC(ada_exc_info) *
ada_exceptions_list (const char *regexp)
{
- VEC(ada_exc_info) *result = NULL;
- struct cleanup *old_chain = NULL;
- regex_t reg;
-
- if (regexp != NULL)
- old_chain = compile_rx_or_error (®, regexp,
- _("invalid regular expression"));
+ if (regexp == NULL)
+ return ada_exceptions_list_1 (NULL);
- result = ada_exceptions_list_1 (regexp != NULL ? ® : NULL);
-
- if (old_chain != NULL)
- do_cleanups (old_chain);
- return result;
+ gdb_regex reg (regexp, REG_NOSUB, _("invalid regular expression"));
+ return ada_exceptions_list_1 (®);
}
/* Implement the "info exceptions" command. */
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 7731c5e..49d5180 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -87,10 +87,10 @@ struct exception_catchpoint : public breakpoint
char *exception_rx;
- /* If non-NULL, an xmalloc'd, compiled regular expression which is
- used to determine which exceptions to stop on. */
+ /* If non-NULL, a compiled regular expression which is used to
+ determine which exceptions to stop on. */
- regex_t *pattern;
+ std::unique_ptr<gdb_regex> pattern;
};
@@ -145,8 +145,6 @@ classify_exception_breakpoint (struct breakpoint *b)
exception_catchpoint::~exception_catchpoint ()
{
xfree (this->exception_rx);
- if (this->pattern != NULL)
- regfree (this->pattern);
}
/* Implement the 'check_status' method. */
@@ -185,7 +183,7 @@ check_status_exception_catchpoint (struct bpstats *bs)
if (!type_name.empty ())
{
- if (regexec (self->pattern, type_name.c_str (), 0, NULL, 0) != 0)
+ if (self->pattern->exec (type_name.c_str (), 0, NULL, 0) != 0)
bs->stop = 0;
}
}
@@ -377,15 +375,12 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx,
const char *cond_string,
enum exception_event_kind ex_event, int from_tty)
{
- regex_t *pattern = NULL;
+ std::unique_ptr<gdb_regex> pattern;
if (except_rx != NULL)
{
- pattern = XNEW (regex_t);
- make_cleanup (xfree, pattern);
-
- compile_rx_or_error (pattern, except_rx,
- _("invalid type-matching regexp"));
+ pattern.reset (new gdb_regex (except_rx, REG_NOSUB,
+ _("invalid type-matching regexp")));
}
std::unique_ptr<exception_catchpoint> cp (new exception_catchpoint ());
@@ -397,7 +392,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx,
cp->type = bp_breakpoint;
cp->kind = ex_event;
cp->exception_rx = except_rx;
- cp->pattern = pattern;
+ cp->pattern = std::move (pattern);
re_set_exception_catchpoint (cp.get ());
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0dc9841..b78cf2b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -8282,13 +8282,11 @@ struct solib_catchpoint : public breakpoint
/* Regular expression to match, if any. COMPILED is only valid when
REGEX is non-NULL. */
char *regex;
- regex_t compiled;
+ std::unique_ptr<gdb_regex> compiled;
};
solib_catchpoint::~solib_catchpoint ()
{
- if (this->regex)
- regfree (&this->compiled);
xfree (this->regex);
}
@@ -8356,7 +8354,7 @@ check_status_catch_solib (struct bpstats *bs)
++ix)
{
if (!self->regex
- || regexec (&self->compiled, iter->so_name, 0, NULL, 0) == 0)
+ || self->compiled->exec (iter->so_name, 0, NULL, 0) == 0)
return;
}
}
@@ -8370,7 +8368,7 @@ check_status_catch_solib (struct bpstats *bs)
++ix)
{
if (!self->regex
- || regexec (&self->compiled, iter, 0, NULL, 0) == 0)
+ || self->compiled->exec (iter, 0, NULL, 0) == 0)
return;
}
}
@@ -8486,16 +8484,7 @@ add_solib_catchpoint (const char *arg, int is_load, int is_temp, int enabled)
if (*arg != '\0')
{
- int errcode;
-
- errcode = regcomp (&c->compiled, arg, REG_NOSUB);
- if (errcode != 0)
- {
- char *err = get_regcomp_error (errcode, &c->compiled);
-
- make_cleanup (xfree, err);
- error (_("Invalid regexp (%s): %s"), err, arg);
- }
+ c->compiled.reset (new gdb_regex (arg, REG_NOSUB, _("Invalid regexp")));
c->regex = xstrdup (arg);
}
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2a5b128..3aedecd 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1336,28 +1336,13 @@ show_user (char *args, int from_tty)
static void
apropos_command (char *searchstr, int from_tty)
{
- regex_t pattern;
- int code;
-
if (searchstr == NULL)
error (_("REGEXP string is empty"));
- code = regcomp (&pattern, searchstr, REG_ICASE);
- if (code == 0)
- {
- struct cleanup *cleanups;
+ gdb_regex pattern (searchstr, REG_ICASE,
+ _("Error in regular expression"));
- cleanups = make_regfree_cleanup (&pattern);
- apropos_cmd (gdb_stdout, cmdlist, &pattern, "");
- do_cleanups (cleanups);
- }
- else
- {
- char *err = get_regcomp_error (code, &pattern);
-
- make_cleanup (xfree, err);
- error (_("Error in regular expression: %s"), err);
- }
+ apropos_cmd (gdb_stdout, cmdlist, &pattern, "");
}
/* Subroutine of alias_command to simplify it.
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index d386d02..87ac0d5 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -917,7 +917,7 @@ add_com_suppress_notification (const char *name, enum command_class theclass,
void
apropos_cmd (struct ui_file *stream,
struct cmd_list_element *commandlist,
- struct re_pattern_buffer *regex, const char *prefix)
+ gdb_regex *regex, const char *prefix)
{
struct cmd_list_element *c;
int returnvalue;
@@ -928,9 +928,10 @@ apropos_cmd (struct ui_file *stream,
returnvalue = -1; /* Needed to avoid double printing. */
if (c->name != NULL)
{
+ size_t name_len = strlen (c->name);
+
/* Try to match against the name. */
- returnvalue = re_search (regex, c->name, strlen(c->name),
- 0, strlen (c->name), NULL);
+ returnvalue = regex->search (c->name, name_len, 0, name_len, NULL);
if (returnvalue >= 0)
{
print_help_for_command (c, prefix,
@@ -939,8 +940,10 @@ apropos_cmd (struct ui_file *stream,
}
if (c->doc != NULL && returnvalue < 0)
{
+ size_t doc_len = strlen (c->doc);
+
/* Try to match against documentation. */
- if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0)
+ if (regex->search (c->doc, doc_len, 0, doc_len, NULL) >= 0)
{
print_help_for_command (c, prefix,
0 /* don't recurse */, stream);
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index 66159fd..b8f2f7c 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -23,8 +23,7 @@
/* Include the public interfaces. */
#include "command.h"
-
-struct re_pattern_buffer;
+#include "gdb_regex.h"
#if 0
/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum
@@ -234,7 +233,7 @@ extern void help_cmd_list (struct cmd_list_element *, enum command_class,
extern void help_cmd (const char *, struct ui_file *);
extern void apropos_cmd (struct ui_file *, struct cmd_list_element *,
- struct re_pattern_buffer *, const char *);
+ gdb_regex *, const char *);
/* Used to mark commands that don't do anything. If we just leave the
function field NULL, the command is interpreted as a help topic, or
diff --git a/gdb/gdb_regex.c b/gdb/gdb_regex.c
new file mode 100644
index 0000000..06c4666
--- /dev/null
+++ b/gdb/gdb_regex.c
@@ -0,0 +1,59 @@
+/* Portable <regex.h>.
+
+ Copyright (C) 1986-2017 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 "defs.h"
+#include "gdb_regex.h"
+
+/* See gdb_regex.h. */
+
+gdb_regex::gdb_regex (const char *regex, int cflags,
+ const char *message)
+{
+ gdb_assert (regex != NULL);
+
+ int code = regcomp (&m_pattern, regex, cflags);
+ if (code != 0)
+ {
+ size_t length = regerror (code, &m_pattern, NULL, 0);
+ std::unique_ptr<char[]> err (new char[length]);
+
+ regerror (code, &m_pattern, err.get (), length);
+ error (("%s: %s"), message, err.get ());
+ }
+}
+
+gdb_regex::~gdb_regex ()
+{
+ regfree (&m_pattern);
+}
+
+int
+gdb_regex::exec (const char *string, size_t nmatch,
+ regmatch_t pmatch[], int eflags)
+{
+ return regexec (&m_pattern, string, nmatch, pmatch, eflags);
+}
+
+int
+gdb_regex::search (const char *string,
+ int length, int start, int range,
+ struct re_registers *regs)
+{
+ return re_search (&m_pattern, string, length, start, range, regs);
+}
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
index 0be26ef..2b0a5a0 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -27,10 +27,26 @@
# include <regex.h>
#endif
-/* From utils.c. */
-struct cleanup *make_regfree_cleanup (regex_t *);
-char *get_regcomp_error (int, regex_t *);
-struct cleanup *compile_rx_or_error (regex_t *pattern, const char *rx,
- const char *message);
+/* A compiled regex. */
+
+class gdb_regex
+{
+public:
+ /* Compile a regexp and throw an exception on error, including
+ MESSAGE. REGEX and MESSAGE must not be NULL. */
+ gdb_regex (const char *regex, int cflags,
+ const char *message);
+ ~gdb_regex ();
+
+ /* Wrapper around ::regexec. */
+ int exec (const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+
+ /* Wrapper around ::re_search. */
+ int search (const char *string, int size,
+ int startpos, int range, struct re_registers *regs);
+
+private:
+ regex_t m_pattern;
+};
#endif /* not GDB_REGEX_H */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 016aadf..f424947 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -38,6 +38,7 @@
#include "gdbcmd.h"
#include "gdb_regex.h"
#include "common/enum-flags.h"
+#include "common/gdb_optional.h"
#include <ctype.h>
@@ -493,6 +494,47 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
}
}
+struct mapping_regexes
+{
+ mapping_regexes ()
+ : dev_zero
+ ("^/dev/zero\\( (deleted)\\)\\?$", REG_NOSUB,
+ _("Could not compile regex to match /dev/zero filename")),
+ shmem_file
+ ("^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$", REG_NOSUB,
+ _("Could not compile regex to match shmem filenames")),
+ file_deleted
+ (" (deleted)$", REG_NOSUB,
+ _("Could not compile regex to match '<file> (deleted)'"))
+ {}
+
+ /* Matches "/dev/zero" filenames (with or without the "(deleted)"
+ string in the end). We know for sure, based on the Linux kernel
+ code, that memory mappings whose associated filename is
+ "/dev/zero" are guaranteed to be MAP_ANONYMOUS. */
+ gdb_regex dev_zero;
+
+ /* Matches "/SYSV%08x" filenames (with or without the "(deleted)"
+ string in the end). These filenames refer to shared memory
+ (shmem), and memory mappings associated with them are
+ MAP_ANONYMOUS as well. */
+ gdb_regex shmem_file;
+
+ /* A heuristic we use to try to mimic the Linux kernel's 'n_link ==
+ 0' code, which is responsible to decide if it is dealing with a
+ 'MAP_SHARED | MAP_ANONYMOUS' mapping. In other words, if
+ FILE_DELETED matches, it does not necessarily mean that we are
+ dealing with an anonymous shared mapping. However, there is no
+ easy way to detect this currently, so this is the best
+ approximation we have.
+
+ As a result, GDB will dump readonly pages of deleted executables
+ when using the default value of coredump_filter (0x33), while the
+ Linux kernel will not dump those pages. But we can live with
+ that. */
+ gdb_regex file_deleted;
+};
+
/* Return 1 if the memory mapping is anonymous, 0 otherwise.
FILENAME is the name of the file present in the first line of the
@@ -506,52 +548,13 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
static int
mapping_is_anonymous_p (const char *filename)
{
- static regex_t dev_zero_regex, shmem_file_regex, file_deleted_regex;
+ /* Like gdb::optional, but tristate. */
static int init_regex_p = 0;
+ static gdb::optional<mapping_regexes> regexes;
if (!init_regex_p)
{
- struct cleanup *c = make_cleanup (null_cleanup, NULL);
-
- /* Let's be pessimistic and assume there will be an error while
- compiling the regex'es. */
- init_regex_p = -1;
-
- /* DEV_ZERO_REGEX matches "/dev/zero" filenames (with or
- without the "(deleted)" string in the end). We know for
- sure, based on the Linux kernel code, that memory mappings
- whose associated filename is "/dev/zero" are guaranteed to be
- MAP_ANONYMOUS. */
- compile_rx_or_error (&dev_zero_regex, "^/dev/zero\\( (deleted)\\)\\?$",
- _("Could not compile regex to match /dev/zero "
- "filename"));
- /* SHMEM_FILE_REGEX matches "/SYSV%08x" filenames (with or
- without the "(deleted)" string in the end). These filenames
- refer to shared memory (shmem), and memory mappings
- associated with them are MAP_ANONYMOUS as well. */
- compile_rx_or_error (&shmem_file_regex,
- "^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$",
- _("Could not compile regex to match shmem "
- "filenames"));
- /* FILE_DELETED_REGEX is a heuristic we use to try to mimic the
- Linux kernel's 'n_link == 0' code, which is responsible to
- decide if it is dealing with a 'MAP_SHARED | MAP_ANONYMOUS'
- mapping. In other words, if FILE_DELETED_REGEX matches, it
- does not necessarily mean that we are dealing with an
- anonymous shared mapping. However, there is no easy way to
- detect this currently, so this is the best approximation we
- have.
-
- As a result, GDB will dump readonly pages of deleted
- executables when using the default value of coredump_filter
- (0x33), while the Linux kernel will not dump those pages.
- But we can live with that. */
- compile_rx_or_error (&file_deleted_regex, " (deleted)$",
- _("Could not compile regex to match "
- "'<file> (deleted)'"));
- /* We will never release these regexes, so just discard the
- cleanups. */
- discard_cleanups (c);
+ regexes.emplace ();
/* If we reached this point, then everything succeeded. */
init_regex_p = 1;
@@ -573,9 +576,9 @@ mapping_is_anonymous_p (const char *filename)
}
if (*filename == '\0'
- || regexec (&dev_zero_regex, filename, 0, NULL, 0) == 0
- || regexec (&shmem_file_regex, filename, 0, NULL, 0) == 0
- || regexec (&file_deleted_regex, filename, 0, NULL, 0) == 0)
+ || regexes->dev_zero.exec (filename, 0, NULL, 0) == 0
+ || regexes->shmem_file.exec (filename, 0, NULL, 0) == 0
+ || regexes->file_deleted.exec (filename, 0, NULL, 0) == 0)
return 1;
return 0;
diff --git a/gdb/probe.c b/gdb/probe.c
index e65e031..c8b92f3 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -36,6 +36,7 @@
#include "location.h"
#include <ctype.h>
#include <algorithm>
+#include "common/gdb_optional.h"
typedef struct bound_probe bound_probe_s;
DEF_VEC_O (bound_probe_s);
@@ -288,18 +289,17 @@ collect_probes (char *objname, char *provider, char *probe_name,
{
struct objfile *objfile;
VEC (bound_probe_s) *result = NULL;
- struct cleanup *cleanup, *cleanup_temps;
- regex_t obj_pat, prov_pat, probe_pat;
+ struct cleanup *cleanup;
+ gdb::optional<gdb_regex> obj_pat, prov_pat, probe_pat;
cleanup = make_cleanup (VEC_cleanup (bound_probe_s), &result);
- cleanup_temps = make_cleanup (null_cleanup, NULL);
if (provider != NULL)
- compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp"));
+ prov_pat.emplace (provider, REG_NOSUB, _("Invalid provider regexp"));
if (probe_name != NULL)
- compile_rx_or_error (&probe_pat, probe_name, _("Invalid probe regexp"));
+ probe_pat.emplace (probe_name, REG_NOSUB, _("Invalid probe regexp"));
if (objname != NULL)
- compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp"));
+ obj_pat.emplace (objname, REG_NOSUB, _("Invalid object file regexp"));
ALL_OBJFILES (objfile)
{
@@ -312,7 +312,7 @@ collect_probes (char *objname, char *provider, char *probe_name,
if (objname)
{
- if (regexec (&obj_pat, objfile_name (objfile), 0, NULL, 0) != 0)
+ if (obj_pat->exec (objfile_name (objfile), 0, NULL, 0) != 0)
continue;
}
@@ -326,11 +326,11 @@ collect_probes (char *objname, char *provider, char *probe_name,
continue;
if (provider
- && regexec (&prov_pat, probe->provider, 0, NULL, 0) != 0)
+ && prov_pat->exec (probe->provider, 0, NULL, 0) != 0)
continue;
if (probe_name
- && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0)
+ && probe_pat->exec (probe->name, 0, NULL, 0) != 0)
continue;
bound.objfile = objfile;
@@ -339,7 +339,6 @@ collect_probes (char *objname, char *provider, char *probe_name,
}
}
- do_cleanups (cleanup_temps);
discard_cleanups (cleanup);
return result;
}
diff --git a/gdb/skip.c b/gdb/skip.c
index 4bd8a9e..65583d8 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -34,6 +34,7 @@
#include "filenames.h"
#include "fnmatch.h"
#include "gdb_regex.h"
+#include "common/gdb_optional.h"
struct skiplist_entry
{
@@ -57,10 +58,7 @@ struct skiplist_entry
char *function;
/* If this is a function regexp, the compiled form. */
- regex_t compiled_function_regexp;
-
- /* Non-zero if the function regexp has been compiled. */
- int compiled_function_regexp_is_valid;
+ gdb::optional<gdb_regex> compiled_function_regexp;
int enabled;
@@ -112,8 +110,6 @@ free_skiplist_entry (struct skiplist_entry *e)
{
xfree (e->file);
xfree (e->function);
- if (e->function_is_regexp && e->compiled_function_regexp_is_valid)
- regfree (&e->compiled_function_regexp);
xfree (e);
}
@@ -202,7 +198,6 @@ skip_function_command (char *arg, int from_tty)
static void
compile_skip_regexp (struct skiplist_entry *e, const char *message)
{
- int code;
int flags = REG_NOSUB;
#ifdef REG_EXTENDED
@@ -210,16 +205,7 @@ compile_skip_regexp (struct skiplist_entry *e, const char *message)
#endif
gdb_assert (e->function_is_regexp && e->function != NULL);
-
- code = regcomp (&e->compiled_function_regexp, e->function, flags);
- if (code != 0)
- {
- char *err = get_regcomp_error (code, &e->compiled_function_regexp);
-
- make_cleanup (xfree, err);
- error (_("%s: %s"), message, err);
- }
- e->compiled_function_regexp_is_valid = 1;
+ e->compiled_function_regexp.emplace (e->function, flags, message);
}
/* Process "skip ..." that does not match "skip file" or "skip function". */
@@ -601,8 +587,8 @@ static int
skip_rfunction_p (struct skiplist_entry *e, const char *function_name)
{
gdb_assert (e->function != NULL && e->function_is_regexp
- && e->compiled_function_regexp_is_valid);
- return (regexec (&e->compiled_function_regexp, function_name, 0, NULL, 0)
+ && e->compiled_function_regexp);
+ return (e->compiled_function_regexp->exec (function_name, 0, NULL, 0)
== 0);
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 22d81fa..1c1eb6c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -62,6 +62,7 @@
#include "parser-defs.h"
#include "completer.h"
#include "progspace-and-thread.h"
+#include "common/gdb_optional.h"
/* Forward declarations for local functions. */
@@ -4299,9 +4300,7 @@ search_symbols (const char *regexp, enum search_domain kind,
struct symbol_search *found;
struct symbol_search *tail;
int nfound;
- /* This is true if PREG contains valid data, false otherwise. */
- bool preg_p;
- regex_t preg;
+ gdb::optional<gdb_regex> preg;
/* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current
CLEANUP_CHAIN is freed only in the case of an error. */
@@ -4316,7 +4315,6 @@ search_symbols (const char *regexp, enum search_domain kind,
ourtype4 = types4[kind];
*matches = NULL;
- preg_p = false;
if (regexp != NULL)
{
@@ -4355,18 +4353,9 @@ search_symbols (const char *regexp, enum search_domain kind,
}
}
- errcode = regcomp (&preg, regexp,
- REG_NOSUB | (case_sensitivity == case_sensitive_off
- ? REG_ICASE : 0));
- if (errcode != 0)
- {
- char *err = get_regcomp_error (errcode, &preg);
-
- make_cleanup (xfree, err);
- error (_("Invalid regexp (%s): %s"), err, regexp);
- }
- preg_p = true;
- make_regfree_cleanup (&preg);
+ int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
+ ? REG_ICASE : 0);
+ preg.emplace (regexp, cflags, _("Invalid regexp"));
}
/* Search through the partial symtabs *first* for all symbols
@@ -4379,8 +4368,8 @@ search_symbols (const char *regexp, enum search_domain kind,
},
[&] (const char *symname)
{
- return (!preg_p || regexec (&preg, symname,
- 0, NULL, 0) == 0);
+ return (!preg || preg->exec (symname,
+ 0, NULL, 0) == 0);
},
NULL,
kind);
@@ -4415,9 +4404,9 @@ search_symbols (const char *regexp, enum search_domain kind,
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (!preg_p
- || regexec (&preg, MSYMBOL_NATURAL_NAME (msymbol), 0,
- NULL, 0) == 0)
+ if (!preg
+ || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+ NULL, 0) == 0)
{
/* Note: An important side-effect of these lookup functions
is to expand the symbol table if msymbol is found, for the
@@ -4459,9 +4448,9 @@ search_symbols (const char *regexp, enum search_domain kind,
files, nfiles, 1))
&& file_matches (symtab_to_fullname (real_symtab),
files, nfiles, 0)))
- && ((!preg_p
- || regexec (&preg, SYMBOL_NATURAL_NAME (sym), 0,
- NULL, 0) == 0)
+ && ((!preg
+ || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
+ NULL, 0) == 0)
&& ((kind == VARIABLES_DOMAIN
&& SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_UNRESOLVED
@@ -4517,9 +4506,8 @@ search_symbols (const char *regexp, enum search_domain kind,
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (!preg_p
- || regexec (&preg, MSYMBOL_NATURAL_NAME (msymbol), 0,
- NULL, 0) == 0)
+ if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+ NULL, 0) == 0)
{
/* For functions we can do a quick check of whether the
symbol might be found via find_pc_symtab. */
diff --git a/gdb/utils.c b/gdb/utils.c
index b4332f8..88a1789 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1038,58 +1038,6 @@ make_hex_string (const gdb_byte *data, size_t length)
-/* A cleanup function that calls regfree. */
-
-static void
-do_regfree_cleanup (void *r)
-{
- regfree ((regex_t *) r);
-}
-
-/* Create a new cleanup that frees the compiled regular expression R. */
-
-struct cleanup *
-make_regfree_cleanup (regex_t *r)
-{
- return make_cleanup (do_regfree_cleanup, r);
-}
-
-/* Return an xmalloc'd error message resulting from a regular
- expression compilation failure. */
-
-char *
-get_regcomp_error (int code, regex_t *rx)
-{
- size_t length = regerror (code, rx, NULL, 0);
- char *result = (char *) xmalloc (length);
-
- regerror (code, rx, result, length);
- return result;
-}
-
-/* Compile a regexp and throw an exception on error. This returns a
- cleanup to free the resulting pattern on success. RX must not be
- NULL. */
-
-struct cleanup *
-compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
-{
- int code;
-
- gdb_assert (rx != NULL);
-
- code = regcomp (pattern, rx, REG_NOSUB);
- if (code != 0)
- {
- char *err = get_regcomp_error (code, pattern);
-
- make_cleanup (xfree, err);
- error (("%s: %s"), message, err);
- }
-
- return make_regfree_cleanup (pattern);
-}
-
/* A cleanup that simply calls ui_unregister_input_event_handler. */
static void
--
2.5.5