gdb
* value.h (evaluate_subexpression_type, extract_field_op): Declare. * printcmd.c (_initialize_printcmd): Use expression_completer for 'p', 'inspect', 'call'. * parser-defs.h (parse_field_expression): Declare. * parse.c: Include exceptions.h. (in_parse_field, expout_last_struct): New globals. (mark_struct_expression): New function. (prefixify_expression): Return int. (prefixify_subexp): Return int. Use expout_last_struct. (parse_exp_1): Update. (parse_exp_in_context): Add 'out_subexp' argument. Handle in_parse_field. (parse_field_expression): New function. * expression.h (parse_field_expression): Declare. (in_parse_field): Likewise. * eval.c (evaluate_subexpression_type): New function. (extract_field_op): Likewise. * completer.h (expression_completer): Declare. * completer.c (expression_completer): New function. (count_struct_fields, add_struct_fields): New functions. * c-exp.y (yyparse): Redefine. (COMPLETE): New token. (exp): New productions. (saw_name_at_eof, last_was_structop): New globals. (yylex): Return COMPLETE when needed. Recognize in_parse_field. (c_parse): New function. * breakpoint.c (_initialize_breakpoint): Use expression_completer for watch, awatch, and rwatch. * Makefile.in (parse.o): Depend on exceptions_h. gdb/testsuite * gdb.base/break1.c (struct some_struct): New struct. (values): New global. * gdb.base/completion.exp: Add field name completion test. gdb/doc * gdb.texinfo (Completion): Add field name example.
This commit is contained in:
parent
90aa6a4044
commit
65d12d83a5
@ -1,3 +1,36 @@
|
||||
2008-06-06 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* value.h (evaluate_subexpression_type, extract_field_op):
|
||||
Declare.
|
||||
* printcmd.c (_initialize_printcmd): Use expression_completer for
|
||||
'p', 'inspect', 'call'.
|
||||
* parser-defs.h (parse_field_expression): Declare.
|
||||
* parse.c: Include exceptions.h.
|
||||
(in_parse_field, expout_last_struct): New globals.
|
||||
(mark_struct_expression): New function.
|
||||
(prefixify_expression): Return int.
|
||||
(prefixify_subexp): Return int. Use expout_last_struct.
|
||||
(parse_exp_1): Update.
|
||||
(parse_exp_in_context): Add 'out_subexp' argument. Handle
|
||||
in_parse_field.
|
||||
(parse_field_expression): New function.
|
||||
* expression.h (parse_field_expression): Declare.
|
||||
(in_parse_field): Likewise.
|
||||
* eval.c (evaluate_subexpression_type): New function.
|
||||
(extract_field_op): Likewise.
|
||||
* completer.h (expression_completer): Declare.
|
||||
* completer.c (expression_completer): New function.
|
||||
(count_struct_fields, add_struct_fields): New functions.
|
||||
* c-exp.y (yyparse): Redefine.
|
||||
(COMPLETE): New token.
|
||||
(exp): New productions.
|
||||
(saw_name_at_eof, last_was_structop): New globals.
|
||||
(yylex): Return COMPLETE when needed. Recognize in_parse_field.
|
||||
(c_parse): New function.
|
||||
* breakpoint.c (_initialize_breakpoint): Use expression_completer
|
||||
for watch, awatch, and rwatch.
|
||||
* Makefile.in (parse.o): Depend on exceptions_h.
|
||||
|
||||
2008-06-06 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
PR gdb/1147
|
||||
|
@ -2591,7 +2591,8 @@ osabi.o: osabi.c $(defs_h) $(gdb_assert_h) $(gdb_string_h) $(osabi_h) \
|
||||
parse.o: parse.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||||
$(frame_h) $(expression_h) $(value_h) $(command_h) $(language_h) \
|
||||
$(f_lang_h) $(parser_defs_h) $(gdbcmd_h) $(symfile_h) $(inferior_h) \
|
||||
$(doublest_h) $(gdb_assert_h) $(block_h) $(source_h) $(objfiles_h)
|
||||
$(doublest_h) $(gdb_assert_h) $(block_h) $(source_h) $(objfiles_h) \
|
||||
$(exceptions_h)
|
||||
p-exp.o: p-exp.c $(defs_h) $(gdb_string_h) $(expression_h) $(value_h) \
|
||||
$(parser_defs_h) $(language_h) $(p_lang_h) $(bfd_h) $(symfile_h) \
|
||||
$(objfiles_h) $(block_h)
|
||||
|
11
gdb/NEWS
11
gdb/NEWS
@ -3,6 +3,17 @@
|
||||
|
||||
*** Changes since GDB 6.8
|
||||
|
||||
* When completing in expressions, gdb will attempt to limit
|
||||
completions to allowable structure or union fields, where appropriate.
|
||||
For instance, consider:
|
||||
|
||||
# struct example { int f1; double f2; };
|
||||
# struct example variable;
|
||||
(gdb) p variable.
|
||||
|
||||
If the user types TAB at the end of this command line, the available
|
||||
completions will be "f1" and "f2".
|
||||
|
||||
* New remote packets
|
||||
|
||||
qSearch:memory:
|
||||
|
@ -8455,19 +8455,19 @@ by using \"enable delete\" on the catchpoint number."));
|
||||
Set a watchpoint for an expression.\n\
|
||||
A watchpoint stops execution of your program whenever the value of\n\
|
||||
an expression changes."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
set_cmd_completer (c, expression_completer);
|
||||
|
||||
c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
|
||||
Set a read watchpoint for an expression.\n\
|
||||
A watchpoint stops execution of your program whenever the value of\n\
|
||||
an expression is read."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
set_cmd_completer (c, expression_completer);
|
||||
|
||||
c = add_com ("awatch", class_breakpoint, awatch_command, _("\
|
||||
Set a watchpoint for an expression.\n\
|
||||
A watchpoint stops execution of your program whenever the value of\n\
|
||||
an expression is either read or written."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
set_cmd_completer (c, expression_completer);
|
||||
|
||||
add_info ("watchpoints", breakpoints_info,
|
||||
_("Synonym for ``info breakpoints''."));
|
||||
|
75
gdb/c-exp.y
75
gdb/c-exp.y
@ -63,7 +63,7 @@ Boston, MA 02110-1301, USA. */
|
||||
generators need to be fixed instead of adding those names to this list. */
|
||||
|
||||
#define yymaxdepth c_maxdepth
|
||||
#define yyparse c_parse
|
||||
#define yyparse c_parse_internal
|
||||
#define yylex c_lex
|
||||
#define yyerror c_error
|
||||
#define yylval c_lval
|
||||
@ -180,6 +180,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
|
||||
|
||||
%token <sval> STRING
|
||||
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
|
||||
%token <voidval> COMPLETE
|
||||
%token <tsym> TYPENAME
|
||||
%type <sval> name
|
||||
%type <ssym> name_not_typename
|
||||
@ -301,6 +302,23 @@ exp : exp ARROW name
|
||||
write_exp_elt_opcode (STRUCTOP_PTR); }
|
||||
;
|
||||
|
||||
exp : exp ARROW name COMPLETE
|
||||
{ mark_struct_expression ();
|
||||
write_exp_elt_opcode (STRUCTOP_PTR);
|
||||
write_exp_string ($3);
|
||||
write_exp_elt_opcode (STRUCTOP_PTR); }
|
||||
;
|
||||
|
||||
exp : exp ARROW COMPLETE
|
||||
{ struct stoken s;
|
||||
mark_struct_expression ();
|
||||
write_exp_elt_opcode (STRUCTOP_PTR);
|
||||
s.ptr = "";
|
||||
s.length = 0;
|
||||
write_exp_string (s);
|
||||
write_exp_elt_opcode (STRUCTOP_PTR); }
|
||||
;
|
||||
|
||||
exp : exp ARROW qualified_name
|
||||
{ /* exp->type::name becomes exp->*(&type::name) */
|
||||
/* Note: this doesn't work if name is a
|
||||
@ -319,6 +337,23 @@ exp : exp '.' name
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT); }
|
||||
;
|
||||
|
||||
exp : exp '.' name COMPLETE
|
||||
{ mark_struct_expression ();
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
write_exp_string ($3);
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT); }
|
||||
;
|
||||
|
||||
exp : exp '.' COMPLETE
|
||||
{ struct stoken s;
|
||||
mark_struct_expression ();
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
s.ptr = "";
|
||||
s.length = 0;
|
||||
write_exp_string (s);
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT); }
|
||||
;
|
||||
|
||||
exp : exp '.' qualified_name
|
||||
{ /* exp.type::name becomes exp.*(&type::name) */
|
||||
/* Note: this doesn't work if name is a
|
||||
@ -1338,6 +1373,16 @@ static const struct token tokentab2[] =
|
||||
{">=", GEQ, BINOP_END}
|
||||
};
|
||||
|
||||
/* 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 int saw_name_at_eof;
|
||||
|
||||
/* This is set if the previously-returned token was a structure
|
||||
operator -- either '.' or ARROW. This is used only when parsing to
|
||||
do field name completion. */
|
||||
static int last_was_structop;
|
||||
|
||||
/* Read one token, getting characters through lexptr. */
|
||||
|
||||
static int
|
||||
@ -1353,6 +1398,9 @@ yylex ()
|
||||
static int tempbufsize;
|
||||
char * token_string = NULL;
|
||||
int class_prefix = 0;
|
||||
int saw_structop = last_was_structop;
|
||||
|
||||
last_was_structop = 0;
|
||||
|
||||
retry:
|
||||
|
||||
@ -1385,6 +1433,8 @@ yylex ()
|
||||
{
|
||||
lexptr += 2;
|
||||
yylval.opcode = tokentab2[i].opcode;
|
||||
if (in_parse_field && tokentab2[i].opcode == ARROW)
|
||||
last_was_structop = 1;
|
||||
return tokentab2[i].token;
|
||||
}
|
||||
|
||||
@ -1393,6 +1443,8 @@ yylex ()
|
||||
case 0:
|
||||
/* If we were just scanning the result of a macro expansion,
|
||||
then we need to resume scanning the original text.
|
||||
If we're parsing for field name completion, and the previous
|
||||
token allows such completion, return a COMPLETE token.
|
||||
Otherwise, we were already scanning the original text, and
|
||||
we're really done. */
|
||||
if (scanning_macro_expansion ())
|
||||
@ -1400,6 +1452,13 @@ yylex ()
|
||||
finished_macro_expansion ();
|
||||
goto retry;
|
||||
}
|
||||
else if (saw_name_at_eof)
|
||||
{
|
||||
saw_name_at_eof = 0;
|
||||
return COMPLETE;
|
||||
}
|
||||
else if (saw_structop)
|
||||
return COMPLETE;
|
||||
else
|
||||
return 0;
|
||||
|
||||
@ -1472,7 +1531,11 @@ yylex ()
|
||||
case '.':
|
||||
/* Might be a floating point number. */
|
||||
if (lexptr[1] < '0' || lexptr[1] > '9')
|
||||
{
|
||||
if (in_parse_field)
|
||||
last_was_structop = 1;
|
||||
goto symbol; /* Nope, must be a symbol. */
|
||||
}
|
||||
/* FALL THRU into number case. */
|
||||
|
||||
case '0':
|
||||
@ -1808,10 +1871,20 @@ yylex ()
|
||||
/* Any other kind of symbol */
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
if (in_parse_field && *lexptr == '\0')
|
||||
saw_name_at_eof = 1;
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
c_parse (void)
|
||||
{
|
||||
last_was_structop = 0;
|
||||
saw_name_at_eof = 0;
|
||||
return yyparse ();
|
||||
}
|
||||
|
||||
void
|
||||
yyerror (msg)
|
||||
char *msg;
|
||||
|
@ -338,6 +338,90 @@ location_completer (char *text, char *word)
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Helper for expression_completer which recursively counts the number
|
||||
of named fields in a structure or union type. */
|
||||
static int
|
||||
count_struct_fields (struct type *type)
|
||||
{
|
||||
int i, result = 0;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||
{
|
||||
if (i < TYPE_N_BASECLASSES (type))
|
||||
result += count_struct_fields (TYPE_BASECLASS (type, i));
|
||||
else if (TYPE_FIELD_NAME (type, i))
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Helper for expression_completer which recursively adds field names
|
||||
from TYPE, a struct or union type, to the array OUTPUT. This
|
||||
function assumes that OUTPUT is correctly-sized. */
|
||||
static void
|
||||
add_struct_fields (struct type *type, int *nextp, char **output,
|
||||
char *fieldname, int namelen)
|
||||
{
|
||||
int i;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||
{
|
||||
if (i < TYPE_N_BASECLASSES (type))
|
||||
add_struct_fields (TYPE_BASECLASS (type, i), nextp, output,
|
||||
fieldname, namelen);
|
||||
else if (TYPE_FIELD_NAME (type, i)
|
||||
&& ! strncmp (TYPE_FIELD_NAME (type, i), fieldname, namelen))
|
||||
{
|
||||
output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i));
|
||||
++*nextp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Complete on expressions. Often this means completing on symbol
|
||||
names, but some language parsers also have support for completing
|
||||
field names. */
|
||||
char **
|
||||
expression_completer (char *text, char *word)
|
||||
{
|
||||
struct type *type;
|
||||
char *fieldname;
|
||||
|
||||
/* Perform a tentative parse of the expression, to see whether a
|
||||
field completion is required. */
|
||||
fieldname = NULL;
|
||||
type = parse_field_expression (text, &fieldname);
|
||||
if (fieldname && type)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
CHECK_TYPEDEF (type);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_PTR
|
||||
&& TYPE_CODE (type) != TYPE_CODE_REF)
|
||||
break;
|
||||
type = TYPE_TARGET_TYPE (type);
|
||||
}
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_UNION
|
||||
|| TYPE_CODE (type) == TYPE_CODE_STRUCT)
|
||||
{
|
||||
int alloc = count_struct_fields (type);
|
||||
int flen = strlen (fieldname);
|
||||
int out = 0;
|
||||
char **result = (char **) xmalloc ((alloc + 1) * sizeof (char *));
|
||||
|
||||
add_struct_fields (type, &out, result, fieldname, flen);
|
||||
result[out] = NULL;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not ideal but it is what we used to do before... */
|
||||
return location_completer (text, word);
|
||||
}
|
||||
|
||||
/* Complete on command names. Used by "help". */
|
||||
char **
|
||||
command_completer (char *text, char *word)
|
||||
@ -520,7 +604,8 @@ complete_line (const char *text, char *line_buffer, int point)
|
||||
rl_completer_word_break_characters =
|
||||
gdb_completer_file_name_break_characters;
|
||||
}
|
||||
else if (c->completer == location_completer)
|
||||
else if (c->completer == location_completer
|
||||
|| c->completer == expression_completer)
|
||||
{
|
||||
/* Commands which complete on locations want to
|
||||
see the entire argument. */
|
||||
@ -588,7 +673,8 @@ complete_line (const char *text, char *line_buffer, int point)
|
||||
rl_completer_word_break_characters =
|
||||
gdb_completer_file_name_break_characters;
|
||||
}
|
||||
else if (c->completer == location_completer)
|
||||
else if (c->completer == location_completer
|
||||
|| c->completer == expression_completer)
|
||||
{
|
||||
for (p = word;
|
||||
p > tmp_command
|
||||
|
@ -25,6 +25,8 @@ extern char **noop_completer (char *, char *);
|
||||
|
||||
extern char **filename_completer (char *, char *);
|
||||
|
||||
extern char **expression_completer (char *, char *);
|
||||
|
||||
extern char **location_completer (char *, char *);
|
||||
|
||||
extern char **command_completer (char *, char *);
|
||||
|
@ -1,3 +1,7 @@
|
||||
2008-06-06 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.texinfo (Completion): Add field name example.
|
||||
|
||||
2008-06-06 Marc Khouzam <marc.khouzam@ericsson.com>
|
||||
|
||||
* gdb.texinfo (GDB/MI Program Context): Added example
|
||||
|
@ -1,6 +1,6 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
|
||||
@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
|
||||
@c Free Software Foundation, Inc.
|
||||
@c
|
||||
@c %**start of header
|
||||
@ -1531,6 +1531,44 @@ Expressions, ,C@t{++} Expressions}. You can use the command @code{set
|
||||
overload-resolution off} to disable overload resolution;
|
||||
see @ref{Debugging C Plus Plus, ,@value{GDBN} Features for C@t{++}}.
|
||||
|
||||
@cindex completion of structure field names
|
||||
@cindex structure field name completion
|
||||
@cindex completion of union field names
|
||||
@cindex union field name completion
|
||||
When completing in an expression which looks up a field in a
|
||||
structure, @value{GDBN} also tries@footnote{The completer can be
|
||||
confused by certain kinds of invalid expressions. Also, it only
|
||||
examines the static type of the expression, not the dynamic type.} to
|
||||
limit completions to the field names available in the type of the
|
||||
left-hand-side:
|
||||
|
||||
@smallexample
|
||||
(@value{GDBP}) p gdb_stdout.@kbd{M-?}
|
||||
magic to_delete to_fputs to_put to_rewind
|
||||
to_data to_flush to_isatty to_read to_write
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
This is because the @code{gdb_stdout} is a variable of the type
|
||||
@code{struct ui_file} that is defined in @value{GDBN} sources as
|
||||
follows:
|
||||
|
||||
@smallexample
|
||||
struct ui_file
|
||||
@{
|
||||
int *magic;
|
||||
ui_file_flush_ftype *to_flush;
|
||||
ui_file_write_ftype *to_write;
|
||||
ui_file_fputs_ftype *to_fputs;
|
||||
ui_file_read_ftype *to_read;
|
||||
ui_file_delete_ftype *to_delete;
|
||||
ui_file_isatty_ftype *to_isatty;
|
||||
ui_file_rewind_ftype *to_rewind;
|
||||
ui_file_put_ftype *to_put;
|
||||
void *to_data;
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
|
||||
@node Help
|
||||
@section Getting Help
|
||||
|
30
gdb/eval.c
30
gdb/eval.c
@ -175,6 +175,36 @@ evaluate_type (struct expression *exp)
|
||||
return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
|
||||
}
|
||||
|
||||
/* Evaluate a subexpression, avoiding all memory references and
|
||||
getting a value whose type alone is correct. */
|
||||
|
||||
struct value *
|
||||
evaluate_subexpression_type (struct expression *exp, int subexp)
|
||||
{
|
||||
return evaluate_subexp (NULL_TYPE, exp, &subexp, EVAL_AVOID_SIDE_EFFECTS);
|
||||
}
|
||||
|
||||
/* Extract a field operation from an expression. If the subexpression
|
||||
of EXP starting at *SUBEXP is not a structure dereference
|
||||
operation, return NULL. Otherwise, return the name of the
|
||||
dereferenced field, and advance *SUBEXP to point to the
|
||||
subexpression of the left-hand-side of the dereference. This is
|
||||
used when completing field names. */
|
||||
|
||||
char *
|
||||
extract_field_op (struct expression *exp, int *subexp)
|
||||
{
|
||||
int tem;
|
||||
char *result;
|
||||
if (exp->elts[*subexp].opcode != STRUCTOP_STRUCT
|
||||
&& exp->elts[*subexp].opcode != STRUCTOP_PTR)
|
||||
return NULL;
|
||||
tem = longest_to_int (exp->elts[*subexp + 1].longconst);
|
||||
result = &exp->elts[*subexp + 2].string;
|
||||
(*subexp) += 1 + 3 + BYTES_TO_EXP_ELEM (tem + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* If the next expression is an OP_LABELED, skips past it,
|
||||
returning the label. Otherwise, does nothing and returns NULL. */
|
||||
|
||||
|
@ -389,8 +389,14 @@ struct expression
|
||||
|
||||
extern struct expression *parse_expression (char *);
|
||||
|
||||
extern struct type *parse_field_expression (char *, char **);
|
||||
|
||||
extern struct expression *parse_exp_1 (char **, struct block *, int);
|
||||
|
||||
/* For use by parsers; set if we want to parse an expression and
|
||||
attempt to complete a field name. */
|
||||
extern int in_parse_field;
|
||||
|
||||
/* The innermost context required by the stack and register variables
|
||||
we've encountered so far. To use this, set it to NULL, then call
|
||||
parse_<whatever>, then look at it. */
|
||||
|
127
gdb/parse.c
127
gdb/parse.c
@ -52,6 +52,7 @@
|
||||
#include "block.h"
|
||||
#include "source.h"
|
||||
#include "objfiles.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
/* Standard set of definitions for printing, dumping, prefixifying,
|
||||
* and evaluating expressions. */
|
||||
@ -80,6 +81,15 @@ char *prev_lexptr;
|
||||
int paren_depth;
|
||||
int comma_terminates;
|
||||
|
||||
/* True if parsing an expression to find a field reference. This is
|
||||
only used by completion. */
|
||||
int in_parse_field;
|
||||
|
||||
/* The index of the last struct expression directly before a '.' or
|
||||
'->'. This is set when parsing and is only used when completing a
|
||||
field name. It is -1 if no dereference operation was found. */
|
||||
static int expout_last_struct = -1;
|
||||
|
||||
/* A temporary buffer for identifiers, so we can null-terminate them.
|
||||
|
||||
We allocate this with xrealloc. parse_exp_1 used to allocate with
|
||||
@ -100,13 +110,13 @@ show_expressiondebug (struct ui_file *file, int from_tty,
|
||||
|
||||
static void free_funcalls (void *ignore);
|
||||
|
||||
static void prefixify_expression (struct expression *);
|
||||
static int prefixify_expression (struct expression *);
|
||||
|
||||
static void prefixify_subexp (struct expression *, struct expression *, int,
|
||||
static int prefixify_subexp (struct expression *, struct expression *, int,
|
||||
int);
|
||||
|
||||
static struct expression *parse_exp_in_context (char **, struct block *, int,
|
||||
int);
|
||||
int, int *);
|
||||
|
||||
void _initialize_parse (void);
|
||||
|
||||
@ -460,6 +470,16 @@ write_exp_msymbol (struct minimal_symbol *msymbol,
|
||||
}
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
}
|
||||
|
||||
/* Mark the current index as the starting location of a structure
|
||||
expression. This is used when completing on field names. */
|
||||
|
||||
void
|
||||
mark_struct_expression (void)
|
||||
{
|
||||
expout_last_struct = expout_ptr;
|
||||
}
|
||||
|
||||
|
||||
/* Recognize tokens that start with '$'. These include:
|
||||
|
||||
@ -664,9 +684,13 @@ copy_name (struct stoken token)
|
||||
}
|
||||
|
||||
/* Reverse an expression from suffix form (in which it is constructed)
|
||||
to prefix form (in which we can conveniently print or execute it). */
|
||||
to prefix form (in which we can conveniently print or execute it).
|
||||
Ordinarily this always returns -1. However, if EXPOUT_LAST_STRUCT
|
||||
is not -1 (i.e., we are trying to complete a field name), it will
|
||||
return the index of the subexpression which is the left-hand-side
|
||||
of the struct operation at EXPOUT_LAST_STRUCT. */
|
||||
|
||||
static void
|
||||
static int
|
||||
prefixify_expression (struct expression *expr)
|
||||
{
|
||||
int len = sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
|
||||
@ -678,7 +702,7 @@ prefixify_expression (struct expression *expr)
|
||||
/* Copy the original expression into temp. */
|
||||
memcpy (temp, expr, len);
|
||||
|
||||
prefixify_subexp (temp, expr, inpos, outpos);
|
||||
return prefixify_subexp (temp, expr, inpos, outpos);
|
||||
}
|
||||
|
||||
/* Return the number of exp_elements in the postfix subexpression
|
||||
@ -875,9 +899,12 @@ operator_length_standard (struct expression *expr, int endpos,
|
||||
|
||||
/* Copy the subexpression ending just before index INEND in INEXPR
|
||||
into OUTEXPR, starting at index OUTBEG.
|
||||
In the process, convert it from suffix to prefix form. */
|
||||
In the process, convert it from suffix to prefix form.
|
||||
If EXPOUT_LAST_STRUCT is -1, then this function always returns -1.
|
||||
Otherwise, it returns the index of the subexpression which is the
|
||||
left-hand-side of the expression at EXPOUT_LAST_STRUCT. */
|
||||
|
||||
static void
|
||||
static int
|
||||
prefixify_subexp (struct expression *inexpr,
|
||||
struct expression *outexpr, int inend, int outbeg)
|
||||
{
|
||||
@ -886,6 +913,7 @@ prefixify_subexp (struct expression *inexpr,
|
||||
int i;
|
||||
int *arglens;
|
||||
enum exp_opcode opcode;
|
||||
int result = -1;
|
||||
|
||||
operator_length (inexpr, inend, &oplen, &args);
|
||||
|
||||
@ -896,6 +924,9 @@ prefixify_subexp (struct expression *inexpr,
|
||||
EXP_ELEM_TO_BYTES (oplen));
|
||||
outbeg += oplen;
|
||||
|
||||
if (expout_last_struct == inend)
|
||||
result = outbeg - oplen;
|
||||
|
||||
/* Find the lengths of the arg subexpressions. */
|
||||
arglens = (int *) alloca (args * sizeof (int));
|
||||
for (i = args - 1; i >= 0; i--)
|
||||
@ -913,11 +944,21 @@ prefixify_subexp (struct expression *inexpr,
|
||||
outbeg does similarly in the output. */
|
||||
for (i = 0; i < args; i++)
|
||||
{
|
||||
int r;
|
||||
oplen = arglens[i];
|
||||
inend += oplen;
|
||||
prefixify_subexp (inexpr, outexpr, inend, outbeg);
|
||||
r = prefixify_subexp (inexpr, outexpr, inend, outbeg);
|
||||
if (r != -1)
|
||||
{
|
||||
/* Return immediately. We probably have only parsed a
|
||||
partial expression, so we don't want to try to reverse
|
||||
the other operands. */
|
||||
return r;
|
||||
}
|
||||
outbeg += oplen;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This page contains the two entry points to this file. */
|
||||
@ -935,23 +976,30 @@ prefixify_subexp (struct expression *inexpr,
|
||||
struct expression *
|
||||
parse_exp_1 (char **stringptr, struct block *block, int comma)
|
||||
{
|
||||
return parse_exp_in_context (stringptr, block, comma, 0);
|
||||
return parse_exp_in_context (stringptr, block, comma, 0, NULL);
|
||||
}
|
||||
|
||||
/* As for parse_exp_1, except that if VOID_CONTEXT_P, then
|
||||
no value is expected from the expression. */
|
||||
no value is expected from the expression.
|
||||
OUT_SUBEXP is set when attempting to complete a field name; in this
|
||||
case it is set to the index of the subexpression on the
|
||||
left-hand-side of the struct op. If not doing such completion, it
|
||||
is left untouched. */
|
||||
|
||||
static struct expression *
|
||||
parse_exp_in_context (char **stringptr, struct block *block, int comma,
|
||||
int void_context_p)
|
||||
int void_context_p, int *out_subexp)
|
||||
{
|
||||
volatile struct gdb_exception except;
|
||||
struct cleanup *old_chain;
|
||||
int subexp;
|
||||
|
||||
lexptr = *stringptr;
|
||||
prev_lexptr = NULL;
|
||||
|
||||
paren_depth = 0;
|
||||
type_stack_depth = 0;
|
||||
expout_last_struct = -1;
|
||||
|
||||
comma_terminates = comma;
|
||||
|
||||
@ -986,10 +1034,20 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma,
|
||||
expout = (struct expression *)
|
||||
xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
|
||||
expout->language_defn = current_language;
|
||||
make_cleanup (free_current_contents, &expout);
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ALL)
|
||||
{
|
||||
if (current_language->la_parser ())
|
||||
current_language->la_error (NULL);
|
||||
}
|
||||
if (except.reason < 0)
|
||||
{
|
||||
if (! in_parse_field)
|
||||
{
|
||||
xfree (expout);
|
||||
throw_exception (except);
|
||||
}
|
||||
}
|
||||
|
||||
discard_cleanups (old_chain);
|
||||
|
||||
@ -1009,7 +1067,9 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma,
|
||||
dump_raw_expression (expout, gdb_stdlog,
|
||||
"before conversion to prefix form");
|
||||
|
||||
prefixify_expression (expout);
|
||||
subexp = prefixify_expression (expout);
|
||||
if (out_subexp)
|
||||
*out_subexp = subexp;
|
||||
|
||||
current_language->la_post_parser (&expout, void_context_p);
|
||||
|
||||
@ -1033,6 +1093,45 @@ parse_expression (char *string)
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Parse STRING as an expression. If parsing ends in the middle of a
|
||||
field reference, return the type of the left-hand-side of the
|
||||
reference; furthermore, if the parsing ends in the field name,
|
||||
return the field name in *NAME. In all other cases, return NULL. */
|
||||
|
||||
struct type *
|
||||
parse_field_expression (char *string, char **name)
|
||||
{
|
||||
struct expression *exp = NULL;
|
||||
struct value *val;
|
||||
int subexp;
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ALL)
|
||||
{
|
||||
in_parse_field = 1;
|
||||
exp = parse_exp_in_context (&string, 0, 0, 0, &subexp);
|
||||
}
|
||||
in_parse_field = 0;
|
||||
if (except.reason < 0 || ! exp)
|
||||
return NULL;
|
||||
if (expout_last_struct == -1)
|
||||
{
|
||||
xfree (exp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*name = extract_field_op (exp, &subexp);
|
||||
if (!*name)
|
||||
{
|
||||
xfree (exp);
|
||||
return NULL;
|
||||
}
|
||||
val = evaluate_subexpression_type (exp, subexp);
|
||||
xfree (exp);
|
||||
|
||||
return value_type (val);
|
||||
}
|
||||
|
||||
/* A post-parser that does nothing */
|
||||
|
||||
void
|
||||
|
@ -138,6 +138,8 @@ extern void write_exp_msymbol (struct minimal_symbol *,
|
||||
|
||||
extern void write_dollar_variable (struct stoken str);
|
||||
|
||||
extern void mark_struct_expression (void);
|
||||
|
||||
extern char *find_template_name_end (char *);
|
||||
|
||||
extern void start_arglist (void);
|
||||
|
@ -2366,7 +2366,7 @@ Call a function in the program.\n\
|
||||
The argument is the function name and arguments, in the notation of the\n\
|
||||
current working language. The result is printed and saved in the value\n\
|
||||
history, if it is not void."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
set_cmd_completer (c, expression_completer);
|
||||
|
||||
add_cmd ("variable", class_vars, set_command, _("\
|
||||
Evaluate expression EXP and assign result to variable VAR, using assignment\n\
|
||||
@ -2399,13 +2399,13 @@ resides in memory.\n\
|
||||
\n\
|
||||
EXP may be preceded with /FMT, where FMT is a format letter\n\
|
||||
but no count or size letter (see \"x\" command)."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
set_cmd_completer (c, expression_completer);
|
||||
add_com_alias ("p", "print", class_vars, 1);
|
||||
|
||||
c = add_com ("inspect", class_vars, inspect_command, _("\
|
||||
Same as \"print\" command, except that if you are running in the epoch\n\
|
||||
environment, the value is printed in its own window."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
set_cmd_completer (c, expression_completer);
|
||||
|
||||
add_setshow_uinteger_cmd ("max-symbolic-offset", no_class,
|
||||
&max_symbolic_offset, _("\
|
||||
|
@ -1,3 +1,9 @@
|
||||
2008-06-06 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.base/break1.c (struct some_struct): New struct.
|
||||
(values): New global.
|
||||
* gdb.base/completion.exp: Add field name completion test.
|
||||
|
||||
2008-06-06 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
* gdb.cp/call-c.exp: Test for incorrect handling of reference
|
||||
|
@ -41,3 +41,12 @@ int marker2 (a) int a; { return (1); } /* set breakpoint 9 here */
|
||||
void marker3 (a, b) char *a, *b; {} /* set breakpoint 18 here */
|
||||
void marker4 (d) long d; {} /* set breakpoint 13 here */
|
||||
#endif
|
||||
|
||||
/* A structure we use for field name completion tests. */
|
||||
struct some_struct
|
||||
{
|
||||
int a_field;
|
||||
int b_field;
|
||||
};
|
||||
|
||||
struct some_struct values[50];
|
||||
|
@ -637,6 +637,22 @@ gdb_expect {
|
||||
timeout { fail "(timeout) complete (2) 'p no_var_named_this-'" }
|
||||
}
|
||||
|
||||
send_gdb "p values\[0\].a\t"
|
||||
sleep 3
|
||||
gdb_expect {
|
||||
-re "^p values.0..a_field $"\
|
||||
{ send_gdb "\n"
|
||||
sleep 1
|
||||
gdb_expect {
|
||||
-re "^.* = 0.*$gdb_prompt $"\
|
||||
{ pass "complete 'p values\[0\].a'"}
|
||||
-re ".*$gdb_prompt $" { fail "complete 'p values\[0\].a'"}
|
||||
timeout {fail "(timeout) complete 'p values\[0\].a'"}
|
||||
}
|
||||
}
|
||||
-re ".*$gdb_prompt $" { fail "complete 'p values\[0\].a'" }
|
||||
timeout { fail "(timeout) complete 'p values\[0\].a' 2" }
|
||||
}
|
||||
|
||||
# The following tests used to simply try to complete `${objdir}/file',
|
||||
# and so on. The problem is that ${objdir} can be very long; the
|
||||
|
@ -420,6 +420,11 @@ extern struct value *evaluate_expression (struct expression *exp);
|
||||
|
||||
extern struct value *evaluate_type (struct expression *exp);
|
||||
|
||||
extern struct value *evaluate_subexpression_type (struct expression *exp,
|
||||
int subexp);
|
||||
|
||||
extern char *extract_field_op (struct expression *exp, int *subexp);
|
||||
|
||||
extern struct value *evaluate_subexp_with_coercion (struct expression *,
|
||||
int *, enum noside);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user