This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA 2/2] C++-ify break-catch-throw


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?

>From 26a9200f3b8f94f24b4c026413ffd7968fd3ea01 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.h         | 26 +++++++++++---
 gdb/linux-tdep.c        | 93 +++++++++++++++++++++++++------------------------
 gdb/probe.c             | 19 +++++-----
 gdb/skip.c              | 24 +++----------
 gdb/symtab.c            | 42 ++++++++--------------
 gdb/utils.c             | 52 ---------------------------
 13 files changed, 135 insertions(+), 230 deletions(-)

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 (&reg, regexp,
-				     _("invalid regular expression"));
+  if (regexp == NULL)
+    return ada_exceptions_list_1 (NULL);
 
-  result = ada_exceptions_list_1 (regexp != NULL ? &reg : 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 (&reg);
 }
 
 /* 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.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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]