This is the mail archive of the gdb-cvs@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]

[binutils-gdb] Introduce compiled_regex, eliminate make_regfree_cleanup


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2d7cc5c7973b6d1bdd9205288863bedadeaf8b41

commit 2d7cc5c7973b6d1bdd9205288863bedadeaf8b41
Author: Pedro Alves <palves@redhat.com>
Date:   Wed Jun 7 14:21:40 2017 +0100

    Introduce compiled_regex, eliminate make_regfree_cleanup
    
    This patch replaces compile_rx_or_error and make_regfree_cleanup with
    a class that wraps a regex_t.
    
    gdb/ChangeLog:
    2017-06-07  Pedro Alves  <palves@redhat.com>
    
    	* Makefile.in (SFILES): Add gdb_regex.c.
    	(COMMON_OBS): Add gdb_regex.o.
    	* ada-lang.c (ada_add_standard_exceptions)
    	(ada_add_exceptions_from_frame, name_matches_regex)
    	(ada_add_global_exceptions, ada_exceptions_list_1): Change regex
    	parameter type to compiled_regex.  Adjust.
    	(ada_exceptions_list): Use compiled_regex.
    	* break-catch-throw.c (exception_catchpoint::pattern): Now a
    	std::unique_ptr<compiled_regex>.
    	(exception_catchpoint::~exception_catchpoint): Remove regfree
    	call.
    	(check_status_exception_catchpoint): Adjust to use compiled_regex.
    	(handle_gnu_v3_exceptions): Adjust to use compiled_regex.
    	* breakpoint.c (solib_catchpoint::compiled): Now a
    	std::unique_ptr<compiled_regex>.
    	(solib_catchpoint::~solib_catchpoint): Remove regfree call.
    	(check_status_catch_solib): Adjust to use compiled_regex.
    	(add_solib_catchpoint): Adjust to use compiled_regex.
    	* cli/cli-cmds.c (apropos_command): Use compiled_regex.
    	* cli/cli-decode.c (apropos_cmd): Change regex parameter to
    	compiled_regex reference.  Adjust to use it.
    	* cli/cli-decode.h: Remove struct re_pattern_buffer forward
    	declaration.  Include "gdb_regex.h".
    	(apropos_cmd): Change regex parameter to compiled_regex reference.
    	* gdb_regex.c: New file.
    	* gdb_regex.h (make_regfree_cleanup, get_regcomp_error): Delete
    	declarations.
    	(class compiled_regex): New.
    	* linux-tdep.c: Include "common/gdb_optional.h".
    	(struct mapping_regexes): New, factored out from
    	mapping_is_anonymous_p, and adjusted to use compiled_regex.
    	(mapping_is_anonymous_p): Use mapping_regexes wrapped in a
    	gdb::optional and remove cleanups.  Adjust to compiled_regex.
    	* probe.c: Include "common/gdb_optional.h".
    	(collect_probes): Use compiled_regex and gdb::optional and remove
    	cleanups.
    	* skip.c: Include "common/gdb_optional.h".
    	(skiplist_entry::compiled_function_regexp): Now a
    	gdb::optional<compiled_regex>.
    	(skiplist_entry::compiled_function_regexp_is_valid): Delete field.
    	(free_skiplist_entry): Remove regfree call.
    	(compile_skip_regexp, skip_rfunction_p): Adjust to use
    	compiled_regex and gdb::optional.
    	* symtab.c: Include "common/gdb_optional.h".
    	(search_symbols): Use compiled_regex and gdb::optional.
    	* utils.c (do_regfree_cleanup, make_regfree_cleanup)
    	(get_regcomp_error, compile_rx_or_error): Delete.  Some bits moved
    	to gdb_regex.c.

