From: Jan Kratochvil Date: Fri, 10 Aug 2012 12:57:16 +0000 (+0200) Subject: +basic completer X-Git-Url: https://git.jankratochvil.net/?p=gdbmicli.git;a=commitdiff_plain;h=86e4d1e57b58b933f751e49d6eaaa0cf4cd6b8ea +basic completer --- diff --git a/main.c b/main.c index c43df32..54360b3 100644 --- a/main.c +++ b/main.c @@ -9,16 +9,20 @@ #include "ansidecl.h" #include "mi_gdb.h" +#define fatal(fmt...) fatal_func (__FILE__, __LINE__, __PRETTY_FUNCTION__, fmt) #define gdb_assert assert +#define gdb_assert_not_reached(msg) fatal ("%s", (msg)) static ATTRIBUTE_NORETURN void -fatal (const char *fmt, ...) +fatal_func (const char *file, int line, const char *func, const char *fmt, ...) { va_list ap; + fprintf (stderr, "%s:%d:%s:", file, line, func); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); + fputc ('\n', stderr); raise (SIGABRT); exit (EXIT_FAILURE); } @@ -34,6 +38,28 @@ xstrdup (const char *s) return retval; } +static void * +xmalloc (size_t size) +{ + void *p; + + gdb_assert (size != 0); + p = malloc (size); + gdb_assert (p != NULL); + return p; +} + +static void * +xrealloc (void *p, size_t size) +{ + if (p == NULL) + return xmalloc (size); + gdb_assert (size != 0); + p = realloc (p, size); + gdb_assert (p != NULL); + return p; +} + static void xfree (void *p) { @@ -122,6 +148,7 @@ default_command (mi_h *h, const char *cmd) count--; break; case MI_CL_ERROR: + count--; gdb_assert (rec->c->type == t_const); puts (rec->c->v.cstr); break; @@ -237,6 +264,90 @@ gdb_show_bool (mi_h *h, const char *setting) return retval; } +static mi_h *completion_entry_function_h; + +static char **completion_entry_function_data; +static size_t completion_entry_function_data_used; +static size_t completion_entry_function_data_allocated; + +static void +completion_entry_function_console_cb (const char *str, void *data) +{ + int line_start = (intptr_t) data; + const char *cs; + char *s; + + if (completion_entry_function_data_used + == completion_entry_function_data_allocated) + { + if (completion_entry_function_data_allocated > 0) + completion_entry_function_data_allocated *= 2; + else + completion_entry_function_data_allocated = 0x100; + completion_entry_function_data = xrealloc (completion_entry_function_data, + (sizeof (*completion_entry_function_data) + * completion_entry_function_data_allocated)); + } + + cs = strchr (str, '\n'); + if (cs == NULL || cs[1] != '\0') + fatal ("Invalid GDB data: %s", str); + + if (strncmp (rl_line_buffer, str, rl_point) != 0) + fatal ("Completion GDB data do not match, have \"%.*s\", got \"%.*s\".", + (int) rl_point, rl_line_buffer, (int) (cs - str), str); + + s = xmalloc (cs - str - line_start + 1); + memcpy (s, &str[line_start], cs - str - line_start); + s[cs - str - line_start] = '\0'; + completion_entry_function_data[completion_entry_function_data_used++] = s; +} + +static char * +completion_entry_function (const char *text, int matches) +{ + mi_h *h = completion_entry_function_h; + + gdb_assert (matches >= 0); + if (matches == 0) + { + mi_output *res; + int line_start; + + while (completion_entry_function_data_used) + xfree (completion_entry_function_data + [--completion_entry_function_data_used]); + xfree (completion_entry_function_data); + completion_entry_function_data = NULL; + completion_entry_function_data_used = 0; + completion_entry_function_data_allocated = 0; + + gdb_assert (rl_point >= 0); + gdb_assert (strlen (rl_line_buffer) >= rl_point); + gdb_assert (strlen (text) <= rl_point); + line_start = rl_point - strlen (text); + gdb_assert (strncmp (text, &rl_line_buffer[line_start], + strlen (text)) == 0); + mi_send (h, "-interpreter-exec console \"complete %.*s\"\n", + (int) rl_point, rl_line_buffer); + + mi_set_console_cb (h, completion_entry_function_console_cb, + (void *) (intptr_t) line_start); + 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); + mi_set_console_cb (h, console_cb, NULL); + } + + if (matches < completion_entry_function_data_used) + return xstrdup (completion_entry_function_data[matches]); + else if (matches == completion_entry_function_data_used) + return NULL; + else + gdb_assert_not_reached ("too many matches"); +} + int main (int argc, char **argv) { @@ -267,6 +378,10 @@ main (int argc, char **argv) // mi_set_to_gdb_cb (h, to_gdb_cb, NULL); // mi_set_from_gdb_cb (h, from_gdb_cb, NULL); + completion_entry_function_h = h; + rl_completion_entry_function = completion_entry_function; + rl_readline_name = "gdb"; + if (gdb_show_bool (h, "history save")) { int history_size = gdb_show_int (h, "history size");