From 9a044a8903fdfe53411787984379191d15373019 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 30 Sep 2008 17:21:28 +0000 Subject: [PATCH] gdb PR gdb/2484: * symtab.c (struct add_macro_name_data): New struct. (add_macro_name): New function. (default_make_symbol_completion_list): Complete macro names. * scm-lang.c (scm_language_defn): Update. * p-lang.c (pascal_language_defn): Update. * objc-lang.c (objc_language_defn): Update. * macrotab.h (macro_callback_fn): Add user_data argument. (macro_for_each): Likewise. (macro_for_each_in_scope): Declare. * macrotab.c: (struct macro_for_each_data): New struct. (foreach_macro): Use it. (macro_for_each): Likewise. (foreach_macro_in_scope): New function. (macro_for_each_in_scope): Likewise. * macrocmd.c (print_one_macro): Add argument. (macro_list_command): Pass NULL to macro_for_each. * m2-lang.c (m2_language_defn): Update. * language.h (struct language_defn) : New field. (macro_expansion): New enum. * language.c (unknown_language_defn): Update. Fix order of initializers. (auto_language_defn): Likewise. (local_language_defn): Update. * jv-lang.c (java_language_defn): Update. * f-lang.c (f_language_defn): Update. * c-lang.c (c_language_defn): Update. (cplus_language_defn): Likewise. (asm_language_defn): Likewise. (minimal_language_defn): Likewise. * ada-lang.c (ada_language_defn): Update. gdb/testsuite * gdb.base/macscp.exp: Add completion tests. * gdb.base/macscp1.c (FIFTY_SEVEN): New macro. (TWENTY_THREE): Likewise. (FORTY_EIGHT): Likewise. --- gdb/ChangeLog | 35 ++++++++++++++++ gdb/ada-lang.c | 1 + gdb/c-lang.c | 4 ++ gdb/f-lang.c | 1 + gdb/jv-lang.c | 1 + gdb/language.c | 7 +++- gdb/language.h | 14 +++++++ gdb/m2-lang.c | 1 + gdb/macrocmd.c | 5 ++- gdb/macrotab.c | 62 +++++++++++++++++++++++---- gdb/macrotab.h | 22 +++++++--- gdb/objc-lang.c | 1 + gdb/p-lang.c | 1 + gdb/scm-lang.c | 1 + gdb/symtab.c | 54 ++++++++++++++++++++++++ gdb/testsuite/ChangeLog | 7 ++++ gdb/testsuite/gdb.base/macscp.exp | 70 +++++++++++++++++++++++++++++++ gdb/testsuite/gdb.base/macscp1.c | 7 ++++ 18 files changed, 277 insertions(+), 17 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index dfa6df18b1..6d33cbbe3c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,38 @@ +2008-09-30 Tom Tromey + + PR gdb/2484: + * symtab.c (struct add_macro_name_data): New struct. + (add_macro_name): New function. + (default_make_symbol_completion_list): Complete macro names. + * scm-lang.c (scm_language_defn): Update. + * p-lang.c (pascal_language_defn): Update. + * objc-lang.c (objc_language_defn): Update. + * macrotab.h (macro_callback_fn): Add user_data argument. + (macro_for_each): Likewise. + (macro_for_each_in_scope): Declare. + * macrotab.c: (struct macro_for_each_data): New struct. + (foreach_macro): Use it. + (macro_for_each): Likewise. + (foreach_macro_in_scope): New function. + (macro_for_each_in_scope): Likewise. + * macrocmd.c (print_one_macro): Add argument. + (macro_list_command): Pass NULL to macro_for_each. + * m2-lang.c (m2_language_defn): Update. + * language.h (struct language_defn) : New + field. + (macro_expansion): New enum. + * language.c (unknown_language_defn): Update. Fix order of + initializers. + (auto_language_defn): Likewise. + (local_language_defn): Update. + * jv-lang.c (java_language_defn): Update. + * f-lang.c (f_language_defn): Update. + * c-lang.c (c_language_defn): Update. + (cplus_language_defn): Likewise. + (asm_language_defn): Likewise. + (minimal_language_defn): Likewise. + * ada-lang.c (ada_language_defn): Update. + 2008-09-30 Joel Brobecker * dwarf2read.c (dwarf2_get_subprogram_pc_bounds): New function. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index d4d7dc0352..c425c80d41 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -10935,6 +10935,7 @@ const struct language_defn ada_language_defn = { case_sensitive_on, /* Yes, Ada is case-insensitive, but that's not quite what this means. */ array_row_major, + macro_expansion_no, &ada_exp_descriptor, parse, ada_error, diff --git a/gdb/c-lang.c b/gdb/c-lang.c index a9cd9c2970..a978b17ebc 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -392,6 +392,7 @@ const struct language_defn c_language_defn = type_check_off, case_sensitive_on, array_row_major, + macro_expansion_c, &exp_descriptor_standard, c_preprocess_and_parse, c_error, @@ -509,6 +510,7 @@ const struct language_defn cplus_language_defn = type_check_off, case_sensitive_on, array_row_major, + macro_expansion_c, &exp_descriptor_standard, c_preprocess_and_parse, c_error, @@ -545,6 +547,7 @@ const struct language_defn asm_language_defn = type_check_off, case_sensitive_on, array_row_major, + macro_expansion_c, &exp_descriptor_standard, c_preprocess_and_parse, c_error, @@ -586,6 +589,7 @@ const struct language_defn minimal_language_defn = type_check_off, case_sensitive_on, array_row_major, + macro_expansion_c, &exp_descriptor_standard, c_preprocess_and_parse, c_error, diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 4e2f3c44ec..736d6c60b0 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -316,6 +316,7 @@ const struct language_defn f_language_defn = type_check_on, case_sensitive_off, array_column_major, + macro_expansion_no, &exp_descriptor_standard, f_parse, /* parser */ f_error, /* parser error function */ diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index 69570b43bb..0470eef69d 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -1102,6 +1102,7 @@ const struct language_defn java_language_defn = type_check_off, case_sensitive_on, array_row_major, + macro_expansion_no, &exp_descriptor_java, java_parse, java_error, diff --git a/gdb/language.c b/gdb/language.c index 0b21dc3ccc..121fc55c6e 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -1135,8 +1135,9 @@ const struct language_defn unknown_language_defn = language_unknown, range_check_off, type_check_off, - array_row_major, case_sensitive_on, + array_row_major, + macro_expansion_no, &exp_descriptor_standard, unk_lang_parser, unk_lang_error, @@ -1172,8 +1173,9 @@ const struct language_defn auto_language_defn = language_auto, range_check_off, type_check_off, - array_row_major, case_sensitive_on, + array_row_major, + macro_expansion_no, &exp_descriptor_standard, unk_lang_parser, unk_lang_error, @@ -1210,6 +1212,7 @@ const struct language_defn local_language_defn = type_check_off, case_sensitive_on, array_row_major, + macro_expansion_no, &exp_descriptor_standard, unk_lang_parser, unk_lang_error, diff --git a/gdb/language.h b/gdb/language.h index ba28540b56..cc10ff2742 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -105,6 +105,17 @@ extern enum case_sensitivity case_sensitive_on, case_sensitive_off } case_sensitivity; + + +/* macro_expansion == + macro_expansion_no: No macro expansion is available + macro_expansion_c: C-like macro expansion is available */ + +enum macro_expansion + { + macro_expansion_no, macro_expansion_c + }; + /* Per architecture (OS/ABI) language information. */ @@ -150,6 +161,9 @@ struct language_defn /* Multi-dimensional array ordering */ enum array_ordering la_array_ordering; + /* Style of macro expansion, if any, supported by this language. */ + enum macro_expansion la_macro_expansion; + /* Definitions related to expression printing, prefixifying, and dumping */ diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index 2b3ca6ab47..ea59403a24 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -367,6 +367,7 @@ const struct language_defn m2_language_defn = type_check_on, case_sensitive_on, array_row_major, + macro_expansion_no, &exp_descriptor_modula2, m2_parse, /* parser */ m2_error, /* parser error function */ diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c index c9ab440f79..56e9a48ff2 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -345,7 +345,8 @@ macro_undef_command (char *exp, int from_tty) static void -print_one_macro (const char *name, const struct macro_definition *macro) +print_one_macro (const char *name, const struct macro_definition *macro, + void *ignore) { fprintf_filtered (gdb_stdout, "macro define %s", name); if (macro->kind == macro_function_like) @@ -366,7 +367,7 @@ print_one_macro (const char *name, const struct macro_definition *macro) static void macro_list_command (char *exp, int from_tty) { - macro_for_each (macro_user_macros, print_one_macro); + macro_for_each (macro_user_macros, print_one_macro, NULL); } diff --git a/gdb/macrotab.c b/gdb/macrotab.c index 7633c98d4f..c33c028d22 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -887,25 +887,71 @@ macro_definition_location (struct macro_source_file *source, } +/* The type for callback data for iterating the splay tree in + macro_for_each and macro_for_each_in_scope. Only the latter uses + the FILE and LINE fields. */ +struct macro_for_each_data +{ + macro_callback_fn fn; + void *user_data; + struct macro_source_file *file; + int line; +}; + /* Helper function for macro_for_each. */ static int -foreach_macro (splay_tree_node node, void *fnp) +foreach_macro (splay_tree_node node, void *arg) { - macro_callback_fn *fn = (macro_callback_fn *) fnp; + struct macro_for_each_data *datum = (struct macro_for_each_data *) arg; struct macro_key *key = (struct macro_key *) node->key; struct macro_definition *def = (struct macro_definition *) node->value; - (**fn) (key->name, def); + (*datum->fn) (key->name, def, datum->user_data); return 0; } /* Call FN for every macro in TABLE. */ void -macro_for_each (struct macro_table *table, macro_callback_fn fn) +macro_for_each (struct macro_table *table, macro_callback_fn fn, + void *user_data) +{ + struct macro_for_each_data datum; + datum.fn = fn; + datum.user_data = user_data; + datum.file = NULL; + datum.line = 0; + splay_tree_foreach (table->definitions, foreach_macro, &datum); +} + +static int +foreach_macro_in_scope (splay_tree_node node, void *info) { - /* Note that we pass in the address of 'fn' because, pedantically - speaking, we can't necessarily cast a pointer-to-function to a - void*. */ - splay_tree_foreach (table->definitions, foreach_macro, &fn); + struct macro_for_each_data *datum = (struct macro_for_each_data *) info; + struct macro_key *key = (struct macro_key *) node->key; + struct macro_definition *def = (struct macro_definition *) node->value; + + /* See if this macro is defined before the passed-in line, and + extends past that line. */ + if (compare_locations (key->start_file, key->start_line, + datum->file, datum->line) < 0 + && (!key->end_file + || compare_locations (key->end_file, key->end_line, + datum->file, datum->line) >= 0)) + (*datum->fn) (key->name, def, datum->user_data); + return 0; +} + +/* Call FN for every macro is visible in SCOPE. */ +void +macro_for_each_in_scope (struct macro_source_file *file, int line, + macro_callback_fn fn, void *user_data) +{ + struct macro_for_each_data datum; + datum.fn = fn; + datum.user_data = user_data; + datum.file = file; + datum.line = line; + splay_tree_foreach (file->table->definitions, + foreach_macro_in_scope, &datum); } diff --git a/gdb/macrotab.h b/gdb/macrotab.h index 71f1d3ed54..25b4c5f5f3 100644 --- a/gdb/macrotab.h +++ b/gdb/macrotab.h @@ -305,12 +305,24 @@ struct macro_source_file *(macro_definition_location int *definition_line)); /* Callback function when walking a macro table. NAME is the name of - the macro, and DEFINITION is the definition. */ + the macro, and DEFINITION is the definition. USER_DATA is an + arbitrary pointer which is passed by the caller to macro_for_each + or macro_for_each_in_scope. */ typedef void (*macro_callback_fn) (const char *name, - const struct macro_definition *definition); - -/* Call the function FN for each macro in the macro table TABLE. */ -void macro_for_each (struct macro_table *table, macro_callback_fn fn); + const struct macro_definition *definition, + void *user_data); + +/* Call the function FN for each macro in the macro table TABLE. + USER_DATA is passed, untranslated, to FN. */ +void macro_for_each (struct macro_table *table, macro_callback_fn fn, + void *user_data); + +/* Call the function FN for each macro that is visible in a given + scope. The scope is represented by FILE and LINE. USER_DATA is + passed, untranslated, to FN. */ +void macro_for_each_in_scope (struct macro_source_file *file, int line, + macro_callback_fn fn, + void *user_data); #endif /* MACROTAB_H */ diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index 4608168826..553080a113 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -504,6 +504,7 @@ const struct language_defn objc_language_defn = { type_check_off, case_sensitive_on, array_row_major, + macro_expansion_c, &exp_descriptor_standard, objc_parse, objc_error, diff --git a/gdb/p-lang.c b/gdb/p-lang.c index b829f8d4aa..7ecdd8d08f 100644 --- a/gdb/p-lang.c +++ b/gdb/p-lang.c @@ -406,6 +406,7 @@ const struct language_defn pascal_language_defn = type_check_on, case_sensitive_on, array_row_major, + macro_expansion_no, &exp_descriptor_standard, pascal_parse, pascal_error, diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c index 607efb6e5d..42d2502387 100644 --- a/gdb/scm-lang.c +++ b/gdb/scm-lang.c @@ -246,6 +246,7 @@ const struct language_defn scm_language_defn = type_check_off, case_sensitive_off, array_row_major, + macro_expansion_no, &exp_descriptor_scm, scm_parse, c_error, diff --git a/gdb/symtab.c b/gdb/symtab.c index 10987e2548..437d4142ec 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -58,6 +58,8 @@ #include "observer.h" #include "gdb_assert.h" #include "solist.h" +#include "macrotab.h" +#include "macroscope.h" /* Prototypes for local functions */ @@ -3640,6 +3642,29 @@ language_search_unquoted_string (char *text, char *p) return p; } +/* Type of the user_data argument passed to add_macro_name. The + contents are simply whatever is needed by + completion_list_add_name. */ +struct add_macro_name_data +{ + char *sym_text; + int sym_text_len; + char *text; + char *word; +}; + +/* A callback used with macro_for_each and macro_for_each_in_scope. + This adds a macro's name to the current completion list. */ +static void +add_macro_name (const char *name, const struct macro_definition *ignore, + void *user_data) +{ + struct add_macro_name_data *datum = (struct add_macro_name_data *) user_data; + completion_list_add_name ((char *) name, + datum->sym_text, datum->sym_text_len, + datum->text, datum->word); +} + char ** default_make_symbol_completion_list (char *text, char *word) { @@ -3826,6 +3851,35 @@ default_make_symbol_completion_list (char *text, char *word) } } + if (current_language->la_macro_expansion == macro_expansion_c) + { + struct macro_scope *scope; + struct add_macro_name_data datum; + + datum.sym_text = sym_text; + datum.sym_text_len = sym_text_len; + datum.text = text; + datum.word = word; + + /* Add any macros visible in the default scope. Note that this + may yield the occasional wrong result, because an expression + might be evaluated in a scope other than the default. For + example, if the user types "break file:line if ", the + resulting expression will be evaluated at "file:line" -- but + at there does not seem to be a way to detect this at + completion time. */ + scope = default_macro_scope (); + if (scope) + { + macro_for_each_in_scope (scope->file, scope->line, + add_macro_name, &datum); + xfree (scope); + } + + /* User-defined macros are always visible. */ + macro_for_each (macro_user_macros, add_macro_name, &datum); + } + return (return_val); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 60adacf7da..d4d08115df 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2008-09-30 Tom Tromey + + * gdb.base/macscp.exp: Add completion tests. + * gdb.base/macscp1.c (FIFTY_SEVEN): New macro. + (TWENTY_THREE): Likewise. + (FORTY_EIGHT): Likewise. + 2008-09-30 Tom Tromey * gdb.base/macscp.exp: Change "M" to "MACRO_TO_EXPAND" diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp index 152e006d4f..2a43a28eb2 100644 --- a/gdb/testsuite/gdb.base/macscp.exp +++ b/gdb/testsuite/gdb.base/macscp.exp @@ -480,6 +480,76 @@ gdb_test "macro undef" \ "usage: macro undef.*" \ "macro undef with no arguments" +# Completion tests. + +# The macro FIFTY_SEVEN is in scope at this point. +send_gdb "p FIFTY_\t" +gdb_expect { + -re "^p FIFTY_SEVEN $"\ + { send_gdb "\n" + gdb_expect { + -re "^.* = 57.*$gdb_prompt $"\ + { pass "complete 'p FIFTY_SEVEN'"} + -re ".*$gdb_prompt $" { fail "complete 'p FIFTY_SEVEN'"} + timeout {fail "(timeout) complete 'p FIFTY_SEVEN'"} + } + } + -re ".*$gdb_prompt $" { fail "complete 'p FIFTY_SEVEN'" } + timeout { fail "(timeout) complete 'p FIFTY_SEVEN' 2" } + } + +# The macro TWENTY_THREE is not in scope. +send_gdb "p TWENTY_\t" +gdb_expect { + -re "^p TWENTY_\\\x07$"\ + { send_gdb "\n" + gdb_expect { + -re "No symbol \"TWENTY_\" in current context\\..*$gdb_prompt $"\ + { pass "complete 'p TWENTY_'"} + -re ".*$gdb_prompt $" { fail "complete 'p TWENTY_'"} + timeout {fail "(timeout) complete 'p TWENTY_'"} + } + } + -re ".*$gdb_prompt $" { fail "complete 'p TWENTY_'" } + timeout { fail "(timeout) complete 'p TWENTY_' 2" } + } + +# The macro FORTY_EIGHT was undefined and thus is not in scope. +send_gdb "p FORTY_\t" +gdb_expect { + -re "^p FORTY_\\\x07$"\ + { send_gdb "\n" + gdb_expect { + -re "No symbol \"FORTY_\" in current context\\..*$gdb_prompt $"\ + { pass "complete 'p FORTY_'"} + -re ".*$gdb_prompt $" { fail "complete 'p FORTY_'"} + timeout {fail "(timeout) complete 'p FORTY_'"} + } + } + -re ".*$gdb_prompt $" { fail "complete 'p FORTY_'" } + timeout { fail "(timeout) complete 'p FORTY_' 2" } + } + +gdb_test "macro define TWENTY_THREE 25" \ + "" \ + "defining TWENTY_THREE" + +# User-defined macros are always in scope. +send_gdb "p TWENTY_\t" +gdb_expect { + -re "^p TWENTY_THREE $"\ + { send_gdb "\n" + gdb_expect { + -re "^.* = 25.*$gdb_prompt $"\ + { pass "complete 'p TWENTY_THREE'"} + -re ".*$gdb_prompt $" { fail "complete 'p TWENTY_THREE'"} + timeout {fail "(timeout) complete 'p TWENTY_THREE'"} + } + } + -re ".*$gdb_prompt $" { fail "complete 'p TWENTY_THREE'" } + timeout { fail "(timeout) complete 'p TWENTY_THREE' 2" } + } + # Splicing tests. gdb_test "macro expand SPLICE(x, y)" \ diff --git a/gdb/testsuite/gdb.base/macscp1.c b/gdb/testsuite/gdb.base/macscp1.c index 0be78c6d9c..40f1217b2d 100644 --- a/gdb/testsuite/gdb.base/macscp1.c +++ b/gdb/testsuite/gdb.base/macscp1.c @@ -5,6 +5,11 @@ #define STRINGIFY(a) INNER_STRINGIFY(a) #define INNER_STRINGIFY(a) #a +#define FIFTY_SEVEN 57 + +#define FORTY_EIGHT 48 +#undef FORTY_EIGHT + /* A macro named UNTIL_ is #defined until just before the definition of the function . @@ -75,6 +80,8 @@ macscp_expr (void) foo = 2; } +#define TWENTY_THREE 23 + int main (int argc, char **argv) { -- 2.34.1