Diff:
---
 gdb/ChangeLog           | 51 +++++++++++++++++++++++++++++
 gdb/Makefile.in         |  2 ++
 gdb/ada-lang.c          | 33 ++++++++-----------
 gdb/break-catch-throw.c | 21 +++++-------
 gdb/breakpoint.c        | 20 +++---------
 gdb/cli/cli-cmds.c      | 21 ++----------
 gdb/cli/cli-decode.c    | 11 ++++---
 gdb/cli/cli-decode.h    |  5 ++-
 gdb/gdb_regex.c         | 56 ++++++++++++++++++++++++++++++++
 gdb/gdb_regex.h         | 39 ++++++++++++++++++++---
 gdb/linux-tdep.c        | 85 +++++++++++++++++++++++++------------------------
 gdb/probe.c             | 19 ++++++-----
 gdb/skip.c              | 24 +++-----------
 gdb/symtab.c            | 42 +++++++++---------------
 gdb/utils.c             | 52 ------------------------------
 15 files changed, 255 insertions(+), 226 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3190410..6424388 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,54 @@
+2017-06-07  Pedro Alves  <palves@redhat.com>
+
+	* Makefile.in (SFILES): Add gdb_regex.c.
+	(COMMON_OBS): Add gdb_regex.o.
+	* ada-lang.c (ada_add_standard_exceptions)
+	(ada_add_exceptions_from_frame, name_matches_regex)
+	(ada_add_global_exceptions, ada_exceptions_list_1): Change regex
+	parameter type to compiled_regex.  Adjust.
+	(ada_exceptions_list): Use compiled_regex.
+	* break-catch-throw.c (exception_catchpoint::pattern): Now a
+	std::unique_ptr<compiled_regex>.
+	(exception_catchpoint::~exception_catchpoint): Remove regfree
+	call.
+	(check_status_exception_catchpoint): Adjust to use compiled_regex.
+	(handle_gnu_v3_exceptions): Adjust to use compiled_regex.
+	* breakpoint.c (solib_catchpoint::compiled): Now a
+	std::unique_ptr<compiled_regex>.
+	(solib_catchpoint::~solib_catchpoint): Remove regfree call.
+	(check_status_catch_solib): Adjust to use compiled_regex.
+	(add_solib_catchpoint): Adjust to use compiled_regex.
+	* cli/cli-cmds.c (apropos_command): Use compiled_regex.
+	* cli/cli-decode.c (apropos_cmd): Change regex parameter to
+	compiled_regex reference.  Adjust to use it.
+	* cli/cli-decode.h: Remove struct re_pattern_buffer forward
+	declaration.  Include "gdb_regex.h".
+	(apropos_cmd): Change regex parameter to compiled_regex reference.
+	* gdb_regex.c: New file.
+	* gdb_regex.h (make_regfree_cleanup, get_regcomp_error): Delete
+	declarations.
+	(class compiled_regex): New.
+	* linux-tdep.c: Include "common/gdb_optional.h".
+	(struct mapping_regexes): New, factored out from
+	mapping_is_anonymous_p, and adjusted to use compiled_regex.
+	(mapping_is_anonymous_p): Use mapping_regexes wrapped in a
+	gdb::optional and remove cleanups.  Adjust to compiled_regex.
+	* probe.c: Include "common/gdb_optional.h".
+	(collect_probes): Use compiled_regex and gdb::optional and remove
+	cleanups.
+	* skip.c: Include "common/gdb_optional.h".
+	(skiplist_entry::compiled_function_regexp): Now a
+	gdb::optional<compiled_regex>.
+	(skiplist_entry::compiled_function_regexp_is_valid): Delete field.
+	(free_skiplist_entry): Remove regfree call.
+	(compile_skip_regexp, skip_rfunction_p): Adjust to use
+	compiled_regex and gdb::optional.
+	* symtab.c: Include "common/gdb_optional.h".
+	(search_symbols): Use compiled_regex and gdb::optional.
+	* utils.c (do_regfree_cleanup, make_regfree_cleanup)
+	(get_regcomp_error, compile_rx_or_error): Delete.  Some bits moved
+	to gdb_regex.c.
+
 2017-06-07  Alan Hayward  <alan.hayward@arm.com>
 
 	* regcache.c (regcache::save): Avoid buffer use.
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..57c670e 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13219,14 +13219,15 @@ 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 (compiled_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 +13254,8 @@ 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 (compiled_regex *preg,
+			       struct frame_info *frame,
 			       VEC(ada_exc_info) **exceptions)
 {
   const struct block *block = get_frame_block (frame, 0);
@@ -13290,10 +13292,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, compiled_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 +13318,8 @@ 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 (compiled_regex *preg,
+			   VEC(ada_exc_info) **exceptions)
 {
   struct objfile *objfile;
   struct compunit_symtab *s;
@@ -13364,7 +13367,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 (compiled_regex *preg)
 {
   VEC(ada_exc_info) *result = NULL;
   struct cleanup *old_chain
@@ -13417,19 +13420,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;
+  compiled_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..0074d06 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<compiled_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<compiled_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 compiled_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 e84d164..053ccef 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -8284,13 +8284,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<compiled_regex> compiled;
 };
 
 solib_catchpoint::~solib_catchpoint ()
 {
-  if (this->regex)
-    regfree (&this->compiled);
   xfree (this->regex);
 }
 
@@ -8358,7 +8356,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;
 	}
     }
@@ -8372,7 +8370,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;
 	}
     }
