From 41d27058f2a51665c78726b4a13510fcfc7db007 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Tue, 5 Feb 2008 22:17:41 +0000 Subject: [PATCH] * language.h (struct language_defn): Add new field la_make_symbol_completion_list. * symtab.c (default_make_symbol_completion_list): Renames make_symbol_completion_list. (make_symbol_completion_list): New function. * symtab.h (default_make_symbol_completion_list): Add declaration. * langauge.c (unknown_language): Set la_make_symbol_completion_list. (auto_language, local_language): Likewise. * objc-lang.c (objc_language_defn): Likewise. * scm-lang.c (scm_language_defn): Likewise. * m2-lang.c (m2_language_defn): Likewise. * f-lang.c (f_language_defn): Likewise. * jv-lang.c (java_language_defn): Likewise. * p-lang.c (pascal_language_defn): Likewise. * c-lang.c (c_language_defn, cplus_language_defn, asm_language_defn) (minimal_language_defn): Likewise. * ada-lang.c (struct string_vector): New structure. (new_string_vector, string_vector_append, ada_unqualified_name) (add_angle_brackets, symbol_completion_match, symbol_completion_add) (ada_make_symbol_completion_list): New functions. (ada_language_defn): Set la_make_symbol_completion_list. * ada-lang.h (ada_make_symbol_completion_list): Remove declaration, this function is static. --- gdb/ChangeLog | 26 ++++ gdb/ada-lang.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ gdb/ada-lang.h | 3 - gdb/c-lang.c | 4 + gdb/f-lang.c | 1 + gdb/jv-lang.c | 1 + gdb/language.c | 3 + gdb/language.h | 5 + gdb/m2-lang.c | 1 + gdb/objc-lang.c | 1 + gdb/p-lang.c | 1 + gdb/scm-lang.c | 1 + gdb/symtab.c | 27 ++-- gdb/symtab.h | 1 + 14 files changed, 423 insertions(+), 14 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ae3c56e814b..41fb91c648f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,29 @@ +2007-02-05 Joel Brobecker + + * language.h (struct language_defn): Add new field + la_make_symbol_completion_list. + * symtab.c (default_make_symbol_completion_list): Renames + make_symbol_completion_list. + (make_symbol_completion_list): New function. + * symtab.h (default_make_symbol_completion_list): Add declaration. + * langauge.c (unknown_language): Set la_make_symbol_completion_list. + (auto_language, local_language): Likewise. + * objc-lang.c (objc_language_defn): Likewise. + * scm-lang.c (scm_language_defn): Likewise. + * m2-lang.c (m2_language_defn): Likewise. + * f-lang.c (f_language_defn): Likewise. + * jv-lang.c (java_language_defn): Likewise. + * p-lang.c (pascal_language_defn): Likewise. + * c-lang.c (c_language_defn, cplus_language_defn, asm_language_defn) + (minimal_language_defn): Likewise. + * ada-lang.c (struct string_vector): New structure. + (new_string_vector, string_vector_append, ada_unqualified_name) + (add_angle_brackets, symbol_completion_match, symbol_completion_add) + (ada_make_symbol_completion_list): New functions. + (ada_language_defn): Set la_make_symbol_completion_list. + * ada-lang.h (ada_make_symbol_completion_list): Remove declaration, + this function is static. + 2008-02-05 Kevin Buettner * mn10300-tdep.c (mn10300_push_dummy_call): Adjust stack pointer diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 7880645fc4d..44a3cc53167 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -68,6 +68,24 @@ #define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2) #endif +/* A structure that contains a vector of strings. + The main purpose of this type is to group the vector and its + associated parameters in one structure. This makes it easier + to handle and pass around. + + brobecker/2008-02-04: GDB does provide a generic VEC which should be + preferable. But we are using the string_vector structure in the context + of symbol completion, and the current infrastructure is such that it's + more convenient to use the string vector for now. It would become + advantageous to switch to VECs if the rest of the completion-related + code switches to VECs as well. */ + +struct string_vector +{ + char **array; /* The vector itself. */ + int index; /* Index of the next available element in the array. */ + size_t size; /* The number of entries allocated in the array. */ +}; static void extract_string (CORE_ADDR addr, char *buf); @@ -316,6 +334,65 @@ static struct obstack symbol_list_obstack; /* Utilities */ +/* Create a new empty string_vector struct with an initial size of + INITIAL_SIZE. */ + +static struct string_vector +new_string_vector (int initial_size) +{ + struct string_vector result; + + result.array = (char **) xmalloc ((initial_size + 1) * sizeof (char *)); + result.index = 0; + result.size = initial_size; + + return result; +} + +/* Add STR at the end of the given string vector SV. If SV is already + full, its size is automatically increased (doubled). */ + +static void +string_vector_append (struct string_vector *sv, char *str) +{ + if (sv->index >= sv->size) + GROW_VECT (sv->array, sv->size, sv->size * 2); + + sv->array[sv->index] = str; + sv->index++; +} + +/* Given DECODED_NAME a string holding a symbol name in its + decoded form (ie using the Ada dotted notation), returns + its unqualified name. */ + +static const char * +ada_unqualified_name (const char *decoded_name) +{ + const char *result = strrchr (decoded_name, '.'); + + if (result != NULL) + result++; /* Skip the dot... */ + else + result = decoded_name; + + return result; +} + +/* Return a string starting with '<', followed by STR, and '>'. + The result is good until the next call. */ + +static char * +add_angle_brackets (const char *str) +{ + static char *result = NULL; + + xfree (result); + result = (char *) xmalloc ((strlen (str) + 3) * sizeof (char)); + + sprintf (result, "<%s>", str); + return result; +} static char * ada_get_gdb_completer_word_break_characters (void) @@ -5340,6 +5417,290 @@ ada_add_block_symbols (struct obstack *obstackp, } } + + /* Symbol Completion */ + +/* If SYM_NAME is a completion candidate for TEXT, return this symbol + name in a form that's appropriate for the completion. The result + does not need to be deallocated, but is only good until the next call. + + TEXT_LEN is equal to the length of TEXT. + Perform a wild match if WILD_MATCH is set. + ENCODED should be set if TEXT represents the start of a symbol name + in its encoded form. */ + +static const char * +symbol_completion_match (const char *sym_name, + const char *text, int text_len, + int wild_match, int encoded) +{ + char *result; + const int verbatim_match = (text[0] == '<'); + int match = 0; + + if (verbatim_match) + { + /* Strip the leading angle bracket. */ + text = text + 1; + text_len--; + } + + /* First, test against the fully qualified name of the symbol. */ + + if (strncmp (sym_name, text, text_len) == 0) + match = 1; + + if (match && !encoded) + { + /* One needed check before declaring a positive match is to verify + that iff we are doing a verbatim match, the decoded version + of the symbol name starts with '<'. Otherwise, this symbol name + is not a suitable completion. */ + const char *sym_name_copy = sym_name; + int has_angle_bracket; + + sym_name = ada_decode (sym_name); + has_angle_bracket = (sym_name[0] == '<'); + match = (has_angle_bracket == verbatim_match); + sym_name = sym_name_copy; + } + + if (match && !verbatim_match) + { + /* When doing non-verbatim match, another check that needs to + be done is to verify that the potentially matching symbol name + does not include capital letters, because the ada-mode would + not be able to understand these symbol names without the + angle bracket notation. */ + const char *tmp; + + for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++); + if (*tmp != '\0') + match = 0; + } + + /* Second: Try wild matching... */ + + if (!match && wild_match) + { + /* Since we are doing wild matching, this means that TEXT + may represent an unqualified symbol name. We therefore must + also compare TEXT against the unqualified name of the symbol. */ + sym_name = ada_unqualified_name (ada_decode (sym_name)); + + if (strncmp (sym_name, text, text_len) == 0) + match = 1; + } + + /* Finally: If we found a mach, prepare the result to return. */ + + if (!match) + return NULL; + + if (verbatim_match) + sym_name = add_angle_brackets (sym_name); + + if (!encoded) + sym_name = ada_decode (sym_name); + + return sym_name; +} + +/* A companion function to ada_make_symbol_completion_list(). + Check if SYM_NAME represents a symbol which name would be suitable + to complete TEXT (TEXT_LEN is the length of TEXT), in which case + it is appended at the end of the given string vector SV. + + ORIG_TEXT is the string original string from the user command + that needs to be completed. WORD is the entire command on which + completion should be performed. These two parameters are used to + determine which part of the symbol name should be added to the + completion vector. + if WILD_MATCH is set, then wild matching is performed. + ENCODED should be set if TEXT represents a symbol name in its + encoded formed (in which case the completion should also be + encoded). */ + +static void +symbol_completion_add (struct string_vector *sv, + const char *sym_name, + const char *text, int text_len, + const char *orig_text, const char *word, + int wild_match, int encoded) +{ + const char *match = symbol_completion_match (sym_name, text, text_len, + wild_match, encoded); + char *completion; + + if (match == NULL) + return; + + /* We found a match, so add the appropriate completion to the given + string vector. */ + + if (word == orig_text) + { + completion = xmalloc (strlen (match) + 5); + strcpy (completion, match); + } + else if (word > orig_text) + { + /* Return some portion of sym_name. */ + completion = xmalloc (strlen (match) + 5); + strcpy (completion, match + (word - orig_text)); + } + else + { + /* Return some of ORIG_TEXT plus sym_name. */ + completion = xmalloc (strlen (match) + (orig_text - word) + 5); + strncpy (completion, word, orig_text - word); + completion[orig_text - word] = '\0'; + strcat (completion, match); + } + + string_vector_append (sv, completion); +} + +/* Return a list of possible symbol names completing TEXT0. The list + is NULL terminated. WORD is the entire command on which completion + is made. */ + +static char ** +ada_make_symbol_completion_list (char *text0, char *word) +{ + char *text; + int text_len; + int wild_match; + int encoded; + struct string_vector result = new_string_vector (128); + struct symbol *sym; + struct symtab *s; + struct partial_symtab *ps; + struct minimal_symbol *msymbol; + struct objfile *objfile; + struct block *b, *surrounding_static_block = 0; + int i; + struct dict_iterator iter; + + if (text0[0] == '<') + { + text = xstrdup (text0); + make_cleanup (xfree, text); + text_len = strlen (text); + wild_match = 0; + encoded = 1; + } + else + { + text = xstrdup (ada_encode (text0)); + make_cleanup (xfree, text); + text_len = strlen (text); + for (i = 0; i < text_len; i++) + text[i] = tolower (text[i]); + + encoded = (strstr (text0, "__") != NULL); + /* If the name contains a ".", then the user is entering a fully + qualified entity name, and the match must not be done in wild + mode. Similarly, if the user wants to complete what looks like + an encoded name, the match must not be done in wild mode. */ + wild_match = (strchr (text0, '.') == NULL && !encoded); + } + + /* First, look at the partial symtab symbols. */ + ALL_PSYMTABS (objfile, ps) + { + struct partial_symbol **psym; + + /* If the psymtab's been read in we'll get it when we search + through the blockvector. */ + if (ps->readin) + continue; + + for (psym = objfile->global_psymbols.list + ps->globals_offset; + psym < (objfile->global_psymbols.list + ps->globals_offset + + ps->n_global_syms); psym++) + { + QUIT; + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (*psym), + text, text_len, text0, word, + wild_match, encoded); + } + + for (psym = objfile->static_psymbols.list + ps->statics_offset; + psym < (objfile->static_psymbols.list + ps->statics_offset + + ps->n_static_syms); psym++) + { + QUIT; + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (*psym), + text, text_len, text0, word, + wild_match, encoded); + } + } + + /* At this point scan through the misc symbol vectors and add each + symbol you find to the list. Eventually we want to ignore + anything that isn't a text symbol (everything else will be + handled by the psymtab code above). */ + + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (msymbol), + text, text_len, text0, word, wild_match, encoded); + } + + /* Search upwards from currently selected frame (so that we can + complete on local vars. */ + + for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) + { + if (!BLOCK_SUPERBLOCK (b)) + surrounding_static_block = b; /* For elmin of dups */ + + ALL_BLOCK_SYMBOLS (b, iter, sym) + { + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (sym), + text, text_len, text0, word, + wild_match, encoded); + } + } + + /* Go through the symtabs and check the externs and statics for + symbols which match. */ + + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, iter, sym) + { + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (sym), + text, text_len, text0, word, + wild_match, encoded); + } + } + + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + /* Don't do this block twice. */ + if (b == surrounding_static_block) + continue; + ALL_BLOCK_SYMBOLS (b, iter, sym) + { + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (sym), + text, text_len, text0, word, + wild_match, encoded); + } + } + + /* Append the closing NULL entry. */ + string_vector_append (&result, NULL); + + return (result.array); +} + /* Field Access */ /* Return non-zero if TYPE is a pointer to the GNAT dispatch table used @@ -10676,6 +11037,7 @@ const struct language_defn ada_language_defn = { 0, /* c-style arrays */ 1, /* String lower bound */ ada_get_gdb_completer_word_break_characters, + ada_make_symbol_completion_list, ada_language_arch_info, ada_print_array_index, default_pass_by_reference, diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h index 515f698a462..c2d08c39a67 100644 --- a/gdb/ada-lang.h +++ b/gdb/ada-lang.h @@ -312,9 +312,6 @@ extern enum language ada_update_initial_language (enum language, extern void clear_ada_sym_cache (void); -extern char **ada_make_symbol_completion_list (const char *text0, - const char *word); - extern int ada_lookup_symbol_list (const char *, const struct block *, domain_enum, struct ada_symbol_info**); diff --git a/gdb/c-lang.c b/gdb/c-lang.c index bf07cb30005..c4ef9d6103f 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -423,6 +423,7 @@ const struct language_defn c_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, c_language_arch_info, default_print_array_index, default_pass_by_reference, @@ -535,6 +536,7 @@ const struct language_defn cplus_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, cplus_language_arch_info, default_print_array_index, cp_pass_by_reference, @@ -569,6 +571,7 @@ const struct language_defn asm_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, c_language_arch_info, /* FIXME: la_language_arch_info. */ default_print_array_index, default_pass_by_reference, @@ -608,6 +611,7 @@ const struct language_defn minimal_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, c_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/f-lang.c b/gdb/f-lang.c index fb169fb929a..038126cb1d0 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -333,6 +333,7 @@ const struct language_defn f_language_defn = 0, /* arrays are first-class (not c-style) */ 1, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, f_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index 058ccac1010..e6c6f7d9274 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -1079,6 +1079,7 @@ const struct language_defn java_language_defn = 0, /* not c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, c_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/language.c b/gdb/language.c index cc94546e50a..a26218d744a 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -1201,6 +1201,7 @@ const struct language_defn unknown_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, unknown_language_arch_info, /* la_language_arch_info. */ default_print_array_index, default_pass_by_reference, @@ -1236,6 +1237,7 @@ const struct language_defn auto_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, unknown_language_arch_info, /* la_language_arch_info. */ default_print_array_index, default_pass_by_reference, @@ -1270,6 +1272,7 @@ const struct language_defn local_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, unknown_language_arch_info, /* la_language_arch_info. */ default_print_array_index, default_pass_by_reference, diff --git a/gdb/language.h b/gdb/language.h index 1639d4cf662..f7e654d2294 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -249,6 +249,11 @@ struct language_defn /* The list of characters forming word boundaries. */ char *(*la_word_break_characters) (void); + /* Should return a NULL terminated array of all symbols which + are possible completions for TEXT. WORD is the entire command + on which the completion is being made. */ + char **(*la_make_symbol_completion_list) (char *text, char *word); + /* The per-architecture (OS/ABI) language information. */ void (*la_language_arch_info) (struct gdbarch *, struct language_arch_info *); diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index bdb1cbdf4fd..6b51fd5328c 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -384,6 +384,7 @@ const struct language_defn m2_language_defn = 0, /* arrays are first-class (not c-style) */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, m2_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index 89d06a72add..ccf80685407 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -518,6 +518,7 @@ const struct language_defn objc_language_defn = { 1, /* C-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, c_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/p-lang.c b/gdb/p-lang.c index b8884bd1451..f7b901f24d1 100644 --- a/gdb/p-lang.c +++ b/gdb/p-lang.c @@ -423,6 +423,7 @@ const struct language_defn pascal_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, pascal_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c index a42f87f7a7d..339c6142390 100644 --- a/gdb/scm-lang.c +++ b/gdb/scm-lang.c @@ -262,6 +262,7 @@ const struct language_defn scm_language_defn = 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, + default_make_symbol_completion_list, c_language_arch_info, default_print_array_index, default_pass_by_reference, diff --git a/gdb/symtab.c b/gdb/symtab.c index 3912ebd4fd1..40e31dc45da 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3523,17 +3523,13 @@ language_search_unquoted_string (char *text, char *p) return p; } - -/* Return a NULL terminated array of all symbols (regardless of class) - which begin by matching TEXT. If the answer is no symbols, then - the return value is an array which contains only a NULL pointer. - - Problem: All of the symbols have to be copied because readline frees them. - I'm not going to worry about this; hopefully there won't be that many. */ - char ** -make_symbol_completion_list (char *text, char *word) +default_make_symbol_completion_list (char *text, char *word) { + /* Problem: All of the symbols have to be copied because readline + frees them. I'm not going to worry about this; hopefully there + won't be that many. */ + struct symbol *sym; struct symtab *s; struct partial_symtab *ps; @@ -3548,8 +3544,7 @@ make_symbol_completion_list (char *text, char *word) /* Length of sym_text. */ int sym_text_len; - /* Now look for the symbol we are supposed to complete on. - FIXME: This should be language-specific. */ + /* Now look for the symbol we are supposed to complete on. */ { char *p; char quote_found; @@ -3717,6 +3712,16 @@ make_symbol_completion_list (char *text, char *word) return (return_val); } +/* Return a NULL terminated array of all symbols (regardless of class) + which begin by matching TEXT. If the answer is no symbols, then + the return value is an array which contains only a NULL pointer. */ + +char ** +make_symbol_completion_list (char *text, char *word) +{ + return current_language->la_make_symbol_completion_list (text, word); +} + /* Like make_symbol_completion_list, but returns a list of symbols defined in a source file FILE. */ diff --git a/gdb/symtab.h b/gdb/symtab.h index 5de08abf4ce..c19e74124c2 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1322,6 +1322,7 @@ extern void forget_cached_source_info (void); extern void select_source_symtab (struct symtab *); +extern char **default_make_symbol_completion_list (char *, char *); extern char **make_symbol_completion_list (char *, char *); extern char **make_file_symbol_completion_list (char *, char *, char *); -- 2.30.2