From 0fe19209f9dde2fd4450b13a9e772203cf313eff Mon Sep 17 00:00:00 2001 From: David Carlton Date: Mon, 24 Feb 2003 23:37:02 +0000 Subject: [PATCH] 2003-02-24 David Carlton * 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 | 8 ++++++ gdb/defs.h | 2 ++ gdb/symfile.c | 47 ++++-------------------------- gdb/symtab.c | 9 +++--- gdb/utils.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 45 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index dbc65bd958..dce6f501d1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2003-02-24 David Carlton + + * 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 * MAINTAINERS (GNU/Linux/x86, linespec, breakpoints, Scheme diff --git a/gdb/defs.h b/gdb/defs.h index 7caef76cf1..9aa4ff3146 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -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 *); diff --git a/gdb/symfile.c b/gdb/symfile.c index 86508d1240..9615987cf8 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -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; + struct partial_symbol *const *s1 = s1p; + struct partial_symbol *const *s2 = s2p; - s1 = (struct partial_symbol **) s1p; - s2 = (struct partial_symbol **) s2p; - st1 = SYMBOL_PRINT_NAME (*s1); - st2 = SYMBOL_PRINT_NAME (*s2); - - - 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 diff --git a/gdb/symtab.c b/gdb/symtab.c index 1a123fb468..1b1e375775 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -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; } diff --git a/gdb/utils.c b/gdb/utils.c index 0d9fb318a9..df196ec846 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -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", "goo". Then, if + we try to do a search for "foo", strcmp will locate this + after "foo" and before "goo". Then lookup_partial_symbol + will start looking at strings beginning with "goo", and will never + see the correct match of "foo". + + 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