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>
|
2008-06-06 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||||
|
|
||||||
PR gdb/1147
|
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) \
|
parse.o: parse.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(frame_h) $(expression_h) $(value_h) $(command_h) $(language_h) \
|
$(frame_h) $(expression_h) $(value_h) $(command_h) $(language_h) \
|
||||||
$(f_lang_h) $(parser_defs_h) $(gdbcmd_h) $(symfile_h) $(inferior_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) \
|
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) \
|
$(parser_defs_h) $(language_h) $(p_lang_h) $(bfd_h) $(symfile_h) \
|
||||||
$(objfiles_h) $(block_h)
|
$(objfiles_h) $(block_h)
|
||||||
|
11
gdb/NEWS
11
gdb/NEWS
@ -3,6 +3,17 @@
|
|||||||
|
|
||||||
*** Changes since GDB 6.8
|
*** 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
|
* New remote packets
|
||||||
|
|
||||||
qSearch:memory:
|
qSearch:memory:
|
||||||
|
@ -8455,19 +8455,19 @@ by using \"enable delete\" on the catchpoint number."));
|
|||||||
Set a watchpoint for an expression.\n\
|
Set a watchpoint for an expression.\n\
|
||||||
A watchpoint stops execution of your program whenever the value of\n\
|
A watchpoint stops execution of your program whenever the value of\n\
|
||||||
an expression changes."));
|
an expression changes."));
|
||||||
set_cmd_completer (c, location_completer);
|
set_cmd_completer (c, expression_completer);
|
||||||
|
|
||||||
c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
|
c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
|
||||||
Set a read watchpoint for an expression.\n\
|
Set a read watchpoint for an expression.\n\
|
||||||
A watchpoint stops execution of your program whenever the value of\n\
|
A watchpoint stops execution of your program whenever the value of\n\
|
||||||
an expression is read."));
|
an expression is read."));
|
||||||
set_cmd_completer (c, location_completer);
|
set_cmd_completer (c, expression_completer);
|
||||||
|
|
||||||
c = add_com ("awatch", class_breakpoint, awatch_command, _("\
|
c = add_com ("awatch", class_breakpoint, awatch_command, _("\
|
||||||
Set a watchpoint for an expression.\n\
|
Set a watchpoint for an expression.\n\
|
||||||
A watchpoint stops execution of your program whenever the value of\n\
|
A watchpoint stops execution of your program whenever the value of\n\
|
||||||
an expression is either read or written."));
|
an expression is either read or written."));
|
||||||
set_cmd_completer (c, location_completer);
|
set_cmd_completer (c, expression_completer);
|
||||||
|
|
||||||
add_info ("watchpoints", breakpoints_info,
|
add_info ("watchpoints", breakpoints_info,
|
||||||
_("Synonym for ``info breakpoints''."));
|
_("Synonym for ``info breakpoints''."));
|
||||||
|
79
gdb/c-exp.y
79
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. */
|
generators need to be fixed instead of adding those names to this list. */
|
||||||
|
|
||||||
#define yymaxdepth c_maxdepth
|
#define yymaxdepth c_maxdepth
|
||||||
#define yyparse c_parse
|
#define yyparse c_parse_internal
|
||||||
#define yylex c_lex
|
#define yylex c_lex
|
||||||
#define yyerror c_error
|
#define yyerror c_error
|
||||||
#define yylval c_lval
|
#define yylval c_lval
|
||||||
@ -180,6 +180,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
|
|||||||
|
|
||||||
%token <sval> STRING
|
%token <sval> STRING
|
||||||
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
|
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
|
||||||
|
%token <voidval> COMPLETE
|
||||||
%token <tsym> TYPENAME
|
%token <tsym> TYPENAME
|
||||||
%type <sval> name
|
%type <sval> name
|
||||||
%type <ssym> name_not_typename
|
%type <ssym> name_not_typename
|
||||||
@ -301,6 +302,23 @@ exp : exp ARROW name
|
|||||||
write_exp_elt_opcode (STRUCTOP_PTR); }
|
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 : exp ARROW qualified_name
|
||||||
{ /* exp->type::name becomes exp->*(&type::name) */
|
{ /* exp->type::name becomes exp->*(&type::name) */
|
||||||
/* Note: this doesn't work if name is a
|
/* Note: this doesn't work if name is a
|
||||||
@ -319,6 +337,23 @@ exp : exp '.' name
|
|||||||
write_exp_elt_opcode (STRUCTOP_STRUCT); }
|
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 : exp '.' qualified_name
|
||||||
{ /* exp.type::name becomes exp.*(&type::name) */
|
{ /* exp.type::name becomes exp.*(&type::name) */
|
||||||
/* Note: this doesn't work if name is a
|
/* Note: this doesn't work if name is a
|
||||||
@ -1338,6 +1373,16 @@ static const struct token tokentab2[] =
|
|||||||
{">=", GEQ, BINOP_END}
|
{">=", 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. */
|
/* Read one token, getting characters through lexptr. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1353,7 +1398,10 @@ yylex ()
|
|||||||
static int tempbufsize;
|
static int tempbufsize;
|
||||||
char * token_string = NULL;
|
char * token_string = NULL;
|
||||||
int class_prefix = 0;
|
int class_prefix = 0;
|
||||||
|
int saw_structop = last_was_structop;
|
||||||
|
|
||||||
|
last_was_structop = 0;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
|
|
||||||
/* Check if this is a macro invocation that we need to expand. */
|
/* Check if this is a macro invocation that we need to expand. */
|
||||||
@ -1385,6 +1433,8 @@ yylex ()
|
|||||||
{
|
{
|
||||||
lexptr += 2;
|
lexptr += 2;
|
||||||
yylval.opcode = tokentab2[i].opcode;
|
yylval.opcode = tokentab2[i].opcode;
|
||||||
|
if (in_parse_field && tokentab2[i].opcode == ARROW)
|
||||||
|
last_was_structop = 1;
|
||||||
return tokentab2[i].token;
|
return tokentab2[i].token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,6 +1443,8 @@ yylex ()
|
|||||||
case 0:
|
case 0:
|
||||||
/* If we were just scanning the result of a macro expansion,
|
/* If we were just scanning the result of a macro expansion,
|
||||||
then we need to resume scanning the original text.
|
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
|
Otherwise, we were already scanning the original text, and
|
||||||
we're really done. */
|
we're really done. */
|
||||||
if (scanning_macro_expansion ())
|
if (scanning_macro_expansion ())
|
||||||
@ -1400,6 +1452,13 @@ yylex ()
|
|||||||
finished_macro_expansion ();
|
finished_macro_expansion ();
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
else if (saw_name_at_eof)
|
||||||
|
{
|
||||||
|
saw_name_at_eof = 0;
|
||||||
|
return COMPLETE;
|
||||||
|
}
|
||||||
|
else if (saw_structop)
|
||||||
|
return COMPLETE;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1472,7 +1531,11 @@ yylex ()
|
|||||||
case '.':
|
case '.':
|
||||||
/* Might be a floating point number. */
|
/* Might be a floating point number. */
|
||||||
if (lexptr[1] < '0' || lexptr[1] > '9')
|
if (lexptr[1] < '0' || lexptr[1] > '9')
|
||||||
goto symbol; /* Nope, must be a symbol. */
|
{
|
||||||
|
if (in_parse_field)
|
||||||
|
last_was_structop = 1;
|
||||||
|
goto symbol; /* Nope, must be a symbol. */
|
||||||
|
}
|
||||||
/* FALL THRU into number case. */
|
/* FALL THRU into number case. */
|
||||||
|
|
||||||
case '0':
|
case '0':
|
||||||
@ -1808,10 +1871,20 @@ yylex ()
|
|||||||
/* Any other kind of symbol */
|
/* Any other kind of symbol */
|
||||||
yylval.ssym.sym = sym;
|
yylval.ssym.sym = sym;
|
||||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
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;
|
return NAME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
c_parse (void)
|
||||||
|
{
|
||||||
|
last_was_structop = 0;
|
||||||
|
saw_name_at_eof = 0;
|
||||||
|
return yyparse ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
yyerror (msg)
|
yyerror (msg)
|
||||||
char *msg;
|
char *msg;
|
||||||
|
@ -338,6 +338,90 @@ location_completer (char *text, char *word)
|
|||||||
return list;
|
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". */
|
/* Complete on command names. Used by "help". */
|
||||||
char **
|
char **
|
||||||
command_completer (char *text, char *word)
|
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 =
|
rl_completer_word_break_characters =
|
||||||
gdb_completer_file_name_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
|
/* Commands which complete on locations want to
|
||||||
see the entire argument. */
|
see the entire argument. */
|
||||||
@ -588,7 +673,8 @@ complete_line (const char *text, char *line_buffer, int point)
|
|||||||
rl_completer_word_break_characters =
|
rl_completer_word_break_characters =
|
||||||
gdb_completer_file_name_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;
|
for (p = word;
|
||||||
p > tmp_command
|
p > tmp_command
|
||||||
|
@ -25,6 +25,8 @@ extern char **noop_completer (char *, char *);
|
|||||||
|
|
||||||
extern char **filename_completer (char *, char *);
|
extern char **filename_completer (char *, char *);
|
||||||
|
|
||||||
|
extern char **expression_completer (char *, char *);
|
||||||
|
|
||||||
extern char **location_completer (char *, char *);
|
extern char **location_completer (char *, char *);
|
||||||
|
|
||||||
extern char **command_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>
|
2008-06-06 Marc Khouzam <marc.khouzam@ericsson.com>
|
||||||
|
|
||||||
* gdb.texinfo (GDB/MI Program Context): Added example
|
* gdb.texinfo (GDB/MI Program Context): Added example
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
|
@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 Free Software Foundation, Inc.
|
||||||
@c
|
@c
|
||||||
@c %**start of header
|
@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;
|
overload-resolution off} to disable overload resolution;
|
||||||
see @ref{Debugging C Plus Plus, ,@value{GDBN} Features for C@t{++}}.
|
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
|
@node Help
|
||||||
@section Getting 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);
|
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,
|
/* If the next expression is an OP_LABELED, skips past it,
|
||||||
returning the label. Otherwise, does nothing and returns NULL. */
|
returning the label. Otherwise, does nothing and returns NULL. */
|
||||||
|
|
||||||
|
@ -389,8 +389,14 @@ struct expression
|
|||||||
|
|
||||||
extern struct expression *parse_expression (char *);
|
extern struct expression *parse_expression (char *);
|
||||||
|
|
||||||
|
extern struct type *parse_field_expression (char *, char **);
|
||||||
|
|
||||||
extern struct expression *parse_exp_1 (char **, struct block *, int);
|
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
|
/* The innermost context required by the stack and register variables
|
||||||
we've encountered so far. To use this, set it to NULL, then call
|
we've encountered so far. To use this, set it to NULL, then call
|
||||||
parse_<whatever>, then look at it. */
|
parse_<whatever>, then look at it. */
|
||||||
|
133
gdb/parse.c
133
gdb/parse.c
@ -52,6 +52,7 @@
|
|||||||
#include "block.h"
|
#include "block.h"
|
||||||
#include "source.h"
|
#include "source.h"
|
||||||
#include "objfiles.h"
|
#include "objfiles.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
/* Standard set of definitions for printing, dumping, prefixifying,
|
/* Standard set of definitions for printing, dumping, prefixifying,
|
||||||
* and evaluating expressions. */
|
* and evaluating expressions. */
|
||||||
@ -80,6 +81,15 @@ char *prev_lexptr;
|
|||||||
int paren_depth;
|
int paren_depth;
|
||||||
int comma_terminates;
|
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.
|
/* A temporary buffer for identifiers, so we can null-terminate them.
|
||||||
|
|
||||||
We allocate this with xrealloc. parse_exp_1 used to allocate with
|
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 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);
|
int);
|
||||||
|
|
||||||
static struct expression *parse_exp_in_context (char **, struct block *, int,
|
static struct expression *parse_exp_in_context (char **, struct block *, int,
|
||||||
int);
|
int, int *);
|
||||||
|
|
||||||
void _initialize_parse (void);
|
void _initialize_parse (void);
|
||||||
|
|
||||||
@ -460,6 +470,16 @@ write_exp_msymbol (struct minimal_symbol *msymbol,
|
|||||||
}
|
}
|
||||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
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:
|
/* 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)
|
/* 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)
|
prefixify_expression (struct expression *expr)
|
||||||
{
|
{
|
||||||
int len = sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
|
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. */
|
/* Copy the original expression into temp. */
|
||||||
memcpy (temp, expr, len);
|
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
|
/* 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
|
/* Copy the subexpression ending just before index INEND in INEXPR
|
||||||
into OUTEXPR, starting at index OUTBEG.
|
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,
|
prefixify_subexp (struct expression *inexpr,
|
||||||
struct expression *outexpr, int inend, int outbeg)
|
struct expression *outexpr, int inend, int outbeg)
|
||||||
{
|
{
|
||||||
@ -886,6 +913,7 @@ prefixify_subexp (struct expression *inexpr,
|
|||||||
int i;
|
int i;
|
||||||
int *arglens;
|
int *arglens;
|
||||||
enum exp_opcode opcode;
|
enum exp_opcode opcode;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
operator_length (inexpr, inend, &oplen, &args);
|
operator_length (inexpr, inend, &oplen, &args);
|
||||||
|
|
||||||
@ -896,6 +924,9 @@ prefixify_subexp (struct expression *inexpr,
|
|||||||
EXP_ELEM_TO_BYTES (oplen));
|
EXP_ELEM_TO_BYTES (oplen));
|
||||||
outbeg += oplen;
|
outbeg += oplen;
|
||||||
|
|
||||||
|
if (expout_last_struct == inend)
|
||||||
|
result = outbeg - oplen;
|
||||||
|
|
||||||
/* Find the lengths of the arg subexpressions. */
|
/* Find the lengths of the arg subexpressions. */
|
||||||
arglens = (int *) alloca (args * sizeof (int));
|
arglens = (int *) alloca (args * sizeof (int));
|
||||||
for (i = args - 1; i >= 0; i--)
|
for (i = args - 1; i >= 0; i--)
|
||||||
@ -913,11 +944,21 @@ prefixify_subexp (struct expression *inexpr,
|
|||||||
outbeg does similarly in the output. */
|
outbeg does similarly in the output. */
|
||||||
for (i = 0; i < args; i++)
|
for (i = 0; i < args; i++)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
oplen = arglens[i];
|
oplen = arglens[i];
|
||||||
inend += oplen;
|
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;
|
outbeg += oplen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This page contains the two entry points to this file. */
|
/* This page contains the two entry points to this file. */
|
||||||
@ -935,23 +976,30 @@ prefixify_subexp (struct expression *inexpr,
|
|||||||
struct expression *
|
struct expression *
|
||||||
parse_exp_1 (char **stringptr, struct block *block, int comma)
|
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
|
/* 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 *
|
static struct expression *
|
||||||
parse_exp_in_context (char **stringptr, struct block *block, int comma,
|
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;
|
struct cleanup *old_chain;
|
||||||
|
int subexp;
|
||||||
|
|
||||||
lexptr = *stringptr;
|
lexptr = *stringptr;
|
||||||
prev_lexptr = NULL;
|
prev_lexptr = NULL;
|
||||||
|
|
||||||
paren_depth = 0;
|
paren_depth = 0;
|
||||||
type_stack_depth = 0;
|
type_stack_depth = 0;
|
||||||
|
expout_last_struct = -1;
|
||||||
|
|
||||||
comma_terminates = comma;
|
comma_terminates = comma;
|
||||||
|
|
||||||
@ -986,10 +1034,20 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma,
|
|||||||
expout = (struct expression *)
|
expout = (struct expression *)
|
||||||
xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
|
xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
|
||||||
expout->language_defn = current_language;
|
expout->language_defn = current_language;
|
||||||
make_cleanup (free_current_contents, &expout);
|
|
||||||
|
|
||||||
if (current_language->la_parser ())
|
TRY_CATCH (except, RETURN_MASK_ALL)
|
||||||
current_language->la_error (NULL);
|
{
|
||||||
|
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);
|
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,
|
dump_raw_expression (expout, gdb_stdlog,
|
||||||
"before conversion to prefix form");
|
"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);
|
current_language->la_post_parser (&expout, void_context_p);
|
||||||
|
|
||||||
@ -1033,6 +1093,45 @@ parse_expression (char *string)
|
|||||||
return exp;
|
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 */
|
/* A post-parser that does nothing */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -138,6 +138,8 @@ extern void write_exp_msymbol (struct minimal_symbol *,
|
|||||||
|
|
||||||
extern void write_dollar_variable (struct stoken str);
|
extern void write_dollar_variable (struct stoken str);
|
||||||
|
|
||||||
|
extern void mark_struct_expression (void);
|
||||||
|
|
||||||
extern char *find_template_name_end (char *);
|
extern char *find_template_name_end (char *);
|
||||||
|
|
||||||
extern void start_arglist (void);
|
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\
|
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\
|
current working language. The result is printed and saved in the value\n\
|
||||||
history, if it is not void."));
|
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, _("\
|
add_cmd ("variable", class_vars, set_command, _("\
|
||||||
Evaluate expression EXP and assign result to variable VAR, using assignment\n\
|
Evaluate expression EXP and assign result to variable VAR, using assignment\n\
|
||||||
@ -2399,13 +2399,13 @@ resides in memory.\n\
|
|||||||
\n\
|
\n\
|
||||||
EXP may be preceded with /FMT, where FMT is a format letter\n\
|
EXP may be preceded with /FMT, where FMT is a format letter\n\
|
||||||
but no count or size letter (see \"x\" command)."));
|
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);
|
add_com_alias ("p", "print", class_vars, 1);
|
||||||
|
|
||||||
c = add_com ("inspect", class_vars, inspect_command, _("\
|
c = add_com ("inspect", class_vars, inspect_command, _("\
|
||||||
Same as \"print\" command, except that if you are running in the epoch\n\
|
Same as \"print\" command, except that if you are running in the epoch\n\
|
||||||
environment, the value is printed in its own window."));
|
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,
|
add_setshow_uinteger_cmd ("max-symbolic-offset", no_class,
|
||||||
&max_symbolic_offset, _("\
|
&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>
|
2008-06-06 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||||
|
|
||||||
* gdb.cp/call-c.exp: Test for incorrect handling of reference
|
* 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 marker3 (a, b) char *a, *b; {} /* set breakpoint 18 here */
|
||||||
void marker4 (d) long d; {} /* set breakpoint 13 here */
|
void marker4 (d) long d; {} /* set breakpoint 13 here */
|
||||||
#endif
|
#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-'" }
|
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',
|
# The following tests used to simply try to complete `${objdir}/file',
|
||||||
# and so on. The problem is that ${objdir} can be very long; the
|
# 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_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 *,
|
extern struct value *evaluate_subexp_with_coercion (struct expression *,
|
||||||
int *, enum noside);
|
int *, enum noside);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user