[PATCH] gdb: add tab completion of type field names for Fortran
Andrew Burgess
andrew.burgess@embecosm.com
Sat Nov 14 10:33:56 GMT 2020
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.
---
gdb/ChangeLog | 10 +++++
gdb/f-exp.y | 51 ++++++++++++++++++++++--
gdb/testsuite/ChangeLog | 6 +++
gdb/testsuite/gdb.fortran/completion.exp | 46 +++++++++++++++++++++
gdb/testsuite/gdb.fortran/completion.f90 | 26 ++++++++++++
5 files changed, 135 insertions(+), 4 deletions(-)
create mode 100644 gdb/testsuite/gdb.fortran/completion.exp
create mode 100644 gdb/testsuite/gdb.fortran/completion.f90
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 5e16678886b..edfbe0cd220 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/gdb.fortran/completion.exp b/gdb/testsuite/gdb.fortran/completion.exp
new file mode 100644
index 00000000000..1458799bf64
--- /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 00000000000..605f783e494
--- /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
--
2.25.4
More information about the Gdb-patches
mailing list