2003-02-24 David Carlton <carlton@math.stanford.edu>
authorDavid Carlton <carlton@bactrian.org>
Mon, 24 Feb 2003 23:37:02 +0000 (23:37 +0000)
committerDavid Carlton <carlton@bactrian.org>
Mon, 24 Feb 2003 23:37:02 +0000 (23:37 +0000)
* symtab.c (lookup_partial_symbol): Use strcmp_iw_ordered to
do the comparison, not strcmp.
* symfile.c (compare_psymbols): Ditto.
* defs.h: Declare strcmp_iw_ordered.
* utils.c (strcmp_iw_ordered): New function.

gdb/ChangeLog
gdb/defs.h
gdb/symfile.c
gdb/symtab.c
gdb/utils.c

index dbc65bd95812cc9c037db8a95c2bcc4efc6fbecb..dce6f501d13ffe71299d1900e7b703e6602bb9b9 100644 (file)
@@ -1,3 +1,11 @@
+2003-02-24  David Carlton  <carlton@math.stanford.edu>
+
+       * symtab.c (lookup_partial_symbol): Use strcmp_iw_ordered to
+       do the comparison, not strcmp.
+       * symfile.c (compare_psymbols): Ditto.
+       * defs.h: Declare strcmp_iw_ordered.
+       * utils.c (strcmp_iw_ordered): New function.
+
 2003-02-24  Jim Blandy  <jimb@redhat.com>
 
        * MAINTAINERS (GNU/Linux/x86, linespec, breakpoints, Scheme
index 7caef76cf178d88966829b76aa1900cdbe553d6f..9aa4ff314694ab0b70c0bf4a166150f781fc046f 100644 (file)
@@ -305,6 +305,8 @@ extern void notice_quit (void);
 
 extern int strcmp_iw (const char *, const char *);
 
+extern int strcmp_iw_ordered (const char *, const char *);
+
 extern int streq (const char *, const char *);
 
 extern int subset_compare (char *, char *);
index 86508d1240501c08b7469b903acf231e7dd0a46a..9615987cf853742e42b6a525ffa19b789253d816 100644 (file)
@@ -213,52 +213,17 @@ compare_symbols (const void *s1p, const void *s2p)
   return (strcmp (SYMBOL_PRINT_NAME (*s1), SYMBOL_PRINT_NAME (*s2)));
 }
 
-/*
-
-   LOCAL FUNCTION
-
-   compare_psymbols -- compare two partial symbols by name
-
-   DESCRIPTION
-
-   Given pointers to pointers to two partial symbol table entries,
-   compare them by name and return -N, 0, or +N (ala strcmp).
-   Typically used by sorting routines like qsort().
-
-   NOTES
-
-   Does direct compare of first two characters before punting
-   and passing to strcmp for longer compares.  Note that the
-   original version had a bug whereby two null strings or two
-   identically named one character strings would return the
-   comparison of memory following the null byte.
-
- */
+/* This compares two partial symbols by names, using strcmp_iw_ordered
+   for the comparison.  */
 
 static int
 compare_psymbols (const void *s1p, const void *s2p)
 {
-  register struct partial_symbol **s1, **s2;
-  register char *st1, *st2;
-
-  s1 = (struct partial_symbol **) s1p;
-  s2 = (struct partial_symbol **) s2p;
-  st1 = SYMBOL_PRINT_NAME (*s1);
-  st2 = SYMBOL_PRINT_NAME (*s2);
+  struct partial_symbol *const *s1 = s1p;
+  struct partial_symbol *const *s2 = s2p;
 
-
-  if ((st1[0] - st2[0]) || !st1[0])
-    {
-      return (st1[0] - st2[0]);
-    }
-  else if ((st1[1] - st2[1]) || !st1[1])
-    {
-      return (st1[1] - st2[1]);
-    }
-  else
-    {
-      return (strcmp (st1, st2));
-    }
+  return strcmp_iw_ordered (SYMBOL_PRINT_NAME (*s1),
+                           SYMBOL_PRINT_NAME (*s2));
 }
 
 void