@@ -8488,16 +8486,8 @@ 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 compiled_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..0930342 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;
+  compiled_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..383adf8 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)
+	     compiled_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..11248ba 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 *);
+                         compiled_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..2e376e3
--- /dev/null
+++ b/gdb/gdb_regex.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2011-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"
+
+compiled_regex::compiled_regex (const char *regex, int cflags,
+				const char *message)
+{
+  gdb_assert (regex != NULL);
+  gdb_assert (message != 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 ());
+    }
+}
+
+compiled_regex::~compiled_regex ()
+{
+  regfree (&m_pattern);
+}
+
+int
+compiled_regex::exec (const char *string, size_t nmatch,
+		      regmatch_t pmatch[], int eflags) const
+{
+  return regexec (&m_pattern, string, nmatch, pmatch, eflags);
+}
+
+int
+compiled_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..f62f81d 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -27,10 +27,39 @@
 # 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.  This is mainly a wrapper around regex_t.  The
+   the constructor throws on regcomp error and the destructor is
+   responsible for calling regfree.  The former means that it's not
+   possible to create an instance of compiled_regex that isn't
+   compiled, hence the name.  */
+class compiled_regex
+{
+public:
+  /* Compile a regexp and throw an exception on error, including
+     MESSAGE.  REGEX and MESSAGE must not be NULL.  */
+  compiled_regex (const char *regex, int cflags,
+		  const char *message)
+    ATTRIBUTE_NONNULL (2) ATTRIBUTE_NONNULL (4);
+
+  ~compiled_regex ();
+
+  /* Disable copy.  */
+  compiled_regex (const compiled_regex&) = delete;
+  void operator= (const compiled_regex&) = delete;
+
+  /* Wrapper around ::regexec.  */
+  int exec (const char *string,
+	    size_t nmatch, regmatch_t pmatch[],
+	    int eflags) const;
+
+  /* Wrapper around ::re_search.  (Not const because re_search's
+     regex_t parameter isn't either.)  */
+  int search (const char *string, int size, int startpos,
+	      int range, struct re_registers *regs);
+
+private:
+  /* The compiled pattern.  */
+  regex_t m_pattern;
+};
 
 #endif /* not GDB_REGEX_H */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 016aadf..1afa8d7 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,44 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
     }
 }
 
+/* Regexes used by mapping_is_anonymous_p.  Put in a structure because
+   they're initialized lazily.  */
+
+struct mapping_regexes
+{
+  /* 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.  */
+  compiled_regex dev_zero
+    {"^/dev/zero\\( (deleted)\\)\\?$", REG_NOSUB,
+     _("Could not compile regex to match /dev/zero filename")};
+
+  /* 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.  */
+  compiled_regex shmem_file
+    {"^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$", REG_NOSUB,
+     _("Could not compile regex to match shmem filenames")};
+
+  /* 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.  */
+  compiled_regex file_deleted
+    {" (deleted)$", REG_NOSUB,
+     _("Could not compile regex to match '<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 +545,16 @@ 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;
+  static gdb::optional<mapping_regexes> regexes;
   static int init_regex_p = 0;
 
   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..cb2dcdb 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<compiled_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..e767f83 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<compiled_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..f1daf8c 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<compiled_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


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