GDB/MI: Add new "--language LANG" command option.
authorJoel Brobecker <brobecker@adacore.com>
Mon, 11 Nov 2013 05:21:44 +0000 (09:21 +0400)
committerJoel Brobecker <brobecker@adacore.com>
Thu, 14 Nov 2013 10:36:18 +0000 (14:36 +0400)
Frontend sometimes need to evaluate expressions that are
language-specific. For instance, Eclipse uses the following
expression to determine the size of an address on the target:

    -data-evaluate-expression "sizeof (void*)"

Unfortunately, if the main of the program being debugged is not C,
this may not work. For instance, if the main is in Ada, you get...

    -data-evaluate-expression "sizeof (void*)"
    ^error,msg="No definition of \"sizeof\" in current context."

... and apparently decides to stop the debugging session as a result.
The  recommendation sent was to specifically set the language to C
before trying to evaluate the expression.  Something such as:

    1. save current language
    2. set language c
    3. -data-evaluate-expression "sizeof (void*)"
    4. Restore language

This has the same disadvantages as the ones outlined in the "Context
Management" section of the GDB/MI documentation regarding setting
the current thread or the current frame, thus recommending the use of
general command-line switches such as --frame, or --thread instead.

This patch follows the same steps for the language, adding a similar
new command option: --language LANG. Example of use:

    -data-evaluate-expression --language c "sizeof (void*)"
    ^done,value="4"

gdb/ChangeLog:

        * mi/mi-parse.h (struct mi_parse) <language>: New field.
        * mi/mi-main.c (mi_cmd_execute): Temporarily set language to
        PARSE->LANGUAGE during command execution, if set.
        * mi/mi-parse.c: Add "language.h" #include.
        (mi_parse): Add parsing of "--language" command option.

        * NEWS: Add entry mentioning the new "--language" command option.

gdb/testsuite/ChangeLog:

        * gdb.mi/mi-language.exp: New file.

gdb/doc/ChangeLog:

        * gdb.texinfo (Show): Add xref anchor for "show language" command.
        (Context management): Place current subsection text into its own
        subsubsection.  Add new subsubsection describing the "--language"
        command option.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/mi/mi-main.c
gdb/mi/mi-parse.c
gdb/mi/mi-parse.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-language.exp [new file with mode: 0644]

index 2dc6cca69876dfaf05541e86dd3f7f9e1b727e7f..8cbe4a4a9f75ecd1ced26bbc92210e9f242a1259 100644 (file)
@@ -1,3 +1,13 @@
+2013-11-14  Joel Brobecker  <brobecker@adacore.com>
+
+       * mi/mi-parse.h (struct mi_parse) <language>: New field.
+       * mi/mi-main.c (mi_cmd_execute): Temporarily set language to
+       PARSE->LANGUAGE during command execution, if set.
+       * mi/mi-parse.c: Add "language.h" #include.
+       (mi_parse): Add parsing of "--language" command option.
+
+       * NEWS: Add entry mentioning the new "--language" command option.
+
 2013-11-14  Pedro Alves  <palves@redhat.com>
            Joel Brobecker  <brobecker@adacore.com>
 
index 38209e8416611b063b3d67d23df550d69ba5344e..3be007373aa77c167cf3a30072b1d98a954e33ea 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -151,6 +151,8 @@ show startup-with-shell
 
 * MI changes
 
+  ** All MI commands now accept an optional "--language" option.
+
   ** The -trace-save MI command can optionally save trace buffer in Common
      Trace Format now.
 
index 968201eb6c0858dbc8f321a4290248cb4b2e09f6..6ffdefa99e1a4fcd1a70ac8a18deeb7bab02eb97 100644 (file)
@@ -1,3 +1,10 @@
+2013-11-14  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.texinfo (Show): Add xref anchor for "show language" command.
+       (Context management): Place current subsection text into its own
+       subsubsection.  Add new subsubsection describing the "--language"
+       command option.
+
 2013-11-13  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.texinfo (GDB/MI Miscellaneous Commands): Delete
