octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Changeset]: Add "-regexp" option to Fwho, Fwhos and Fclear


From: David Bateman
Subject: [Changeset]: Add "-regexp" option to Fwho, Fwhos and Fclear
Date: Sun, 18 May 2008 22:23:48 +0200
User-agent: Thunderbird 2.0.0.12 (X11/20080306)

The attached changeset adds the "-regexp" option to Fwho, Fwhos, Fclear.
It uses regexcomp so it assume that regex is available, and so maybe a
pcre version of the regex_match class should be written as well, but as
we don't use named tokens in the case concerned this isn't important.

I also looked briefly at the "-file" option for Fwhos and it seems the
load-save.cc (do_load) function already partially implements this idea,
though hooking that up with the variables.cc (symbol_info_list) class is
not obvious. Also it seems to me that the reason for the -file option is
to allow variables in files to be listed even if they are too large to
be loaded, and so it doesn't make sense to have the octave_value stored
in the symbol_info_list class for that case. However, the changes to get
all this to work seem a bit invasive for the amount of time I have
available.

D.
# HG changeset patch
# User David Bateman <address@hidden>
# Date 1211141685 -7200
# Node ID 5f7268a38c64058a430cdb819d0be9d4b1b78279
# Parent  5d7b80a15330a8f5c79a463502b7d800d85b5f21
Add regexp matching to Fwho and Fclear

diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,10 @@ 2008-05-14  David Bateman  <address@hidden
+2008-05-18  David Bateman  <address@hidden>
+
+       * regex-match.cc, regex-match.h: New class for simple regular
+       expression matching
+       * Makefile.in (INCLUDES): Add regex-match.h here, and
+       (LIBOCTAVE_CXX_SOURCES): regex-match.cc here.
+
 2008-05-14  David Bateman  <address@hidden>
 
        * fCMatrix.cc (float rcond): Replace with float rcon everywhere
diff --git a/liboctave/Makefile.in b/liboctave/Makefile.in
--- a/liboctave/Makefile.in
+++ b/liboctave/Makefile.in
@@ -91,7 +91,7 @@ INCLUDES := Bounds.h CollocWt.h DAE.h DA
        oct-rl-hist.h oct-shlib.h oct-sort.h oct-spparms.h oct-syscalls.h \
        oct-sparse.h oct-time.h oct-uname.h \
        pathlen.h pathsearch.h prog-args.h \
-       randgamma.h randmtzig.h randpoisson.h \
+       randgamma.h randmtzig.h randpoisson.h regex-match.h \
        so-array.h sparse-sort.h statdefs.h str-vec.h \
        sparse-util.h sun-utils.h sysdir.h systime.h syswait.h \
        $(MATRIX_INC)
@@ -148,7 +148,8 @@ LIBOCTAVE_CXX_SOURCES := Bounds.cc Collo
        lo-utils.cc mach-info.cc oct-alloc.cc oct-env.cc \
        oct-fftw.cc oct-group.cc oct-md5.cc oct-passwd.cc oct-rand.cc \
        oct-shlib.cc oct-spparms.cc oct-syscalls.cc oct-time.cc oct-uname.cc \
-       prog-args.cc so-array.cc sparse-sort.cc sparse-util.cc str-vec.cc \
+       prog-args.cc regex-match.cc \
+       so-array.cc sparse-sort.cc sparse-util.cc str-vec.cc \
        $(TEMPLATE_SRC) \
        $(TI_SRC) \
        $(MATRIX_SRC)
