From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21614 invoked by alias); 29 Jul 2008 20:39:17 -0000 Received: (qmail 21602 invoked by uid 22791); 29 Jul 2008 20:39:15 -0000 X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 29 Jul 2008 20:38:52 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id m6TKcoKc005286 for ; Tue, 29 Jul 2008 16:38:50 -0400 Received: from pobox.corp.redhat.com (pobox.corp.redhat.com [10.11.255.20]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m6TKcou9021447; Tue, 29 Jul 2008 16:38:50 -0400 Received: from opsy.redhat.com (vpn-10-116.bos.redhat.com [10.16.10.116]) by pobox.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m6TKcn13027807; Tue, 29 Jul 2008 16:38:49 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id 0EA2A3784E5; Tue, 29 Jul 2008 14:38:49 -0600 (MDT) To: gdb-patches@sourceware.org Subject: RFA: PR 2484: completion of macro names From: Tom Tromey Reply-To: tromey@redhat.com X-Attribution: Tom Date: Tue, 29 Jul 2008 20:39:00 -0000 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-07/txt/msg00548.txt.bz2 This patch fixes PR gdb/2484. The bug here is that TAB completion does not complete macro names. This patch adds a new la_macro_expansion field to struct language_defn, and updates all the languages. (It also fixes a bug in field ordering in a couple language initializers.) It also adds a callback argument to macro_for_each. In keeping with my understanding of Jim's wishes for the macro code, I made the new macro_for_each_in_scope take an explicit pair of file/line arguments, rather than a macro_scope. This means that macrotab.c still can remain blissfully ignorant of struct macro_scope. The guts of the change are in symtab.c. The patch changes default_make_symbol_completion_list to look at all the macros in scope, plus all the user-defined macros. Built and regression tested on the compile farm (x86-64). A couple new test cases included. Ok? Tom 2008-07-28 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 (struct macro_scope): Declare. (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. * 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. * Makefile.in (symtab.o): Add macroscope_h, macrotab_h. b/gdb/testsuite/ChangeLog: 2008-07-28 Tom Tromey * gdb.base/macscp1.c (FIFTY_SEVEN): New macro. (TWENTY_THREE): Likewise. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index a24e29b..295455f 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2904,7 +2904,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \ $(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \ $(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \ $(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h) \ - $(solist_h) $(p_lang_h) $(addrmap_h) + $(solist_h) $(p_lang_h) $(addrmap_h) $(macrotab_h) $(macroscope_h) target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \ $(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \ $(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \ diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index f3f1f34..5aabcdd 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -10934,6 +10934,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, + 0, &ada_exp_descriptor, parse, ada_error, diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 9ce4bb9..d467587 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -390,6 +390,7 @@ const struct language_defn c_language_defn = type_check_off, case_sensitive_on, array_row_major, + 1, &exp_descriptor_standard, c_preprocess_and_parse, c_error, @@ -503,6 +504,7 @@ const struct language_defn cplus_language_defn = type_check_off, case_sensitive_on, array_row_major, + 1, &exp_descriptor_standard, c_preprocess_and_parse, c_error, @@ -538,6 +540,7 @@ const struct language_defn asm_language_defn = type_check_off, case_sensitive_on, array_row_major, + 1, &exp_descriptor_standard, c_preprocess_and_parse, c_error, @@ -578,6 +581,7 @@ const struct language_defn minimal_language_defn = type_check_off, case_sensitive_on, array_row_major, + 1, &exp_descriptor_standard, c_preprocess_and_parse, c_error, diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 5dcbd33..813cef7 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -313,6 +313,7 @@ const struct language_defn f_language_defn = type_check_on, case_sensitive_off, array_column_major, + 0, &exp_descriptor_standard, f_parse, /* parser */ f_error, /* parser error function */ diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index 6080839..4686c7b 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -1057,6 +1057,7 @@ const struct language_defn java_language_defn = type_check_off, case_sensitive_on, array_row_major, + 0, &exp_descriptor_java, java_parse, java_error, diff --git a/gdb/language.c b/gdb/language.c index 66e5542..b5c8173 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -1179,8 +1179,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, + 0, &exp_descriptor_standard, unk_lang_parser, unk_lang_error, @@ -1215,8 +1216,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, + 0, &exp_descriptor_standard, unk_lang_parser, unk_lang_error, @@ -1252,6 +1254,7 @@ const struct language_defn local_language_defn = type_check_off, case_sensitive_on, array_row_major, + 0, &exp_descriptor_standard, unk_lang_parser, unk_lang_error, diff --git a/gdb/language.h b/gdb/language.h index 8bdc212..efea145 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -153,6 +153,9 @@ struct language_defn /* Multi-dimensional array ordering */ enum array_ordering la_array_ordering; + /* True if this language supports C-like macro expansion. */ + unsigned int la_macro_expansion : 1; + /* Definitions related to expression printing, prefixifying, and dumping */ diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index bb205ad..5e7c111 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -364,6 +364,7 @@ const struct language_defn m2_language_defn = type_check_on, case_sensitive_on, array_row_major, + 0, &exp_descriptor_modula2, m2_parse, /* parser */ m2_error, /* parser error function */ diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c index 4a70d4f..030251a 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -318,7 +318,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) @@ -339,7 +340,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 7633c98..a96d4af 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -887,25 +887,66 @@ 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; + + if (compare_locations (key->start_file, key->start_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 5ff36ea..25a6b88 100644 --- a/gdb/macrotab.h +++ b/gdb/macrotab.h @@ -75,6 +75,9 @@ struct macro_table; /* The definition of a single macro. */ struct macro_definition; +/* A macro scope. */ +struct macro_scope; + /* A source file that participated in a compilation unit --- either a main file, or an #included file. If a file is #included more than once, the presence of the `included_from' and `included_at_line' @@ -305,12 +308,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 56871e3..4ac1d33 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -497,6 +497,7 @@ const struct language_defn objc_language_defn = { type_check_off, case_sensitive_on, array_row_major, + 1, &exp_descriptor_standard, objc_parse, objc_error, diff --git a/gdb/p-lang.c b/gdb/p-lang.c index 2accf35..e9329f1 100644 --- a/gdb/p-lang.c +++ b/gdb/p-lang.c @@ -403,6 +403,7 @@ const struct language_defn pascal_language_defn = type_check_on, case_sensitive_on, array_row_major, + 0, &exp_descriptor_standard, pascal_parse, pascal_error, diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c index 991e4b4..0020a57 100644 --- a/gdb/scm-lang.c +++ b/gdb/scm-lang.c @@ -240,6 +240,7 @@ const struct language_defn scm_language_defn = type_check_off, case_sensitive_off, array_row_major, + 0, &exp_descriptor_scm, scm_parse, c_error, diff --git a/gdb/symtab.c b/gdb/symtab.c index 2ab520d..2ea1a96 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 */ @@ -3636,6 +3638,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) { @@ -3822,6 +3847,32 @@ default_make_symbol_completion_list (char *text, char *word) } } + if (current_language->la_macro_expansion) + { + 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. 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/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp index 15d3f2f..290f040 100644 --- a/gdb/testsuite/gdb.base/macscp.exp +++ b/gdb/testsuite/gdb.base/macscp.exp @@ -477,3 +477,58 @@ gdb_test "print M" \ gdb_test "macro expand SPLICE(x, y)" \ "Token splicing is not implemented yet." \ "macro splicing lexes correctly" + + +# 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" } + } + +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" } + } diff --git a/gdb/testsuite/gdb.base/macscp1.c b/gdb/testsuite/gdb.base/macscp1.c index 200ac26..3ac41c6 100644 --- a/gdb/testsuite/gdb.base/macscp1.c +++ b/gdb/testsuite/gdb.base/macscp1.c @@ -5,6 +5,8 @@ #define STRINGIFY(a) INNER_STRINGIFY(a) #define INNER_STRINGIFY(a) #a +#define FIFTY_SEVEN 57 + /* A macro named UNTIL_ is #defined until just before the definition of the function . @@ -75,6 +77,8 @@ macscp_expr (void) foo = 2; } +#define TWENTY_THREE 23 + int main (int argc, char **argv) {