* cp-support.c: Include "safe-ctype.h".
authorDaniel Jacobowitz <drow@false.org>
Mon, 22 Oct 2007 14:37:36 +0000 (14:37 +0000)
committerDaniel Jacobowitz <drow@false.org>
Mon, 22 Oct 2007 14:37:36 +0000 (14:37 +0000)
(cp_already_canonical): New function.
(cp_canonicalize_string): Use it.  Return NULL for already canonical
strings.
(mangled_name_to_comp): Update call to cp_demangled_name_to_comp.
(cp_func_name, remove_params): Likewise.
(cp_find_first_component_aux): Use ISSPACE.
* cp-support.h (cp_demangled_name_to_comp): Correct comment.  Remove
MEMORY_P argument.
* cp-name-parser.y (ALLOC_CHUNK): Define.
(struct demangle_info): Add PREV and NEXT.  Increase the size of
COMPS.
(d_grab): Convert to a function.
(allocate_info): Rewrite.
(cp_demangled_name_to_comp): Remove MEMORY argument.  Do not use
strlen.  Update call to allocate_info.  Do not free it on failure.
(main): Update calls to cp_demangled_name_to_comp.
* Makefile.in (cp-support.o): Update.

gdb/ChangeLog
gdb/Makefile.in
gdb/cp-name-parser.y
gdb/cp-support.c
gdb/cp-support.h

index d728e9f3605ef385b359f83f80167af744c8271e..c66a8c7b39667d15a60494fb7a8d667ee1cf9e2e 100644 (file)
@@ -1,3 +1,24 @@
+2007-10-22  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * cp-support.c: Include "safe-ctype.h".
+       (cp_already_canonical): New function.
+       (cp_canonicalize_string): Use it.  Return NULL for already canonical
+       strings.
+       (mangled_name_to_comp): Update call to cp_demangled_name_to_comp.
+       (cp_func_name, remove_params): Likewise.
+       (cp_find_first_component_aux): Use ISSPACE.
+       * cp-support.h (cp_demangled_name_to_comp): Correct comment.  Remove
+       MEMORY_P argument.
+       * cp-name-parser.y (ALLOC_CHUNK): Define.
+       (struct demangle_info): Add PREV and NEXT.  Increase the size of
+       COMPS.
+       (d_grab): Convert to a function.
+       (allocate_info): Rewrite.
+       (cp_demangled_name_to_comp): Remove MEMORY argument.  Do not use
+       strlen.  Update call to allocate_info.  Do not free it on failure.
+       (main): Update calls to cp_demangled_name_to_comp.
+       * Makefile.in (cp-support.o): Update.
+
 2007-10-22  Markus Deuling  <deuling@de.ibm.com>
 
        * std-regs.c (value_of_builtin_frame_fp_reg)
