diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2020-11-13 18:27:42 +0000 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2020-11-14 21:19:27 +0000 |
commit | 9dd02fc063284f59994c095ce525e1b8934b0dc1 (patch) | |
tree | 54b999286c860db72841595efeeb35f80dd85724 /gdb | |
parent | 758cb81029440efad398f1aba4789a18e59daee2 (diff) | |
download | gdb-9dd02fc063284f59994c095ce525e1b8934b0dc1.zip gdb-9dd02fc063284f59994c095ce525e1b8934b0dc1.tar.gz gdb-9dd02fc063284f59994c095ce525e1b8934b0dc1.tar.bz2 |
gdb: add tab completion of type field names for Fortran
Add support for tab-completion on Fortran field names. Consider this
test case:
program test
type my_type
integer :: field_a
integer :: other_field
integer :: last_field
end type my_type
type(my_type) :: var
print *, var
end program test
And the GDB session before this patch:
(gdb) start
...
(gdb) p var% <- Trigger TAB completion here.
Display all 200 possibilities? (y or n) n
(gdb) p var%
And the GDB session with this patch:
(gdb) start
...
(gdb) p var% <- Trigger TAB completion here.
field_a last_field other_field
(gdb) p var%
The implementation for this is basically copied from c-exp.y, I
tweaked the parser patterns to be appropriate for Fortran, and it
"just worked".
gdb/ChangeLog:
PR cli/26879
* f-exp.y (COMPLETE): New token.
(exp): Two new rules for tab-completion.
(saw_name_at_eof): New static global.
(last_was_structop): Likewise.
(yylex): Set new variables, and return COMPLETE token at the end
of the input stream in some cases.
gdb/testsuite/ChangeLog:
PR cli/26879
* gdb.fortran/completion.exp: New file.
* gdb.fortran/completion.f90: New file.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/f-exp.y | 51 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/completion.exp | 46 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/completion.f90 | 26 |
5 files changed, 135 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 69af942..a70c5fe 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2020-11-14 Andrew Burgess <andrew.burgess@embecosm.com> + + PR cli/26879 + * f-exp.y (COMPLETE): New token. + (exp): Two new rules for tab-completion. + (saw_name_at_eof): New static global. + (last_was_structop): Likewise. + (yylex): Set new variables, and return COMPLETE token at the end + of the input stream in some cases. + 2020-11-14 Tom Tromey <tom@tromey.com> * infrun.c (fetch_inferior_event): Use "bool" for should_stop. diff --git a/gdb/f-exp.y b/gdb/f-exp.y index 5e16678..edfbe0c 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -149,6 +149,7 @@ static int parse_number (struct parser_state *, const char *, int, %token <lval> BOOLEAN_LITERAL %token <ssym> NAME %token <tsym> TYPENAME +%token <voidval> COMPLETE %type <sval> name %type <ssym> name_not_typename @@ -374,6 +375,22 @@ exp : exp '%' name write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } ; +exp : exp '%' name COMPLETE + { pstate->mark_struct_expression (); + write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); + write_exp_string (pstate, $3); + write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } + ; + +exp : exp '%' COMPLETE + { struct stoken s; + pstate->mark_struct_expression (); + write_exp_elt_opcode (pstate, STRUCTOP_PTR); + s.ptr = ""; + s.length = 0; + write_exp_string (pstate, s); + write_exp_elt_opcode (pstate, STRUCTOP_PTR); } + /* Binary operators in order of decreasing precedence. */ exp : exp '@' exp @@ -1100,6 +1117,15 @@ match_string_literal (void) } } +/* This is set if a NAME token appeared at the very end of the input + string, with no whitespace separating the name from the EOF. This + is used only when parsing to do field name completion. */ +static bool saw_name_at_eof; + +/* This is set if the previously-returned token was a structure + operator '%'. */ +static bool last_was_structop; + /* Read one token, getting characters through lexptr. */ static int @@ -1109,7 +1135,10 @@ yylex (void) int namelen; unsigned int token; const char *tokstart; - + bool saw_structop = last_was_structop; + + last_was_structop = false; + retry: pstate->prev_lexptr = pstate->lexptr; @@ -1156,6 +1185,13 @@ yylex (void) switch (c = *tokstart) { case 0: + if (saw_name_at_eof) + { + saw_name_at_eof = false; + return COMPLETE; + } + else if (pstate->parse_completion && saw_structop) + return COMPLETE; return 0; case ' ': @@ -1257,12 +1293,14 @@ yylex (void) pstate->lexptr = p; return toktype; } - + + case '%': + last_was_structop = true; + /* Fall through. */ case '+': case '-': case '*': case '/': - case '%': case '|': case '&': case '^': @@ -1374,7 +1412,10 @@ yylex (void) return NAME_OR_INT; } } - + + if (pstate->parse_completion && *pstate->lexptr == '\0') + saw_name_at_eof = true; + /* Any other kind of symbol */ yylval.ssym.sym = result; yylval.ssym.is_a_field_of_this = false; @@ -1391,6 +1432,8 @@ f_language::parser (struct parser_state *par_state) const parser_debug); gdb_assert (par_state != NULL); pstate = par_state; + last_was_structop = false; + saw_name_at_eof = false; paren_depth = 0; struct type_stack stack; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index b1ca924..b1a8f8f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-11-14 Andrew Burgess <andrew.burgess@embecosm.com> + + PR cli/26879 + * gdb.fortran/completion.exp: New file. + * gdb.fortran/completion.f90: New file. + 2020-11-12 Joseph Myers <joseph@codesourcery.com> * lib/gdb.exp (gdb_file_cmd): Check for case where $arg.exe exists diff --git a/gdb/testsuite/gdb.fortran/completion.exp b/gdb/testsuite/gdb.fortran/completion.exp new file mode 100644 index 0000000..1458799 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/completion.exp @@ -0,0 +1,46 @@ +# Copyright 2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> . + +# Test tab completion of Fortran type field names. + +if {[skip_fortran_tests]} { return -1 } + +standard_testfile ".f90" +load_lib fortran.exp +load_lib completion-support.exp + +if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \ + {debug f90}]} { + return -1 +} + +if ![fortran_runto_main] { + untested "could not run to main" + return -1 +} + +test_gdb_complete_none "p var%x" +test_gdb_complete_multiple "p var%" "" "" { + "aa_field_1" + "aa_field_2" + "bb_field_3" +} + +test_gdb_complete_multiple "p var%" "aa" "_field_" { + "aa_field_1" + "aa_field_2" +} + +test_gdb_complete_unique "p var%b" "p var%bb_field_3" diff --git a/gdb/testsuite/gdb.fortran/completion.f90 b/gdb/testsuite/gdb.fortran/completion.f90 new file mode 100644 index 0000000..605f783 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/completion.f90 @@ -0,0 +1,26 @@ +! Copyright 2020 Free Software Foundation, Inc. +! +! This program is free software; you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation; either version 3 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see <http://www.gnu.org/licenses/>. + +program test + type some_type + integer :: aa_field_1 + integer :: aa_field_2 + integer :: bb_field_3 + end type some_type + + type(some_type) :: var + + print *, var +end program test |