index 1a123fb4684ae0cdff18651cd6fcc1e86e892771..1b1e375775e486c597ebe507e548f2baf97f4c37 100644 (file)
@@ -1374,9 +1374,10 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
       do_linear_search = 0;
 
       /* Binary search.  This search is guaranteed to end with center
-         pointing at the earliest partial symbol with the correct
-         name.  At that point *all* partial symbols with that name
-         will be checked against the correct namespace. */
+         pointing at the earliest partial symbol whose name might be
+         correct.  At that point *all* partial symbols with an
+         appropriate name will be checked against the correct
+         namespace.  */
 
       bottom = start;
       top = start + length - 1;
@@ -1391,7 +1392,7 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
            {
              do_linear_search = 1;
            }
-         if (strcmp (SYMBOL_PRINT_NAME (*center), name) >= 0)
+         if (strcmp_iw_ordered (SYMBOL_PRINT_NAME (*center), name) >= 0)
            {
              top = center;
            }
index 0d9fb318a96d88ddd336ac90fc7c1b066cc3b2e9..df196ec84685791c2e4025b695d5c166f9109304 100644 (file)
@@ -2358,6 +2358,86 @@ strcmp_iw (const char *string1, const char *string2)
   return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
 }
 
+/* This is like strcmp except that it ignores whitespace and treats
+   '(' as the first non-NULL character in terms of ordering.  Like
+   strcmp (and unlike strcmp_iw), it returns negative if STRING1 <
+   STRING2, 0 if STRING2 = STRING2, and positive if STRING1 > STRING2
+   according to that ordering.
+
+   If a list is sorted according to this function and if you want to
+   find names in the list that match some fixed NAME according to
+   strcmp_iw(LIST_ELT, NAME), then the place to start looking is right
+   where this function would put NAME.
+
+   Here are some examples of why using strcmp to sort is a bad idea:
+
+   Whitespace example:
+
+   Say your partial symtab contains: "foo<char *>", "goo".  Then, if
+   we try to do a search for "foo<char*>", strcmp will locate this
+   after "foo<char *>" and before "goo".  Then lookup_partial_symbol
+   will start looking at strings beginning with "goo", and will never
+   see the correct match of "foo<char *>".
+
+   Parenthesis example:
+
+   In practice, this is less like to be an issue, but I'll give it a
+   shot.  Let's assume that '$' is a legitimate character to occur in
+   symbols.  (Which may well even be the case on some systems.)  Then
+   say that the partial symbol table contains "foo$" and "foo(int)".
+   strcmp will put them in this order, since '$' < '('.  Now, if the
+   user searches for "foo", then strcmp will sort "foo" before "foo$".
+   Then lookup_partial_symbol will notice that strcmp_iw("foo$",
+   "foo") is false, so it won't proceed to the actual match of
+   "foo(int)" with "foo".  */
+
+int
+strcmp_iw_ordered (const char *string1, const char *string2)
+{
+  while ((*string1 != '\0') && (*string2 != '\0'))
+    {
+      while (isspace (*string1))
+       {
+         string1++;
+       }
+      while (isspace (*string2))
+       {
+         string2++;
+       }
+      if (*string1 != *string2)
+       {
+         break;
+       }
+      if (*string1 != '\0')
+       {
+         string1++;
+         string2++;
+       }
+    }
+
+  switch (*string1)
+    {
+      /* Characters are non-equal unless they're both '\0'; we want to
+        make sure we get the comparison right according to our
+        comparison in the cases where one of them is '\0' or '('.  */
+    case '\0':
+      if (*string2 == '\0')
+       return 0;
+      else
+       return -1;
+    case '(':
+      if (*string2 == '\0')
+       return 1;
+      else
+       return -1;
+    default:
+      if (*string2 == '(')
+       return 1;
+      else
+       return *string1 - *string2;
+    }
+}
+
 /* A simple comparison function with opposite semantics to strcmp.  */
 
 int