b00bc3d34f4857e7aeec8feeb825815f0874e873
[gdbmicli.git] / main.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <signal.h>
5 #include <readline/readline.h>
6 #include <readline/history.h>
7 #include <assert.h>
8 #include <errno.h>
9 #include <setjmp.h>
10 #include "ansidecl.h"
11 #include "mi_gdb.h"
12
13 #define fatal(fmt...) fatal_func (__FILE__, __LINE__, __PRETTY_FUNCTION__, fmt)
14 #define gdb_assert assert
15 #define gdb_assert_not_reached(msg) fatal ("%s", (msg))
16 #define _(x) x
17
18 static ATTRIBUTE_NORETURN void
19 fatal_func (const char *file, int line, const char *func, const char *fmt, ...)
20 {
21   va_list ap;
22
23   fprintf (stderr, "%s:%d:%s:", file, line, func);
24   va_start (ap, fmt);
25   vfprintf (stderr, fmt, ap);
26   va_end (ap);
27   fputc ('\n', stderr);
28 raise (SIGABRT);
29   exit (EXIT_FAILURE);
30 }
31
32 static char *
33 xstrdup (const char *s)
34 {
35   char *retval;
36
37   gdb_assert (s != NULL);
38   retval = strdup (s);
39   gdb_assert (retval != NULL);
40   return retval;
41 }
42
43 static void *
44 xmalloc (size_t size)
45 {
46   void *p;
47
48   gdb_assert (size != 0);
49   p = malloc (size);
50   gdb_assert (p != NULL);
51   return p;
52 }
53
54 static void *
55 xrealloc (void *p, size_t size)
56 {
57   if (p == NULL)
58     return xmalloc (size);
59   gdb_assert (size != 0);
60   p = realloc (p, size);
61   gdb_assert (p != NULL);
62   return p;
63 }
64
65 static void
66 xfree (void *p)
67 {
68   free (p);
69 }
70
71 static char *
72 xstrprintf (const char *fmt, ...)
73 {
74   va_list ap;
75   char *retval;
76   int i;
77
78   va_start (ap, fmt);
79   i = vasprintf (&retval, fmt, ap);
80   va_end (ap);
81   gdb_assert (i > 0);
82   gdb_assert (i == strlen (retval));
83   return retval;
84 }
85
86 static void
87 console_cb (const char *str, void *data)
88 {
89   fputs (str, stdout);
90 }
91
92 static int
93 time_out_cb (void *data)
94 {
95   fatal ("GDB response has timed out");
96   /* NOTREACHED */
97   return 0;
98 }
99
100 static ATTRIBUTE_UNUSED void
101 to_gdb_cb (const char *str, void *data)
102 {
103   printf ("to_gdb: %s\n", str);
104 }
105
106 static ATTRIBUTE_UNUSED void
107 from_gdb_cb (const char *str, void *data)
108 {
109   printf ("from_gdb: %s\n", str);
110 }
111
112 static void
113 h_disconnect (int rc, void *arg)
114 {
115   mi_h *h = arg;
116
117   mi_disconnect (h);
118 }
119
120 static void
121 history_save (int rc, void *arg)
122 {
123   const char *history_filename = arg;
124
125   write_history (history_filename);
126 }
127
128 static void
129 default_command (mi_h *h, const char *cmd)
130 {
131   int count = 1;
132
133   gdb_assert (strchr (cmd, '\n') == 0);
134   mi_send (h, "-interpreter-exec console \"%s\"\n", cmd);
135
136   while (count > 0)
137     {
138       mi_output *rec, *res;
139
140       res = mi_get_response_blk (h);
141       gdb_assert (res != NULL);
142
143       for (rec = res; rec != NULL; rec = rec->next)
144         switch (rec->tclass)
145         {
146           case MI_CL_DONE:
147             count--;
148             break;
149           case MI_CL_RUNNING:
150             /* We do not get MI_CL_DONE here, wait for MI_CL_STOPPED.  */
151             break;
152           case MI_CL_STOPPED:
153             count--;
154             break;
155           case MI_CL_ERROR:
156             count--;
157             gdb_assert (rec->c->type == t_const);
158             puts (rec->c->v.cstr);
159             break;
160           default:
161             fatal ("mi_get_rrecord == MI_CL_??? (%d)", rec->tclass);
162         }
163
164       mi_free_output (res);
165     }
166 }
167
168 static void
169 quit_command (mi_h *h, const char *cmd)
170 {
171   exit (EXIT_SUCCESS);
172 }
173
174 static char *
175 mi_escape (const char *cs)
176 {
177   char *d, *retval = xmalloc (strlen (cs) * 2 + 1);
178
179   d = retval;
180   while (*cs)
181     {
182       if (*cs == '"' || *cs == '\\')
183         *d++ = '\\';
184       *d++ = *cs++;
185     }
186   *d = '\0';
187   return retval;
188 }
189
190 static void
191 gdb_done (mi_h *h, const char *command)
192 {
193   mi_output *res;
194
195   mi_send (h, "%s\n", command);
196   res = mi_get_response_blk (h);
197   gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
198               && res->c == NULL);
199   mi_free_output (res);
200 }
201
202 static jmp_buf gdb_readline_jmp_buf;
203
204 static void
205 gdb_readline_sigint_handler (int signum)
206 {
207   gdb_assert (signum == SIGINT);
208   longjmp (gdb_readline_jmp_buf, 1);
209 }
210
211 static char *
212 gdb_readline (const char *prompt)
213 {
214   char *retval;
215   sighandler_t saved_handler;
216   sigset_t mask;
217   int i;
218
219   i = sigprocmask (SIG_SETMASK, NULL, &mask);
220   assert (i == 0);
221   saved_handler = signal (SIGINT, gdb_readline_sigint_handler);
222   if (setjmp (gdb_readline_jmp_buf) != 0)
223     {
224       rl_free_line_state ();
225       rl_cleanup_after_signal ();
226
227       /* GDB prints this.  */
228       puts ("Quit");
229
230       i = sigprocmask (SIG_SETMASK, &mask, NULL);
231       assert (i == 0);
232     }
233   retval = readline (prompt);
234   saved_handler = signal (SIGINT, saved_handler);
235   gdb_assert (saved_handler == gdb_readline_sigint_handler);
236   return retval;
237 }
238
239 static void
240 commands_command_console_cb (const char *str, void *data)
241 {
242   char **strptr = data;
243
244   gdb_assert (*strptr == NULL);
245   *strptr = xstrdup (str);
246 }
247
248 static void
249 commands_command (mi_h *h, const char *cmd_param)
250 {
251   char *cmd = xstrdup ("");
252   size_t cmd_len = 0;
253   mi_output *res;
254   char *bpnum = NULL;
255   int nesting;
256
257   if (*cmd_param == '\0')
258     {
259       mi_set_console_cb (h, commands_command_console_cb, &bpnum);
260       gdb_done (h, "output $bpnum");
261       mi_set_console_cb (h, console_cb, NULL);
262       gdb_assert (bpnum != NULL);
263       cmd_param = bpnum;
264     }
265
266   printf (_("Type commands for breakpoint(s) %s, one per line.\n"
267             "End with a line saying just \"end\".\n"), cmd_param);
268
269   nesting = 0;
270   while (nesting >= 0)
271     {
272       char *prompt, *data, *data2, *start, *end;
273       size_t data2_len;
274       int do_nest = 0;
275
276       prompt = xstrprintf ("%*s>", (int) nesting);
277       data = gdb_readline (prompt);
278       xfree (prompt);
279       if (data == NULL)
280         data = xstrdup ("end");
281
282       for (start = data; isspace (*start); start++);
283       for (end = data + strlen (data); end > start && isspace (end[-1]); end--);
284       data2 = xmalloc (end - start + 1);
285       memcpy (data2, start, end - start);
286       data2[end - start] = '\0';
287       if (strcmp (data2, "python") == 0)
288         do_nest = 1;
289       if (strcmp (data2, "end") == 0)
290         do_nest = -1;
291       for (end = data2; *end && !isspace (*end); end++);
292       *end = '\0';
293
294       /* Here is a bug in GDB, it does not recognize command shortcuts.  */
295       if (strcmp (data2, "while") == 0 || strcmp (data2, "if") == 0
296           || strcmp (data2, "commands") == 0
297           || strcmp (data2, "while-stepping") == 0
298           || strcmp (data2, "stepping") == 0 || strcmp (data2, "ws") == 0)
299         do_nest = 1;
300       xfree (data2);
301
302       nesting += do_nest;
303       if (nesting < 0)
304         break;
305
306       data2 = mi_escape (data);
307       xfree (data);
308       data2_len = strlen (data2);
309       cmd = xrealloc (cmd, cmd_len + 2 + data2_len + 2);
310       cmd[cmd_len] = ' ';
311       cmd[cmd_len + 1] = '"';
312       memcpy (&cmd[cmd_len + 2], data2, data2_len);
313       cmd[cmd_len + 2 + data2_len] = '"';
314       cmd[cmd_len + 2 + data2_len + 1] = '\0';
315       cmd_len += 2 + data2_len + 1;
316       xfree (data2);
317     }
318
319   mi_send (h, "-break-commands %s%s\n", cmd_param, cmd);
320   xfree (cmd);
321   xfree (bpnum);
322
323   res = mi_get_response_blk (h);
324   gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
325               && res->c == NULL);
326   mi_free_output (res);
327 }
328
329 static const struct cmd
330 {
331   const char *name;
332   int min_shortcut;
333   void (*func) (mi_h *h, const char *cmd);
334 } cmds[] =
335 {
336   { "quit", 1, quit_command },
337   { "commands", 4, commands_command },
338 };
339
340 static void
341 executecommand (mi_h *h, const char *cmd)
342 {
343   const char *start, *end, *cs;
344   const struct cmd *cmdp;
345
346   cs = cmd;
347   while (isspace (*cs))
348     cs++;
349   start = cs;
350   while (isalnum (*cs))
351     cs++;
352   end = cs;
353   while (isspace (*cs))
354     cs++;
355
356   for (cmdp = cmds; cmdp < &cmds[LENGTH (cmds)]; cmdp++)
357     if (cmdp->min_shortcut <= end - start && end - start <= strlen (cmdp->name)
358         && strncmp (start, cmdp->name, end - start) == 0)
359       return cmdp->func (h, cs);
360
361   return default_command (h, cmd);
362 }
363
364 static void
365 gdb_set_string (mi_h *h, const char *setting, const char *value)
366 {
367   char *cmd = xstrprintf ("-gdb-set %s %s", setting, value);
368
369   gdb_done (h, cmd);
370   xfree (cmd);
371 }
372
373 static void
374 gdb_set_bool (mi_h *h, const char *setting, bool value)
375 {
376   gdb_set_string (h, setting, value ? "on" : "off");
377 }
378
379 static char *
380 gdb_show_string (mi_h *h, const char *setting)
381 {
382   mi_output *res;
383   char *retval;
384
385   mi_send (h, "-gdb-show %s\n", setting);
386   res = mi_get_response_blk (h);
387   gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
388               && res->c != NULL && res->c->next == NULL
389               && res->c->type == t_const && strcmp (res->c->var, "value") == 0);
390   retval = xstrdup (res->c->v.cstr);
391   mi_free_output (res);
392   return retval;
393 }
394
395 static int
396 gdb_show_int (mi_h *h, const char *setting)
397 {
398   char *string = gdb_show_string (h, setting);
399   long l;
400   int retval;
401   char *end;
402
403   errno = 0;
404   retval = l = strtol (string, &end, 10);
405   gdb_assert (errno == 0 && (end == NULL || *end == '\0') && retval == l);
406   xfree (string);
407   return retval;
408 }
409
410 static bool
411 gdb_show_bool (mi_h *h, const char *setting)
412 {
413   char *string = gdb_show_string (h, setting);
414   bool retval;
415
416   retval = strcmp (string, "on") == 0;
417   gdb_assert (retval || strcmp (string, "off") == 0);
418   xfree (string);
419   return retval;
420 }
421
422 static mi_h *completion_entry_function_h;
423
424 static char **completion_entry_function_data;
425 static size_t completion_entry_function_data_used;
426 static size_t completion_entry_function_data_allocated;
427
428 static void
429 completion_entry_function_console_cb (const char *str, void *data)
430 {
431   int line_start = (intptr_t) data;
432   const char *cs;
433   char *s;
434
435   if (completion_entry_function_data_used
436       == completion_entry_function_data_allocated)
437     {
438       if (completion_entry_function_data_allocated > 0)
439         completion_entry_function_data_allocated *= 2;
440       else
441         completion_entry_function_data_allocated = 0x100;
442       completion_entry_function_data = xrealloc (completion_entry_function_data,
443                                   (sizeof (*completion_entry_function_data)
444                                    * completion_entry_function_data_allocated));
445     }
446
447   cs = strchr (str, '\n');
448   if (cs == NULL || cs[1] != '\0')
449     fatal ("Invalid GDB data: %s", str);
450
451   if (strncmp (rl_line_buffer, str, rl_point) != 0)
452     fatal ("Completion GDB data do not match, have \"%.*s\", got \"%.*s\".",
453            (int) rl_point, rl_line_buffer, (int) (cs - str), str);
454
455   s = xmalloc (cs - str - line_start + 1);
456   memcpy (s, &str[line_start], cs - str - line_start);
457   s[cs - str - line_start] = '\0';
458   completion_entry_function_data[completion_entry_function_data_used++] = s;
459 }
460
461 static char *
462 completion_entry_function (const char *text, int matches)
463 {
464   mi_h *h = completion_entry_function_h;
465
466   gdb_assert (matches >= 0);
467   if (matches == 0)
468     {
469       mi_output *res;
470       int line_start;
471
472       while (completion_entry_function_data_used)
473         xfree (completion_entry_function_data
474                [--completion_entry_function_data_used]);
475       xfree (completion_entry_function_data);
476       completion_entry_function_data = NULL;
477       completion_entry_function_data_used = 0;
478       completion_entry_function_data_allocated = 0;
479
480       gdb_assert (rl_point >= 0);
481       gdb_assert (strlen (rl_line_buffer) >= rl_point);
482       gdb_assert (strlen (text) <= rl_point);
483       line_start = rl_point - strlen (text);
484       gdb_assert (strncmp (text, &rl_line_buffer[line_start],
485                            strlen (text)) == 0);
486       mi_send (h, "-interpreter-exec console \"complete %.*s\"\n",
487                (int) rl_point, rl_line_buffer);
488
489       mi_set_console_cb (h, completion_entry_function_console_cb,
490                          (void *) (intptr_t) line_start);
491       res = mi_get_response_blk (h);
492       gdb_assert (res != NULL && res->next == NULL && res->tclass == MI_CL_DONE
493                   && res->c == NULL);
494       mi_free_output (res);
495       mi_set_console_cb (h, console_cb, NULL);
496     }
497
498   if (matches < completion_entry_function_data_used)
499     return xstrdup (completion_entry_function_data[matches]);
500   else if (matches == completion_entry_function_data_used)
501     return NULL;
502   else
503     gdb_assert_not_reached ("too many matches");
504 }
505
506 extern char **mi_gdb_argv;
507 extern void (*mi_gdb_start_hook) (mi_h *h);
508
509 static void
510 start_hook (mi_h *h)
511 {
512   on_exit (h_disconnect, h);
513   mi_set_console_cb (h, console_cb, NULL);
514   mi_set_time_out_cb (h, time_out_cb, NULL);
515
516 //  mi_set_to_gdb_cb (h, to_gdb_cb, NULL);
517 //  mi_set_from_gdb_cb (h, from_gdb_cb, NULL);
518 }
519
520 int
521 main (int argc, char **argv)
522 {
523   mi_h *h;
524   mi_output *res;
525
526   setbuf (stdout, NULL);
527
528   mi_gdb_argv = xmalloc ((argc + 2) * sizeof (*mi_gdb_argv));
529   memcpy (&mi_gdb_argv[2], &argv[1], argc * sizeof (*mi_gdb_argv));
530   mi_gdb_argv[0] = "gdb";
531   mi_gdb_argv[1] = "--interpreter=mi";
532
533   mi_gdb_start_hook = start_hook;
534
535   h = mi_connect_local ();
536   if (h == NULL)
537     fatal ("Cannot connect to GDB");
538
539   /* First eat the prompt.  Then run empty command so that additional results
540      from -ex or -x during mi_connect_local are flushed.  */
541   res = mi_get_response_blk (h);
542   gdb_assert (res == NULL);
543   default_command (h, "echo");
544
545   completion_entry_function_h = h;
546   rl_completion_entry_function = completion_entry_function;
547   rl_readline_name = "gdb";        
548
549   if (gdb_show_bool (h, "history save"))
550     {
551       int history_size = gdb_show_int (h, "history size");
552       char *history_filename = gdb_show_string (h, "history filename");
553
554       gdb_set_bool (h, "history save", false);
555       stifle_history (history_size);
556       read_history (history_filename);
557       on_exit (history_save, history_filename);
558       /* Do not free HISTORY_FILENAME.  */
559     }
560
561   for (;;)
562     {
563       char *prompt, *cmd;
564       
565       prompt = gdb_show_string (h, "prompt");
566       cmd = gdb_readline (prompt);
567       xfree (prompt);
568
569       if (cmd == NULL)
570         cmd = xstrdup ("quit");
571       else
572         add_history (cmd);
573
574       executecommand (h, cmd);
575       xfree (cmd);
576     }
577 }