index 722d36190d9c11910fe27307f300672191b0f45c..05b1deb3f1911483329c022b3c5fef8318dc69ba 100644 (file)
@@ -1931,7 +1931,7 @@ cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \
 cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \
        $(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \
        $(objfiles_h) $(frame_h) $(symtab_h) $(block_h) $(complaints_h) \
-       $(gdbtypes_h)
+       $(gdbtypes_h) $(safe_ctype_h)
 cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \
        $(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \
        $(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \
index 0916e866c3dbf94443112949979b209e89127629..0eab4f2120ebd15d6d6faeb89427169fa697e266 100644 (file)
@@ -54,13 +54,38 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
 /* The components built by the parser are allocated ahead of time,
    and cached in this structure.  */
 
+#define ALLOC_CHUNK 100
+
 struct demangle_info {
   int used;
-  struct demangle_component comps[1];
+  struct demangle_info *prev, *next;
+  struct demangle_component comps[ALLOC_CHUNK];
 };
 
 static struct demangle_info *demangle_info;
-#define d_grab() (&demangle_info->comps[demangle_info->used++])
+
+static struct demangle_component *
+d_grab (void)
+{
+  struct demangle_info *more;
+
+  if (demangle_info->used >= ALLOC_CHUNK)
+    {
+      if (demangle_info->next == NULL)
+       {
+         more = malloc (sizeof (struct demangle_info));
+         more->prev = demangle_info;
+         more->next = NULL;
+         demangle_info->next = more;
+       }
+      else
+       more = demangle_info->next;
+
+      more->used = 0;
+      demangle_info = more;
+    }
+  return &demangle_info->comps[demangle_info->used++];
+}
 
 /* The parse tree created by the parser is stored here after a successful
    parse.  */
@@ -1923,19 +1948,24 @@ yyerror (char *msg)
   global_errmsg = msg ? msg : "parse error";
 }
 
-/* Allocate all the components we'll need to build a tree.  We generally
-   allocate too many components, but the extra memory usage doesn't hurt
-   because the trees are temporary.  If we start keeping the trees for
-   a longer lifetime we'll need to be cleverer.  */
-static struct demangle_info *
-allocate_info (int comps)
+/* Allocate a chunk of the components we'll need to build a tree.  We
+   generally allocate too many components, but the extra memory usage
+   doesn't hurt because the trees are temporary and the storage is
+   reused.  More may be allocated later, by d_grab.  */
+static void
+allocate_info (void)
 {
-  struct demangle_info *ret;
+  if (demangle_info == NULL)
+    {
+      demangle_info = malloc (sizeof (struct demangle_info));
+      demangle_info->prev = NULL;
+      demangle_info->next = NULL;
+    }
+  else
+    while (demangle_info->prev)
+      demangle_info = demangle_info->prev;
 
-  ret = malloc (sizeof (struct demangle_info)
-               + sizeof (struct demangle_component) * (comps - 1));
-  ret->used = 0;
-  return ret;
+  demangle_info->used = 0;
 }
 
 /* Convert RESULT to a string.  The return value is allocated
@@ -1975,26 +2005,23 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len)
   return (buf);
 }
 
-/* Convert a demangled name to a demangle_component tree.  *MEMORY is set to the
-   block of used memory that should be freed when finished with the
-   tree.  On error, NULL is returned, and an error message will be
-   set in *ERRMSG (which does not need to be freed).  */
+/* Convert a demangled name to a demangle_component tree.  On success,
+   the root of the new tree is returned; it is valid until the next
+   call to this function and should not be freed.  On error, NULL is
+   returned, and an error message will be set in *ERRMSG (which does
+   not need to be freed).  */
 
 struct demangle_component *
-cp_demangled_name_to_comp (const char *demangled_name, void **memory,
-                          const char **errmsg)
+cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 {
   static char errbuf[60];
   struct demangle_component *result;
 
-  int len = strlen (demangled_name);
-
-  len = len + len / 8;
   prev_lexptr = lexptr = demangled_name;
   error_lexptr = NULL;
   global_errmsg = NULL;
 
-  demangle_info = allocate_info (len);
+  allocate_info ();
 
   if (yyparse ())
     {
@@ -2005,11 +2032,9 @@ cp_demangled_name_to_comp (const char *demangled_name, void **memory,
          strcat (errbuf, "'");
          *errmsg = errbuf;
        }
-      free (demangle_info);
       return NULL;
     }
 
-  *memory = demangle_info;
   result = global_result;
   global_result = NULL;
 
@@ -2063,11 +2088,10 @@ trim_chars (char *lexptr, char **extra_chars)
 int
 main (int argc, char **argv)
 {
-  char *str2, *extra_chars, c;
+  char *str2, *extra_chars = "", c;
   char buf[65536];
   int arg;
   const char *errmsg;
-  void *memory;
   struct demangle_component *result;
 
   arg = 1;
@@ -2094,7 +2118,7 @@ main (int argc, char **argv)
              printf ("%s\n", buf);
            continue;
          }
-       result = cp_demangled_name_to_comp (str2, &memory, &errmsg);
+       result = cp_demangled_name_to_comp (str2, &errmsg);
        if (result == NULL)
          {
            fputs (errmsg, stderr);
@@ -2103,7 +2127,6 @@ main (int argc, char **argv)
          }
 
        cp_print (result);
-       free (memory);
 
        free (str2);
        if (c)
@@ -2115,7 +2138,7 @@ main (int argc, char **argv)
       }
   else
     {
-      result = cp_demangled_name_to_comp (argv[arg], &memory, &errmsg);
+      result = cp_demangled_name_to_comp (argv[arg], &errmsg);
       if (result == NULL)
        {
          fputs (errmsg, stderr);
@@ -2124,7 +2147,6 @@ main (int argc, char **argv)
        }
       cp_print (result);
       putchar ('\n');
-      free (memory);
     }
   return 0;
 }
index 2d8c3c752792e79dbbe5758bd704b0e7d6fd6498..34ddde3059c78f0ee5c85230a3fd8cb8dd4c33ac 100644 (file)
@@ -19,7 +19,6 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include <ctype.h>
 #include "cp-support.h"
 #include "gdb_string.h"
 #include "demangle.h"
@@ -33,6 +32,8 @@
 #include "complaints.h"
 #include "gdbtypes.h"
 
+#include "safe-ctype.h"
+
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
 
@@ -68,30 +69,63 @@ struct cmd_list_element *maint_cplus_cmd_list = NULL;
 static void maint_cplus_command (char *arg, int from_tty);
 static void first_component_command (char *arg, int from_tty);
 
-/* Return the canonicalized form of STRING, or NULL if STRING can not be
-   parsed.  The return value is allocated via xmalloc.
+/* Return 1 if STRING is clearly already in canonical form.  This
+   function is conservative; things which it does not recognize are
+   assumed to be non-canonical, and the parser will sort them out
+   afterwards.  This speeds up the critical path for alphanumeric
+   identifiers.  */
+
+static int
+cp_already_canonical (const char *string)
+{
+  /* Identifier start character [a-zA-Z_].  */
+  if (!ISIDST (string[0]))
+    return 0;
+
+  /* These are the only two identifiers which canonicalize to other
+     than themselves or an error: unsigned -> unsigned int and
+     signed -> int.  */
+  if (string[0] == 'u' && strcmp (&string[1], "nsigned") == 0)
+    return 0;
+  else if (string[0] == 's' && strcmp (&string[1], "igned") == 0)
+    return 0;
+
+  /* Identifier character [a-zA-Z0-9_].  */
+  while (ISIDNUM (string[1]))
+    string++;
+
+  if (string[1] == '\0')
+    return 1;
+  else
+    return 0;
+}
 
-   drow/2005-03-07: Should we also return NULL for things that trivially do
-   not require any change?  e.g. simple identifiers.  This could be more
-   efficient.  */
+/* Parse STRING and convert it to canonical form.  If parsing fails,
+   or if STRING is already canonical, return NULL.  Otherwise return
+   the canonical form.  The return value is allocated via xmalloc.  */
 
 char *
 cp_canonicalize_string (const char *string)
 {
-  void *storage;
   struct demangle_component *ret_comp;
+  unsigned int estimated_len;
   char *ret;
-  int len = strlen (string);
 
-  len = len + len / 8;
+  if (cp_already_canonical (string))
+    return NULL;
 
-  ret_comp = cp_demangled_name_to_comp (string, &storage, NULL);
+  ret_comp = cp_demangled_name_to_comp (string, NULL);
   if (ret_comp == NULL)
     return NULL;
 
-  ret = cp_comp_to_string (ret_comp, len);
+  estimated_len = strlen (string) * 2;
+  ret = cp_comp_to_string (ret_comp, estimated_len);
 
-  xfree (storage);
+  if (strcmp (string, ret) == 0)
+    {
+      xfree (ret);
+      return NULL;
+    }
 
   return ret;
 }
@@ -128,7 +162,7 @@ mangled_name_to_comp (const char *mangled_name, int options,
    return NULL;
   
   /* If we could demangle the name, parse it to build the component tree.  */
-  ret = cp_demangled_name_to_comp (demangled_name, memory, NULL);
+  ret = cp_demangled_name_to_comp (demangled_name, NULL);
 
   if (ret == NULL)
     {
@@ -321,12 +355,11 @@ method_name_from_physname (const char *physname)
 char *
 cp_func_name (const char *full_name)
 {
-  void *storage;
   char *ret;
   struct demangle_component *ret_comp;
   int done;
 
-  ret_comp = cp_demangled_name_to_comp (full_name, &storage, NULL);
+  ret_comp = cp_demangled_name_to_comp (full_name, NULL);
   if (!ret_comp)
     return NULL;
 
@@ -336,7 +369,6 @@ cp_func_name (const char *full_name)
   if (ret_comp != NULL)
     ret = cp_comp_to_string (ret_comp, 10);
 
-  xfree (storage);
   return ret;
 }
 
@@ -349,13 +381,12 @@ remove_params (const char *demangled_name)
 {
   int done = 0;
   struct demangle_component *ret_comp;
-  void *storage;
   char *ret = NULL;
 
   if (demangled_name == NULL)
     return NULL;
 
-  ret_comp = cp_demangled_name_to_comp (demangled_name, &storage, NULL);
+  ret_comp = cp_demangled_name_to_comp (demangled_name, NULL);
   if (ret_comp == NULL)
     return NULL;
 
@@ -381,7 +412,6 @@ remove_params (const char *demangled_name)
   if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
     ret = cp_comp_to_string (d_left (ret_comp), 10);
 
-  xfree (storage);
   return ret;
 }
 
@@ -511,7 +541,7 @@ cp_find_first_component_aux (const char *name, int permissive)
              && strncmp (name + index, "operator", LENGTH_OF_OPERATOR) == 0)
            {
              index += LENGTH_OF_OPERATOR;
-             while (isspace(name[index]))
+             while (ISSPACE(name[index]))
                ++index;
              switch (name[index])
                {
index 960fc6bf976b2a6d9fb33b136fad78fd1fb753da..e85fa4668b4d6bf7a9e758638b09c36a14ae7c5f 100644 (file)
@@ -114,10 +114,10 @@ extern void cp_check_possible_namespace_symbols (const char *name,
 
 struct type *cp_lookup_transparent_type (const char *name);
 
-/* Functions from cp-names.y.  */
+/* Functions from cp-name-parser.y.  */
 
 extern struct demangle_component *cp_demangled_name_to_comp
-  (const char *demangled_name, void **memory_p, const char **errmsg);
+  (const char *demangled_name, const char **errmsg);
 
 extern char *cp_comp_to_string (struct demangle_component *result,
                                int estimated_len);