]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb
authorTom Tromey <tromey@redhat.com>
Fri, 6 Jun 2008 20:58:08 +0000 (20:58 +0000)
committerTom Tromey <tromey@redhat.com>
Fri, 6 Jun 2008 20:58:08 +0000 (20:58 +0000)
* 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.

18 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/breakpoint.c
gdb/c-exp.y
gdb/completer.c
gdb/completer.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/eval.c
gdb/expression.h
gdb/parse.c
gdb/parser-defs.h
gdb/printcmd.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/break1.c
gdb/testsuite/gdb.base/completion.exp
gdb/value.h

index 897ee48a1d0a5a4d377c14ba19e5fd423770957a..29f89cfe26e8614f2b7b369f6b4ba9ba97296c9b 100644 (file)
@@ -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
index 7132b489c920cc47f94d8ff0038bb40a34daf9ee..c14dc1ab4accbe8d2fccfadee6f8c5e2bb063dbd 100644 (file)
@@ -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)
index 1a11319215b46d9903edfaa77b8d71ab67eb3ee1..523f328eec8b7d9006cdd87552fe12fe7d22124e 100644 (file)
--- a/gdb/NEWS
+++ b/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:
index 808d06262cb694c39cbc23e5ae89ba0d5a523295..051b753d6392fe6640d58fb13b5bfbc7da2f4899 100644 (file)
@@ -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''."));
index 372963318c79babb0ffc6e7ea63cc470933f4831..9cf63d8970d4a107336eda56e3753d6c5480a8b9 100644 (file)
@@ -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,7 +1398,10 @@ yylex ()
   static int tempbufsize;
   char * token_string = NULL;
   int class_prefix = 0;
-   
+  int saw_structop = last_was_structop;
+
+  last_was_structop = 0;
+
  retry:
 
   /* Check if this is a macro invocation that we need to expand.  */
@@ -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')
-       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.  */
 
     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;
index 3d3d34cce537eae282877ae016b0b54a32de3437..163a9dcfc83184c2c703845ce5ebd79b96609fef 100644 (file)
@@ -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
index de311c4ac175e777eab55e8997e1ffacf9cd8372..318594e11e267900f3271655676aa30a37938444 100644 (file)
@@ -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 *);
index a6f98e674c33d4f42eba5a212e30f6dc5341b39c..c24925392bc0918d98392e49ccc2a0d898c9850d 100644 (file)
@@ -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
index 9915ea1f2219c1afa8c8fe67cd135a7ef5d4de2e..5cef05b5efb9b9e75757a3de84621ac4e33ecfe9 100644 (file)
@@ -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
index 97503c3a21197bcda5ba334e148da8d8efe650d9..bbd7539a9fbbe80970685135a798f6f28cb960c8 100644 (file)
@@ -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. */
 
index 0085b99002b3e1b2dc7bbbe2ba7ea569e051dc50..084c70effed1bcd25a19452c085695b733645d30 100644 (file)
@@ -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.  */
index 09ceaa920251e0c3f498a27badf9166f9daa6306..b587ec394c8a3da647d28a988e7392f48173c909 100644 (file)
@@ -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,
-                             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;
+}
+
 \f
 /* Recognize tokens that start with '$'.  These include:
 
@@ -664,9 +684,13 @@ copy_name (struct stoken token)
 }
 \f
 /* 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;
 }
 \f
 /* 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);
 
-  if (current_language->la_parser ())
-    current_language->la_error (NULL);
+  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
index 3e473c4d6871a83142f714b7a98b8254509bdb3f..f49ff9e76aa53db543303f92099ed0dc23fe16f8 100644 (file)
@@ -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);
index bbfef3e044165fb04e8499aca3227dfcd515825b..e25c73c4da5ab02290a3b9d5907fef14089407df 100644 (file)
@@ -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, _("\
index 917d9302463af149a8f52c2b3c57d2f2b978d3b2..ef42b4d4f7204e0b53c2371093a77f9265b43db1 100644 (file)
@@ -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
index 3272cbd6a007efc0f7c3a6e7b273a27d91bfccd2..9cbcd3036e82ffb2a3d545d92a039e6d5dacfa6d 100644 (file)
@@ -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];
index 09f04dfeaa286c4288dbc66fefc4a8176744a5c2..79f588b8aab2968a5b0f6faf8228221ef46ca71b 100644 (file)
@@ -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
index fa42965783b8dc01c5fc71382df0aba5c4092cf3..2aac9b2d76c0c70def36528e31d708a34e9199ef 100644 (file)
@@ -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);