diff --git a/liboctave/regex-match.cc b/liboctave/regex-match.cc
new file mode 100644
--- /dev/null
+++ b/liboctave/regex-match.cc
@@ -0,0 +1,153 @@
+/*
+
+Copyright (C) 2008 David Bateman
+
+This file is part of Octave.
+
+Octave 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.
+
+Octave 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 Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <vector>
+#include <iostream>
+#include <string>
+
+#include "regex-match.h"
+#include "str-vec.h"
+
+regex_match& 
+regex_match::operator = (const regex_match& gm)
+{
+  if (this != &gm)
+    {
+#if HAVE_REGEX
+      for (int i = 0; i < pat.length (); i++)
+       regfree (compiled +i);
+      delete [] compiled;
+#endif
+      pat = gm.pat;
+      case_insen = gm.case_insen;
+      init ();
+    }
+  return *this;
+}
+
+regex_match::~regex_match (void)
+{
+#if HAVE_REGEX
+  for (int i = 0; i < pat.length (); i++)
+    regfree (compiled +i);
+  delete [] compiled;
+#endif
+}
+
+
+void 
+regex_match::set_pattern (const std::string& p) 
+{ 
+#if HAVE_REGEX
+  for (int i = 0; i < pat.length (); i++)
+    regfree (compiled +i);
+  delete [] compiled;
+#endif
+  pat = p; 
+  init ();
+}
+
+void 
+regex_match::set_pattern (const string_vector& p) 
+{ 
+#if HAVE_REGEX
+  for (int i = 0; i < pat.length (); i++)
+    regfree (compiled +i);
+  delete [] compiled;
+#endif
+  pat = p; 
+  init ();
+}
+
+void
+regex_match::init (void)
+{
+#ifdef HAVE_REGEX
+  int npat = pat.length ();
+  int err;
+  int i;
+
+  compiled = new regex_t [npat];
+
+  for (i = 0; i < npat; i++)
+    if (err = regcomp (compiled + i, pat(i).c_str (), 
+                      (REG_NOSUB | REG_EXTENDED |
+                       (case_insen ? REG_ICASE : 0))))
+      break;
+  
+  if (err)
+    {
+      int len = regerror(err, compiled + i, 0, 0);
+      OCTAVE_LOCAL_BUFFER (char, errmsg, len);
+      regerror(err, compiled + i, errmsg, len);
+      (*current_liboctave_error_handler) ("%s in pattern (%s)", errmsg, 
+                                         pat(i).c_str());
+
+      for (int j = 0; j < i + 1; j++)
+       regfree(compiled + j);
+    }
+#else
+  (*current_liboctave_error_handler) 
+    ("regex not available in this version of Octave"); 
+#endif
+}
+
+bool
+regex_match::match (const std::string& s)
+{
+#if HAVE_REGEX
+  int npat = pat.length ();
+
+  const char *str = s.c_str ();
+
+  for (int i = 0; i < npat; i++)
+    if (regexec(compiled + i, str, 0, 0, 0) == 0) 
+      return true;
+#endif
+
+  return false;
+}
+
+Array<bool>
+regex_match::match (const string_vector& s)
+{
+  int n = s.length ();
+
+  Array<bool> retval (n);
+
+  for (int i = 0; i < n; i++)
+    retval(i) = match (s[i]);
+
+  return retval;
+}
+
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
+
diff --git a/liboctave/regex-match.h b/liboctave/regex-match.h
new file mode 100644
--- /dev/null
+++ b/liboctave/regex-match.h
@@ -0,0 +1,90 @@
+/*
+
+Copyright (C) 2008  David Bateman
+
+This file is part of Octave.
+
+Octave 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.
+
+Octave 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 Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_regex_match_h)
+#define octave_regex_match_h 1
+
+#include <string>
+
+#if defined (HAVE_REGEX)
+#if defined (__MINGW32__)
+#define __restrict
+#endif
+#if defined (HAVE_SYS_TYPES_H)
+#include <sys/types.h>
+#endif
+#include <regex.h>
+#endif
+
+#include "Array.h"
+#include "str-vec.h"
+
+class
+OCTAVE_API
+regex_match
+{
+public:
+
+  regex_match (const std::string& p, bool insen = false) 
+    : pat (p), case_insen (insen){ init (); }
+
+  regex_match (const string_vector& p = string_vector (), bool insen = false) 
+    : pat (p), case_insen (insen)  { init (); }
+
+  regex_match (const regex_match& gm) 
+    : pat (gm.pat), case_insen (gm.case_insen) { init (); }
+
+  regex_match& operator = (const regex_match& gm);
+
+  ~regex_match (void);
+
+  void set_pattern (const std::string& p);
+
+  void set_pattern (const string_vector& p);
+
+  bool match (const std::string&);
+
+  Array<bool> match (const string_vector&);
+
+private:
+
+  void init (void);
+
+  // Regex pattern(s).
+  string_vector pat;
+
+  // Should match be case insensitive
+  bool case_insen;
+
+#if HAVE_REGEX
+  regex_t *compiled;
+#endif
+
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
diff --git a/src/ChangeLog b/src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,28 @@ 2008-05-14  David Bateman  <address@hidden
+2008-05-18  David Bateman  <address@hidden>
+
+       * load-save.cc (do_load): Treat non verbose list_only output in
+       the same manner as Fwho.
+       * symtab.h (static void clear_variable_regexp (const
+       std::string&): New method.
+       (static std::list<symbol_record> regexp (const std::string&)): Ditto.
+       (static std::list<symbol_record> regexp_variables (const
+       std::string&)): Ditto.
+       (static std::list<symbol_record> regexp_global_variables (const
+       std::string&)): Ditto,
+       (static std::list<symbol_record> regexp_variables (const
+       string_vector&)): Ditto.
+       (void do_clear_variable_regexp (const std::string&)): Ditto.
+       (std::list<symbol_record> do_regexp (const std::string&, bool)
+       const): Ditto.
+       (do_who): Accept the "-regexp" option. Use regexp versions of
+       symbol table functions.
+       (static inline bool name_match_any_pattern (const string_vector&,
+       int, int, bool): Add regexp argument, and use regexp matching if
+       true.
+       (do_clear_variables): Add regexp option and pass to
+       name_match_any_pattern.
+       (Fclear): Accept the -regexp option.
+
 2008-05-14  David Bateman  <address@hidden>
 
        * DLD-FUNCTIONS/rcond.cc (Frcond): Add support for single precision.
diff --git a/src/load-save.cc b/src/load-save.cc
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -334,6 +334,7 @@ do_load (std::istream& stream, const std
   Octave_map retstruct;
 
   std::ostringstream output_buf;
+  std::list<std::string> symbol_names;
 
   octave_idx_type count = 0;
 
@@ -411,9 +412,10 @@ do_load (std::istream& stream, const std
                            << std::setiosflags (std::ios::right)
                            << std::setw (7) << tc.rows ()
                            << std::setw (7) << tc.columns ()
-                           << "   ";
+                           << "   " << name << "\n";
                        }
-                     output_buf << name << "\n";
+                     else
+                       symbol_names.push_back (name);
                    }
                  else
                    {
@@ -449,12 +451,28 @@ do_load (std::istream& stream, const std
 
   if (list_only && count)
     {
-      std::string msg = output_buf.str ();
-
-      if (nargout > 0)
-       retval = msg;
+      if (verbose)
+       {
+         std::string msg = output_buf.str ();
+
+         if (nargout > 0)
+           retval = msg;
+         else
+           octave_stdout << msg;
+       }
       else
-       octave_stdout << msg;
+       {
+         if (nargout  > 0)
+           retval = Cell (string_vector (symbol_names));
+         else
+           {
+             string_vector names (symbol_names);
+
+             names.list_in_columns (octave_stdout);
+
+             octave_stdout << "\n";
+           }
+       }
     }
   else if (retstruct.nfields () != 0)
     retval = retstruct;
diff --git a/src/symtab.h b/src/symtab.h
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -31,6 +31,7 @@ along with Octave; see the file COPYING.
 #include <string>
 
 #include "glob-match.h"
+#include "regex-match.h"
 
 class tree_argument_list;
 
@@ -1340,6 +1341,14 @@ public:
       inst->do_clear_variable_pattern (pat);
   }
 
+  static void clear_variable_regexp (const std::string& pat)
+  {
+    symbol_table *inst = get_instance (xcurrent_scope);
+
+    if (inst)
+      inst->do_clear_variable_regexp (pat);
+  }
+
   static void clear_symbol_pattern (const std::string& pat)
   {
     // FIXME -- are we supposed to do both here?
@@ -1530,11 +1539,25 @@ public:
     return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
   }
 
+  static std::list<symbol_record> regexp (const std::string& pattern)
+  {
+    symbol_table *inst = get_instance (xcurrent_scope);
+
+    return inst ? inst->do_regexp (pattern) : std::list<symbol_record> ();
+  }
+
   static std::list<symbol_record> glob_variables (const std::string& pattern)
   {
     symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
+  }
+
+  static std::list<symbol_record> regexp_variables (const std::string& pattern)
+  {
+    symbol_table *inst = get_instance (xcurrent_scope);
+
+    return inst ? inst->do_regexp (pattern, true) : std::list<symbol_record> 
();
   }
 
   static std::list<symbol_record>
@@ -1559,6 +1582,28 @@ public:
     return retval;
   }
 
+  static std::list<symbol_record>
+  regexp_global_variables (const std::string& pattern)
+  {
+    std::list<symbol_record> retval;
+
+    regex_match pat (pattern);
+
+    for (global_table_const_iterator p = global_table.begin ();
+        p != global_table.end (); p++)
+      {
+       // We generate a list of symbol_record objects so that
+       // the results from regexp_variables and regexp_global_variables
+       // may be handled the same way.
+
+       if (pat.match (p->first))
+         retval.push_back (symbol_record (p->first, p->second,
+                                          symbol_record::global));
+      }
+
+    return retval;
+  }
+
   static std::list<symbol_record> glob_variables (const string_vector& 
patterns)
   {
     std::list<symbol_record> retval;
@@ -1568,6 +1613,23 @@ public:
     for (size_t i = 0; i < len; i++)
       {
        std::list<symbol_record> tmp = glob_variables (patterns[i]);
+
+       retval.insert (retval.begin (), tmp.begin (), tmp.end ());
+      }
+
+    return retval;
+  }
+
+  static std::list<symbol_record> regexp_variables 
+    (const string_vector& patterns)
+  {
+    std::list<symbol_record> retval;
+
+    size_t len = patterns.length ();
+
+    for (size_t i = 0; i < len; i++)
+      {
+       std::list<symbol_record> tmp = regexp_variables (patterns[i]);
 
        retval.insert (retval.begin (), tmp.begin (), tmp.end ());
       }
@@ -2034,6 +2096,22 @@ private:
       }
   }
 
+  void do_clear_variable_regexp (const std::string& pat)
+  {
+    regex_match pattern (pat);
+
+    for (table_iterator p = table.begin (); p != table.end (); p++)
+      {
+       symbol_record& sr = p->second;
+
+       if (sr.is_defined () || sr.is_global ())
+         {
+           if (pattern.match (sr.name ()))
+             sr.clear ();
+         }
+      }
+  }
+
   void do_mark_hidden (const std::string& name)
   {
     table_iterator p = table.find (name);
@@ -2074,6 +2152,29 @@ private:
     std::list<symbol_record> retval;
 
     glob_match pat (pattern);
+
+    for (table_const_iterator p = table.begin (); p != table.end (); p++)
+      {
+       if (pat.match (p->first))
+         {
+           const symbol_record& sr = p->second;
+
+           if (vars_only && ! sr.is_variable ())
+             continue;
+
+           retval.push_back (sr);
+         }
+      }
+
+    return retval;
+  }
+
+  std::list<symbol_record> do_regexp (const std::string& pattern,
+                                     bool vars_only = false) const
+  {
+    std::list<symbol_record> retval;
+
+    regex_match pat (pattern);
 
     for (table_const_iterator p = table.begin (); p != table.end (); p++)
       {
diff --git a/src/variables.cc b/src/variables.cc
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -36,6 +36,7 @@ along with Octave; see the file COPYING.
 #include "oct-env.h"
 #include "file-ops.h"
 #include "glob-match.h"
+#include "regex-match.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -1637,17 +1638,15 @@ do_who (int argc, const string_vector& a
   std::string my_name = argv[0];
 
   bool global_only = false;
+  bool have_regexp = false;
 
   int i;
   for (i = 1; i < argc; i++)
     {
-      if (argv[i] == "-regexp" || argv[i] == "-file")
-       {
-         error ("%s: `%s' option not implemented", my_name.c_str (),
-                argv[i].c_str ());
-
-         return retval;
-       }
+      if (argv[i] == "-file")
+       error ("%s: `-file' option not implemented", my_name.c_str ());
+      else if (argv[i] == "-regexp")
+       have_regexp = true;
       else if (argv[i] == "global")
        global_only = true;
       else if (argv[i][0] == '-')
@@ -1678,46 +1677,11 @@ do_who (int argc, const string_vector& a
     {
       std::string pat = pats[j];
 
-      size_t pos = pat.find_first_of (".({");
-
-      if (pos != NPOS && pos > 0)
-        {
-         if (verbose)
-           {
-             // NOTE: we can only display information for
-             // expressions based on global values if the variable is
-             // global in the current scope because we currently have
-             // no way of looking up the base value in the global
-             // scope and then evaluating the arguments in the
-             // current scope.
-
-             std::string base_name = pat.substr (0, pos);
-
-             if (symbol_table::is_variable (base_name))
-               {
-                 symbol_table::symbol_record sr
-                   = symbol_table::find_symbol (base_name);
-
-                 if (! global_only || sr.is_global ())
-                   {
-                     int parse_status;
-
-                     octave_value expr_val
-                       = eval_string (pat, true, parse_status);
-
-                     if (! error_state)
-                       symbol_stats.append (sr, pat, expr_val);
-                     else
-                       return retval;
-                   }
-               }
-           }
-       }
-      else
+      if (have_regexp)
        {
          std::list<symbol_table::symbol_record> tmp = global_only
-           ? symbol_table::glob_global_variables (pats[j])
-           : symbol_table::glob_variables (pats[j]);
+           ? symbol_table::regexp_global_variables (pat)
+           : symbol_table::regexp_variables (pat);
 
          for (std::list<symbol_table::symbol_record>::const_iterator p = 
tmp.begin ();
               p != tmp.end (); p++)
@@ -1726,6 +1690,59 @@ do_who (int argc, const string_vector& a
                symbol_stats.append (*p);
              else
                symbol_names.push_back (p->name ());
+           }
+       }
+      else
+       {
+         size_t pos = pat.find_first_of (".({");
+
+         if (pos != NPOS && pos > 0)
+           {
+             if (verbose)
+               {
+                 // NOTE: we can only display information for
+                 // expressions based on global values if the variable is
+                 // global in the current scope because we currently have
+                 // no way of looking up the base value in the global
+                 // scope and then evaluating the arguments in the
+                 // current scope.
+
+                 std::string base_name = pat.substr (0, pos);
+
+                 if (symbol_table::is_variable (base_name))
+                   {
+                     symbol_table::symbol_record sr
+                       = symbol_table::find_symbol (base_name);
+
+                     if (! global_only || sr.is_global ())
+                       {
+                         int parse_status;
+
+                         octave_value expr_val
+                           = eval_string (pat, true, parse_status);
+
+                         if (! error_state)
+                           symbol_stats.append (sr, pat, expr_val);
+                         else
+                           return retval;
+                       }
+                   }
+               }
+           }
+         else
+           {
+             std::list<symbol_table::symbol_record> tmp = global_only
+               ? symbol_table::glob_global_variables (pat)
+               : symbol_table::glob_variables (pat);
+
+             for (std::list<symbol_table::symbol_record>::const_iterator p = 
tmp.begin ();
+                  p != tmp.end (); p++)
+               {
+                 if (verbose)
+                   symbol_stats.append (*p);
+                 else
+                   symbol_names.push_back (p->name ());
+               }
            }
        }
     }
@@ -1775,25 +1792,12 @@ may not be combined.\n\
 may not be combined.\n\
 \n\
 @table @code\n\
address@hidden -all\n\
-List all currently defined symbols.\n\
-\n\
address@hidden -builtins\n\
-List built-in functions.  This includes all currently\n\
-compiled function files, but does not include all function files that\n\
-are in the search path.\n\
-\n\
address@hidden -functions\n\
-List user-defined functions.\n\
-\n\
address@hidden -long\n\
-Print a long listing including the type and dimensions of any symbols.\n\
-The symbols in the first column of output indicate whether it is\n\
-possible to redefine the symbol, and whether it is possible for it to be\n\
-cleared.\n\
-\n\
address@hidden -variables\n\
-List user-defined variables.\n\
address@hidden global\n\
+List the variables in the global scope rather than the current scope.\n\
address@hidden -regexp\n\
+The patterns are considered as regular expressions and will be used\n\
+for matching the variables to display. The same pattern syntax as for\n\
+the @code{regexp} function is used.\n\
 @end table\n\
 \n\
 Valid patterns are the same as described for the @code{clear} command\n\
@@ -1802,6 +1806,7 @@ visible in the local scope are displayed
 visible in the local scope are displayed.\n\
 \n\
 The command @kbd{whos} is equivalent to @kbd{who -long}.\n\
address@hidden
 @end deffn")
 {
   octave_value retval;
@@ -2012,23 +2017,35 @@ then return true if the current function
 // Deleting names from the symbol tables.
 
 static inline bool
-name_matches_any_pattern (const std::string& nm,
-                         const string_vector& argv, int argc, int idx)
+name_matches_any_pattern (const std::string& nm, const string_vector& argv, 
+                         int argc, int idx, bool have_regexp = false)
 {
   bool retval = false;
 
   for (int k = idx; k < argc; k++)
     {
       std::string patstr = argv[k];
-
       if (! patstr.empty ())
        {
-         glob_match pattern (patstr);
-
-         if (pattern.match (nm))
+         if (have_regexp)
            {
-             retval = true;
-             break;
+             regex_match pattern (patstr);
+
+             if (pattern.match (nm))
+               {
+                 retval = true;
+                 break;
+               }
+           }
+         else
+           {
+             glob_match pattern (patstr);
+
+             if (pattern.match (nm))
+               {
+                 retval = true;
+                 break;
+               }
            }
        }
     }
@@ -2112,7 +2129,7 @@ do_clear_globals (const string_vector& a
 
 static void
 do_clear_variables (const string_vector& argv, int argc, int idx,
-                   bool exclusive = false)
+                   bool exclusive = false, bool have_regexp = false)
 {
   if (idx == argc)
     symbol_table::clear_variables ();
@@ -2128,14 +2145,18 @@ do_clear_variables (const string_vector&
            {
              std::string nm = lvars[i];
 
-             if (! name_matches_any_pattern (nm, argv, argc, idx))
+             if (! name_matches_any_pattern (nm, argv, argc, idx, have_regexp))
                symbol_table::clear_variable (nm);
            }
        }
       else
        {
-         while (idx < argc)
-           symbol_table::clear_variable_pattern (argv[idx++]);
+         if (have_regexp)
+           while (idx < argc)
+             symbol_table::clear_variable_regexp (argv[idx++]);
+         else
+           while (idx < argc)
+             symbol_table::clear_variable_pattern (argv[idx++]);
        }
     }
 }
@@ -2266,6 +2287,9 @@ Clears the global symbol names.\n\
 Clears the global symbol names.\n\
 @item -variables, -v\n\
 Clears the local variable names.\n\
address@hidden -regexp, -r\n\
+The arguments are treated as regular expressions as any variables that\n\
+match will be cleared.\n\
 @end table\n\
 With the execption of @code{exclusive}, all long options can be used \n\
 without the dash as well.\n\
@@ -2292,6 +2316,7 @@ without the dash as well.\n\
          bool clear_globals = false;
          bool clear_variables = false;
          bool exclusive = false;
+         bool have_regexp = false;
          bool have_dash_option = false;
 
          while (++idx < argc)
@@ -2329,6 +2354,13 @@ without the dash as well.\n\
                  have_dash_option = true;
                  clear_variables = true;
                }
+             else if (argv[idx] == "-regexp" || argv[idx] == "-r")
+               {
+                 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
+
+                 have_dash_option = true;
+                 have_regexp = true;
+               }
              else
                break;
            }
@@ -2350,6 +2382,10 @@ without the dash as well.\n\
                          ("clear: ignoring extra arguments after -all");
 
                      symbol_table::clear_all ();
+                   }
+                 else if (have_regexp)
+                   {
+                     do_clear_variables (argv, argc, idx, exclusive, true);
                    }
                  else if (clear_functions)
                    {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]