From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24151 invoked by alias); 30 Sep 2008 16:13:59 -0000 Received: (qmail 24134 invoked by uid 22791); 30 Sep 2008 16:13:54 -0000 X-Spam-Check-By: sourceware.org Received: from mx2.redhat.com (HELO mx2.redhat.com) (66.187.237.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 30 Sep 2008 16:13:19 +0000 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id m8UG9Af8027052; Tue, 30 Sep 2008 12:09:10 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m8UG99HH024317; Tue, 30 Sep 2008 12:09:09 -0400 Received: from opsy.redhat.com (vpn-10-3.bos.redhat.com [10.16.10.3]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id m8UG9707006043; Tue, 30 Sep 2008 12:09:08 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id 1791350859E; Tue, 30 Sep 2008 10:07:49 -0600 (MDT) To: Pedro Alves Cc: gdb-patches@sourceware.org Subject: Re: RFA: PR 2484: completion of macro names References: <200809282301.17191.pedro@codesourcery.com> From: Tom Tromey Reply-To: Tom Tromey X-Attribution: Tom Date: Tue, 30 Sep 2008 16:13:00 -0000 In-Reply-To: <200809282301.17191.pedro@codesourcery.com> (Pedro Alves's message of "Sun\, 28 Sep 2008 23\:01\:16 +0100") 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-09/txt/msg00573.txt.bz2 Pedro> This matches macros that have been undefined before the Pedro> current line, was that intended? E.g., [...] Thanks. I fixed this and added a new test. Pedro> I'm a bonehead, and don't follow this :-). Could you show/add here Pedro> an example of one such case, that would matter for completion? I added an example. Pedro> Since several other language flags are enums, and since there Pedro> aren't that many languages that we have to consider space Pedro> savings here, making this an enum as well would make these, Done. Pedro> Out of curiosity --- can one use the C preprocessor with gcj? No. Pedro> (Or any other non-C frontend for the matter) Fortran allows macro expansion now. I did not change this, because it also requires changes to the Fortran lexer in gdb. I think that is outside the scope of this patch. Perhaps a Fortran maintainer could implement it. Here's the updated patch. Built and regtested on x86-64. Tom 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 Tom Tromey * gdb.base/macscp.exp: Add completion tests. * gdb.base/macscp1.c (FIFTY_SEVEN): New macro. (TWENTY_THREE): Likewise. (FORTY_EIGHT): Likewise. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 7176561..132e89e 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 ebe781b..ce75345 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, @@ -508,6 +509,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, @@ -543,6 +545,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, @@ -583,6 +586,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 8ae7775..7339aa4 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 39d8f48..260d1cf 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 7b0b44a..84a1f6c 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, @@ -1171,8 +1172,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, @@ -1208,6 +1210,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 04d4da2..ee84eab 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -113,6 +113,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. */ @@ -158,6 +169,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 : 1; + /* Definitions related to expression printing, prefixifying, and dumping */ diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index 8bc0ce7..c3226fc 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 8213c0d..bea5c08 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -326,7 +326,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) @@ -347,7 +348,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..c33c028 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 71f1d3e..25b4c5f 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 1692c3d..8d88758 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 b763e04..45755ce 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 003e27a..5dea59a 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 10987e2..437d414 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/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp index 3424714..426c98d 100644 --- a/gdb/testsuite/gdb.base/macscp.exp +++ b/gdb/testsuite/gdb.base/macscp.exp @@ -484,3 +484,74 @@ gdb_test "macro undef" \ 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" } + } + +# 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" } + } diff --git a/gdb/testsuite/gdb.base/macscp1.c b/gdb/testsuite/gdb.base/macscp1.c index 200ac26..97d6b49 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) {