Re: [RFC] New GDB/MI command "-info-gdb-mi-command"

Pedro Alves
2013-11-14T19:03:04Z

On 11/14/2013 06:44 PM, Pedro Alves wrote:

> Yeah. I think that points out that errors like "Undefined MI command:" and
> "Usage:" errors are in a different class of errors from errors caused
> by user input though. The former should never ever be seen by the user.
> They're "internal" gdb<->frontend errors. We could/should tag these
> differently somehow, so that the frontend doesn't have to parse a
> free form string. Like:
>
> "^error,msg="..."
> "^error,msg="...",code="unknown-command"
> "^error,msg="...",code="usage"
>
> or some such.
>
> This does not invalidate listing features in -list-features, as
> it's often useful to know upfront whether some feature is supported,
> so the frontend can disable parts of the GUI that won't make sense
> for the current target/session.
>

Something like this:

-whatever
^error,msg="Undefined MI command: whatever",error="unknown-command"
(gdb)
-list-thread-groups --frame 1 --frame 1
^error,msg="Duplicate '--frame' option",error="command-usage"
(gdb)

Frontends must ignore unknown attributes, so it's backwards
compatible.

Just a POC. Of course, we'd have to go audit all MI "error" calls.

---

gdb/exceptions.h | 6 ++++++
gdb/mi/mi-main.c | 13 ++++++++++++-
gdb/mi/mi-parse.c | 20 +++++++++++++-------
3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index 129d29a..07599ae 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -93,6 +93,12 @@ enum errors {
aborted as the inferior state is no longer valid. */
TARGET_CLOSE_ERROR,

+ /* An unknown command was executed. */
+ UNKNOWN_COMMAND_ERROR,
+
+ /* Wrong command usage. */
+ COMMAND_USAGE_ERROR,
+
/* Add more errors here. */
NR_ERRORS
};
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index bbf944a..c2a3988 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -2021,7 +2021,18 @@ mi_print_exception (const char *token, struct gdb_exception exception)
fputs_unfiltered ("unknown error", raw_stdout);
else
fputstr_unfiltered (exception.message, '"', raw_stdout);
- fputs_unfiltered ("\"\n", raw_stdout);
+ fputs_unfiltered ("\"", raw_stdout);
+
+ switch (exception.error)
+ {
+ case UNKNOWN_COMMAND_ERROR:
+ fputs_unfiltered (",error=\"unknown-command\"", raw_stdout);
+ break;
+ case COMMAND_USAGE_ERROR:
+ fputs_unfiltered (",error=\"command-usage\"", raw_stdout);
+ break;
+ }
+ fputs_unfiltered ("\n", raw_stdout);
}

void
diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c
index 9994307..2c9d267 100644
--- a/gdb/mi/mi-parse.c
+++ b/gdb/mi/mi-parse.c
@@ -285,7 +285,8 @@ mi_parse (const char *cmd, char **token)
/* Find the command in the MI table. */
parse->cmd = mi_lookup (parse->command);
if (parse->cmd == NULL)
- error (_("Undefined MI command: %s"), parse->command);
+ throw_error (UNKNOWN_COMMAND_ERROR,
+ _("Undefined MI command: %s"), parse->command);

/* Skip white space following the command. */
chp = skip_spaces_const (chp);
@@ -324,7 +325,8 @@ mi_parse (const char *cmd, char **token)

option = "--thread-group";
if (parse->thread_group != -1)
- error (_("Duplicate '--thread-group' option"));
+ throw_error (COMMAND_USAGE_ERROR,
+ _("Duplicate '--thread-group' option"));
chp += tgs;
if (*chp != 'i')
error (_("Invalid thread group id"));
@@ -338,7 +340,8 @@ mi_parse (const char *cmd, char **token)

option = "--thread";
if (parse->thread != -1)
- error (_("Duplicate '--thread' option"));
+ throw_error (COMMAND_USAGE_ERROR,
+ _("Duplicate '--thread' option"));
chp += ts;
parse->thread = strtol (chp, &endp, 10);
chp = endp;
@@ -349,7 +352,8 @@ mi_parse (const char *cmd, char **token)

option = "--frame";
if (parse->frame != -1)
- error (_("Duplicate '--frame' option"));
+ throw_error (COMMAND_USAGE_ERROR,
+ _("Duplicate '--frame' option"));
chp += fs;
parse->frame = strtol (chp, &endp, 10);
chp = endp;
@@ -367,7 +371,8 @@ mi_parse (const char *cmd, char **token)
parse->language = language_enum (lang_name);
if (parse->language == language_unknown
|| parse->language == language_auto)
- error (_("Invalid --language argument: %s"), lang_name);
+ throw_error (COMMAND_USAGE_ERROR,
+ _("Invalid --language argument: %s"), lang_name);

do_cleanups (old_chain);
}
@@ -414,7 +419,8 @@ mi_parse_print_values (const char *name)
|| strcmp (name, mi_simple_values) == 0)
return PRINT_SIMPLE_VALUES;
else
- error (_("Unknown value for PRINT_VALUES: must be: \
+ throw_error (COMMAND_USAGE_ERROR,
+ _("Unknown value for PRINT_VALUES: must be: \
0 or \"%s\", 1 or \"%s\", 2 or \"%s\""),
- mi_no_values, mi_all_values, mi_simple_values);
+ mi_no_values, mi_all_values, mi_simple_values);
}