aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2020-11-13 18:27:42 +0000
committerAndrew Burgess <andrew.burgess@embecosm.com>2020-11-14 21:19:27 +0000
commit9dd02fc063284f59994c095ce525e1b8934b0dc1 (patch)
tree54b999286c860db72841595efeeb35f80dd85724 /gdb
parent758cb81029440efad398f1aba4789a18e59daee2 (diff)
downloadfsf-binutils-gdb-9dd02fc063284f59994c095ce525e1b8934b0dc1.zip
fsf-binutils-gdb-9dd02fc063284f59994c095ce525e1b8934b0dc1.tar.gz
fsf-binutils-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/ChangeLog10
-rw-r--r--gdb/f-exp.y51
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.fortran/completion.exp46
-rw-r--r--gdb/testsuite/gdb.fortran/completion.f9026
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