fputs (str, stdout);
}
+static int
+time_out_cb (void *data)
+{
+ fatal ("GDB response has timed out");
+ /* NOTREACHED */
+ return 0;
+}
+
static ATTRIBUTE_UNUSED void
to_gdb_cb (const char *str, void *data)
{
}
static void
-quit_command (mi_h *h, const char *cmd)
-{
- exit (EXIT_SUCCESS);
-}
-
-static void
default_command (mi_h *h, const char *cmd)
{
int count = 1;
+ gdb_assert (strchr (cmd, '\n') == 0);
mi_send (h, "-interpreter-exec console \"%s\"\n", cmd);
while (count > 0)
}
}
+static void
+quit_command (mi_h *h, const char *cmd)
+{
+ exit (EXIT_SUCCESS);
+}
+
+static char *
+mi_escape (const char *cs)
+{
+ char *d, *retval = xmalloc (strlen (cs) * 2 + 1);
+
+ d = retval;
+ while (*cs)
+ {
+ if (*cs == '"' || *cs == '\\')
+ *d++ = '\\';
+ *d++ = *cs++;
+ }
+ *d = '\0';
+ return retval;
+}
+
+static void
+gdb_done (mi_h *h, const char *command)
+{
+ mi_output *res;
+
+ mi_send (h, "%s\n", command);
+ res = mi_get_response_blk (h);
+ gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
+ && res->c == NULL);
+ mi_free_output (res);
+}
+
+static void
+commands_command_console_cb (const char *str, void *data)
+{
+ char **strptr = data;
+
+ gdb_assert (*strptr == NULL);
+ *strptr = xstrdup (str);
+}
+
+static void
+commands_command (mi_h *h, const char *cmd_param)
+{
+ char *cmd = xstrdup ("");
+ size_t cmd_len = 0;
+ mi_output *res;
+ char *bpnum = NULL;
+ int nesting;
+
+ if (*cmd_param == '\0')
+ {
+ mi_set_console_cb (h, commands_command_console_cb, &bpnum);
+ gdb_done (h, "output $bpnum");
+ mi_set_console_cb (h, console_cb, NULL);
+ gdb_assert (bpnum != NULL);
+ cmd_param = bpnum;
+ }
+
+ printf (_("Type commands for breakpoint(s) %s, one per line.\n"
+ "End with a line saying just \"end\".\n"), cmd_param);
+
+ nesting = 0;
+ while (nesting >= 0)
+ {
+ char *prompt, *data, *data2, *start, *end;
+ size_t data2_len;
+ int do_nest = 0;
+
+ prompt = xstrprintf ("%*s>", (int) nesting);
+ data = readline (prompt);
+ xfree (prompt);
+ if (data == NULL)
+ data = xstrdup ("end");
+
+ for (start = data; isspace (*start); start++);
+ for (end = data + strlen (data); end > start && isspace (end[-1]); end--);
+ data2 = xmalloc (end - start + 1);
+ memcpy (data2, start, end - start);
+ data2[end - start] = '\0';
+ if (strcmp (data2, "python") == 0)
+ do_nest = 1;
+ if (strcmp (data2, "end") == 0)
+ do_nest = -1;
+ for (end = data2; *end && !isspace (*end); end++);
+ *end = '\0';
+
+ /* Here is a bug in GDB, it does not recognize command shortcuts. */
+ if (strcmp (data2, "while") == 0 || strcmp (data2, "if") == 0
+ || strcmp (data2, "commands") == 0
+ || strcmp (data2, "while-stepping") == 0
+ || strcmp (data2, "stepping") == 0 || strcmp (data2, "ws") == 0)
+ do_nest = 1;
+ xfree (data2);
+
+ nesting += do_nest;
+ if (nesting < 0)
+ break;
+
+ data2 = mi_escape (data);
+ xfree (data);
+ data2_len = strlen (data2);
+ cmd = xrealloc (cmd, cmd_len + 2 + data2_len + 2);
+ cmd[cmd_len] = ' ';
+ cmd[cmd_len + 1] = '"';
+ memcpy (&cmd[cmd_len + 2], data2, data2_len);
+ cmd[cmd_len + 2 + data2_len] = '"';
+ cmd[cmd_len + 2 + data2_len + 1] = '\0';
+ cmd_len += 2 + data2_len + 1;
+ xfree (data2);
+ }
+
+ mi_send (h, "-break-commands %s%s\n", cmd_param, cmd);
+ xfree (cmd);
+ xfree (bpnum);
+
+ res = mi_get_response_blk (h);
+ gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
+ && res->c == NULL);
+ mi_free_output (res);
+}
+
static const struct cmd
{
const char *name;
+ int min_shortcut;
void (*func) (mi_h *h, const char *cmd);
} cmds[] =
{
- { "q", quit_command },
- { "qu", quit_command },
- { "qui", quit_command },
- { "quit", quit_command },
+ { "quit", 1, quit_command },
+ { "commands", 4, commands_command },
};
static void
while (isalnum (*cs))
cs++;
end = cs;
+ while (isspace (*cs))
+ cs++;
for (cmdp = cmds; cmdp < &cmds[LENGTH (cmds)]; cmdp++)
- if (strlen (cmdp->name) == end - start
- && strncmp (cmd, cmdp->name, end - start) == 0)
- return cmdp->func (h, cmd);
+ if (cmdp->min_shortcut <= end - start && end - start <= strlen (cmdp->name)
+ && strncmp (start, cmdp->name, end - start) == 0)
+ return cmdp->func (h, cs);
return default_command (h, cmd);
}
static void
-gdb_done (mi_h *h, const char *command)
-{
- mi_output *res;
-
- mi_send (h, "%s\n", command);
- res = mi_get_response_blk (h);
- gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
- && res->c == NULL);
- mi_free_output (res);
-}
-
-static void
gdb_set_string (mi_h *h, const char *setting, const char *value)
{
char *cmd = xstrprintf ("-gdb-set %s %s", setting, value);
{
on_exit (h_disconnect, h);
mi_set_console_cb (h, console_cb, NULL);
+ mi_set_time_out_cb (h, time_out_cb, NULL);
+
// mi_set_to_gdb_cb (h, to_gdb_cb, NULL);
// mi_set_from_gdb_cb (h, from_gdb_cb, NULL);
}