From: Jan Kratochvil Date: Fri, 3 Aug 2012 11:31:02 +0000 (+0200) Subject: Commends interpretation etc. X-Git-Url: http://git.jankratochvil.net/?p=gdbmicli.git;a=commitdiff_plain;h=f2ce960a8b335fdfd2a2defa26ffae990afa8049 Commends interpretation etc. --- diff --git a/ansidecl.h b/ansidecl.h index 7628064..b16f2b2 100644 --- a/ansidecl.h +++ b/ansidecl.h @@ -1,4 +1,11 @@ -#if (GCC_VERSION < 2007) +#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#if GCC_VERSION < 2007 # define __attribute__(x) #endif #define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#define LENGTH(x) (sizeof (x) / sizeof (*(x))) + +#define bool int +#define true 1 +#define false 0 diff --git a/main.c b/main.c index 880c1fe..c43df32 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,16 @@ +#define _GNU_SOURCE #include #include +#include #include +#include +#include +#include #include "ansidecl.h" #include "mi_gdb.h" +#define gdb_assert assert + static ATTRIBUTE_NORETURN void fatal (const char *fmt, ...) { @@ -12,15 +19,224 @@ fatal (const char *fmt, ...) va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); +raise (SIGABRT); exit (EXIT_FAILURE); } +static char * +xstrdup (const char *s) +{ + char *retval; + + gdb_assert (s != NULL); + retval = strdup (s); + gdb_assert (retval != NULL); + return retval; +} + +static void +xfree (void *p) +{ + free (p); +} + +static char * +xstrprintf (const char *fmt, ...) +{ + va_list ap; + char *retval; + int i; + + va_start (ap, fmt); + i = vasprintf (&retval, fmt, ap); + va_end (ap); + gdb_assert (i > 0); + gdb_assert (i == strlen (retval)); + return retval; +} + static void console_cb (const char *str, void *data) { fputs (str, stdout); } +static ATTRIBUTE_UNUSED void +to_gdb_cb (const char *str, void *data) +{ + printf ("to_gdb: %s\n", str); +} + +static ATTRIBUTE_UNUSED void +from_gdb_cb (const char *str, void *data) +{ + printf ("from_gdb: %s\n", str); +} + +static void +h_disconnect (int rc, void *arg) +{ + mi_h *h = arg; + + mi_disconnect (h); +} + +static void +history_save (int rc, void *arg) +{ + const char *history_filename = arg; + + write_history (history_filename); +} + +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; + + mi_send (h, "-interpreter-exec console \"%s\"\n", cmd); + + while (count > 0) + { + mi_output *rec, *res; + + res = mi_get_response_blk (h); + gdb_assert (res != NULL); + + for (rec = res; rec != NULL; rec = rec->next) + switch (rec->tclass) + { + case MI_CL_DONE: + count--; + break; + case MI_CL_RUNNING: + /* We do not get MI_CL_DONE here, wait for MI_CL_STOPPED. */ + break; + case MI_CL_STOPPED: + count--; + break; + case MI_CL_ERROR: + gdb_assert (rec->c->type == t_const); + puts (rec->c->v.cstr); + break; + default: + fatal ("mi_get_rrecord == MI_CL_??? (%d)", rec->tclass); + } + + mi_free_output (res); + } +} + +static const struct cmd +{ + const char *name; + void (*func) (mi_h *h, const char *cmd); +} cmds[] = +{ + { "q", quit_command }, + { "qu", quit_command }, + { "qui", quit_command }, + { "quit", quit_command }, +}; + +static void +executecommand (mi_h *h, const char *cmd) +{ + const char *start, *end, *cs; + const struct cmd *cmdp; + + cs = cmd; + while (isspace (*cs)) + cs++; + start = cs; + while (isalnum (*cs)) + cs++; + end = 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); + + 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); + + gdb_done (h, cmd); + xfree (cmd); +} + +static void +gdb_set_bool (mi_h *h, const char *setting, bool value) +{ + gdb_set_string (h, setting, value ? "on" : "off"); +} + +static char * +gdb_show_string (mi_h *h, const char *setting) +{ + mi_output *res; + char *retval; + + mi_send (h, "-gdb-show %s\n", setting); + res = mi_get_response_blk (h); + gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE + && res->c != NULL && res->c->next == NULL + && res->c->type == t_const && strcmp (res->c->var, "value") == 0); + retval = xstrdup (res->c->v.cstr); + mi_free_output (res); + return retval; +} + +static int +gdb_show_int (mi_h *h, const char *setting) +{ + char *string = gdb_show_string (h, setting); + long l; + int retval; + char *end; + + errno = 0; + retval = l = strtol (string, &end, 10); + gdb_assert (errno == 0 && (end == NULL || *end == '\0') && retval == l); + xfree (string); + return retval; +} + +static bool +gdb_show_bool (mi_h *h, const char *setting) +{ + char *string = gdb_show_string (h, setting); + bool retval; + + retval = strcmp (string, "on") == 0; + gdb_assert (retval || strcmp (string, "off") == 0); + xfree (string); + return retval; +} + int main (int argc, char **argv) { @@ -45,37 +261,40 @@ main (int argc, char **argv) if (h == NULL) fatal ("Cannot connect to GDB"); + on_exit (h_disconnect, h); + mi_set_console_cb (h, console_cb, NULL); +// mi_set_to_gdb_cb (h, to_gdb_cb, NULL); +// mi_set_from_gdb_cb (h, from_gdb_cb, NULL); - for (;;) + if (gdb_show_bool (h, "history save")) { - mi_output *rec, *res; + int history_size = gdb_show_int (h, "history size"); + char *history_filename = gdb_show_string (h, "history filename"); + + gdb_set_bool (h, "history save", false); + stifle_history (history_size); + read_history (history_filename); + on_exit (history_save, history_filename); + /* Do not free HISTORY_FILENAME. */ + } + for (;;) + { if (ex_used < ex_count) { - cmd = strdup (ex[ex_used++]); + cmd = xstrdup (ex[ex_used++]); printf ("(gdb) %s\n", cmd); } else { cmd = readline ("(gdb) "); if (cmd == NULL) - cmd = strdup ("quit"); + cmd = xstrdup ("quit"); + else + add_history (cmd); } - - mi_send (h, "-interpreter-exec console \"%s\"\n", cmd); - free (cmd); - - res = mi_get_response_blk (h); - if (res == NULL) - fatal ("mi_get_response_blk == NULL"); - - rec = mi_get_rrecord (res); - if (rec == NULL) - fatal ("mi_get_rrecord == NULL"); - if (rec->tclass != MI_CL_DONE) - fatal ("mi_get_rrecord != MI_CL_DONE"); - - mi_free_output (res); + executecommand (h, cmd); + xfree (cmd); } }