index 84acd5c0ad7622fff02fce9e1b8191d567e12d1f..a164785720f8050d238d06e0bce18f3d0b7add54 100644 (file)
@@ -13340,6 +13340,7 @@ working language, and also what language source files were written in.
 
 @table @code
 @item show language
+@anchor{show language}
 @kindex show language
 Display the current working language.  This is the
 language you can use with commands such as @code{print} to
@@ -28816,6 +28817,8 @@ the user interface.
 @node Context management
 @subsection Context management
 
+@subsubsection Threads and Frames
+
 In most cases when @value{GDBN} accesses the target, this access is
 done in context of a specific thread and frame (@pxref{Frames}).
 Often, even when accessing global data, the target requires that a thread
@@ -28866,6 +28869,25 @@ all subsequent commands.  No frontend is known to do this exactly
 right, so it is suggested to just always pass the @samp{--thread} and
 @samp{--frame} options.
 
+@subsubsection Language
+
+The execution of several commands depends on which language is selected.
+By default, the current language (@pxref{show language}) is used.
+But for commands known to be language-sensitive, it is recommended
+to use the @samp{--language} option.  This option takes one argument,
+which is the name of the language to use while executing the command.
+For instance:
+
+@smallexample
+-data-evaluate-expression --language c "sizeof (void*)"
+^done,value="4"
+(gdb) 
+@end smallexample
+
+The valid language names are the same names accepted by the
+@samp{set language} command (@pxref{Manually}), excluding @samp{auto},
+@samp{local} or @samp{unknown}.
+
 @node Asynchronous and non-stop modes
 @subsection Asynchronous command execution and non-stop mode
 
index c3f72210479fc322d84d9a1ec318294a460f1da6..bbf944a0a316da1b40c11f82ee09f92b6a3424ea 100644 (file)
@@ -2122,6 +2122,7 @@ static void
 mi_cmd_execute (struct mi_parse *parse)
 {
   struct cleanup *cleanup;
+  enum language saved_language;
 
   cleanup = prepare_execute_command ();
 
@@ -2183,6 +2184,12 @@ mi_cmd_execute (struct mi_parse *parse)
        error (_("Invalid frame id: %d"), frame);
     }
 
+  if (parse->language != language_unknown)
+    {
+      make_cleanup_restore_current_language ();
+      set_language (parse->language);
+    }
+
   current_context = parse;
 
   if (parse->cmd->suppress_notification != NULL)
index a3c184910bf1e773cf4ad5c56f7a59021fcb8fd9..9994307d9f07f2188d805fb1d5608e92064d64a9 100644 (file)
@@ -27,6 +27,7 @@
 #include <ctype.h>
 #include "gdb_string.h"
 #include "cli/cli-utils.h"
+#include "language.h"
 
 static const char mi_no_values[] = "--no-values";
 static const char mi_simple_values[] = "--simple-values";
@@ -244,6 +245,7 @@ mi_parse (const char *cmd, char **token)
   parse->thread_group = -1;
   parse->thread = -1;
   parse->frame = -1;
+  parse->language = language_unknown;
 
   cleanup = make_cleanup (mi_parse_cleanup, parse);
 
@@ -292,7 +294,10 @@ mi_parse (const char *cmd, char **token)
      some important commands, like '-break-*' are implemented by
      forwarding to the CLI layer directly.  We want to parse --thread
      and --frame here, so as not to leave those option in the string
-     that will be passed to CLI.  */
+     that will be passed to CLI.
+
+     Same for the --language option.  */
+
   for (;;)
     {
       const char *option;
@@ -300,6 +305,7 @@ mi_parse (const char *cmd, char **token)
       size_t tgs = sizeof ("--thread-group ") - 1;
       size_t ts = sizeof ("--thread ") - 1;
       size_t fs = sizeof ("--frame ") - 1;
+      size_t ls = sizeof ("--language ") - 1;
 
       if (strncmp (chp, "--all ", as) == 0)
        {
@@ -348,6 +354,23 @@ mi_parse (const char *cmd, char **token)
          parse->frame = strtol (chp, &endp, 10);
          chp = endp;
        }
+      else if (strncmp (chp, "--language ", ls) == 0)
+       {
+         char *lang_name;
+         struct cleanup *old_chain;
+
+         option = "--language";
+         chp += ls;
+         lang_name = extract_arg_const (&chp);
+         old_chain = make_cleanup (xfree, lang_name);
+
+         parse->language = language_enum (lang_name);
+         if (parse->language == language_unknown
+             || parse->language == language_auto)
+           error (_("Invalid --language argument: %s"), lang_name);
+
+         do_cleanups (old_chain);
+       }
       else
        break;
 
index b20a389dca32a3bf02664b0ae9fa86a58cfbf0e9..325c1e14398c5992bfbe217485eaae40a84f2054 100644 (file)
@@ -50,6 +50,10 @@ struct mi_parse
     int thread_group; /* At present, the same as inferior number.  */
     int thread;
     int frame;
+
+    /* The language that should be used to evaluate the MI command.
+       Ignored if set to language_unknown.  */
+    enum language language;
   };
 
 /* Attempts to parse CMD returning a ``struct mi_parse''.  If CMD is
index 5d1de05957169b2b4d9589fa055441d0f79f7afe..0b0f75901492b206a5944f53266c6309094d72b4 100644 (file)
@@ -1,3 +1,7 @@
+2013-11-14  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.mi/mi-language.exp: New file.
+
 2013-09-17  Keith Seitz  <keiths@redhat.com>
 
        PR c++/7935
diff --git a/gdb/testsuite/gdb.mi/mi-language.exp b/gdb/testsuite/gdb.mi/mi-language.exp
new file mode 100644 (file)
index 0000000..550beec
--- /dev/null
@@ -0,0 +1,62 @@
+# Copyright 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+mi_gdb_test "set lang ada" \
+            ".*=cmd-param-changed,param=\"language\",value=\"ada\".*" \
+            "set lang ada"
+
+# Evaluate an expression that the Ada language is unable to parse.
+mi_gdb_test "-data-evaluate-expression \"sizeof (void*)\"" \
+            "\\^error,.*" \
+            "sizeof expression using current language"
+
+# Now, ask for the same expression to be parsed, but using the C
+# language.
+mi_gdb_test "-data-evaluate-expression --language c \"sizeof (void*)\"" \
+            "\\^done,value=\"$decimal\"" \
+            "sizeof expression using C language"
+
+# Double-check that the current language has not changed.
+mi_gdb_test "show lang ada" \
+            ".*The current source language is \\\\\"ada\\\\\".*" \
+            "set lang ada"
+
+# Test what happens when specifying an invalid language name...
+mi_gdb_test "-data-evaluate-expression --language invlang \"sizeof (void*)\"" \
+            "\\^error,msg=\"Invalid --language argument: invlang\"" \
+            "data-evaluate-expression with invalid language name"
+
+# Make sure that "--language auto" is also rejected.
+mi_gdb_test "-data-evaluate-expression --language auto \"sizeof (void*)\"" \
+            "\\^error,msg=\"Invalid --language argument: auto\"" \
+            "data-evaluate-expression with language auto"
+
+# Make sure that "--language local" is also rejected.
+mi_gdb_test "-data-evaluate-expression --language local \"sizeof (void*)\"" \
+            "\\^error,msg=\"Invalid --language argument: local\"" \
+            "data-evaluate-expression with language local"
+
+# Make sure that "--language unknown" is also rejected.
+mi_gdb_test "-data-evaluate-expression --language unknown \"sizeof (void*)\"" \
+            "\\^error,msg=\"Invalid --language argument: unknown\"" \
+            "data-evaluate-expression with language unknown"