]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add files mentioned in yesterday's changelog. Oops.
authorKeith Seitz <keiths@redhat.com>
Wed, 29 May 2002 20:03:17 +0000 (20:03 +0000)
committerKeith Seitz <keiths@redhat.com>
Wed, 29 May 2002 20:03:17 +0000 (20:03 +0000)
gdb/cli/cli-interp.c [new file with mode: 0644]
gdb/interps.c [new file with mode: 0644]
gdb/interps.h [new file with mode: 0644]
gdb/mi/mi-events.c [new file with mode: 0644]
gdb/mi/mi-interp.c [new file with mode: 0644]
gdb/mi/mi.h [new file with mode: 0644]

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
new file mode 100644 (file)
index 0000000..db66492
--- /dev/null
@@ -0,0 +1,114 @@
+/* CLI Definitions for GDB
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "interps.h"
+#include "wrapper.h"
+#include "event-top.h"
+#include "ui-out.h"
+#include "cli-out.h"
+
+/* Prototypes for the CLI Interpreter functions */
+
+int cli_interpreter_init (void *data);
+int cli_interpreter_resume (void *data);
+int cli_interpreter_do_one_event (void *data);
+int cli_interpreter_suspend (void *data);
+int cli_interpreter_delete (void *data);
+int cli_interpreter_exec (void *data, char *command_str);
+int cli_interpreter_display_prompt (void *data, char *new_prompt);
+
+/* These are the ui_out and the interpreter for the console interpreter. */
+struct ui_out *cli_uiout;
+struct gdb_interpreter *cli_interp;
+
+/* These implement the cli out interpreter: */
+
+int
+cli_interpreter_init (void *data)
+{
+  return 1;
+}
+
+int
+cli_interpreter_resume (void *data)
+{
+  /*sync_execution = 1;*/
+  gdb_setup_readline ();
+  return 1;
+}
+
+int
+cli_interpreter_do_one_event (void *data)
+{
+  return 1;
+}
+
+int
+cli_interpreter_suspend (void *data)
+{
+  gdb_disable_readline ();
+  return 1;
+}
+
+int
+cli_interpreter_delete (void *data)
+{
+  return 1;
+}
+
+int
+cli_interpreter_display_prompt (void *data, char *new_prompt)
+{
+  if (gdb_interpreter_is_quiet (NULL))
+    {
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+int
+cli_interpreter_exec (void *data, char *command_str)
+{
+  return gdb_execute_command (uiout, command_str, 0);
+}
+
+/* standard gdb initialization hook */
+void
+_initialize_cli_interp (void)
+{
+  struct gdb_interpreter_procs procs = {
+    cli_interpreter_init,      /* init_proc */
+    cli_interpreter_resume,    /* resume_proc */
+    cli_interpreter_do_one_event, /* do_one_event_proc */
+    cli_interpreter_suspend,   /* suspend_proc */
+    cli_interpreter_delete,    /* delete_proc */
+    cli_interpreter_exec,      /* exec_proc */
+    cli_interpreter_display_prompt /* prompt_proc */
+  };
+
+  cli_uiout = cli_out_new (gdb_stdout);
+  cli_interp = gdb_new_interpreter (GDB_INTERPRETER_CONSOLE, NULL, cli_uiout,
+                                   &procs);
+  gdb_add_interpreter (cli_interp);
+}
diff --git a/gdb/interps.c b/gdb/interps.c
new file mode 100644 (file)
index 0000000..4b9b901
--- /dev/null
@@ -0,0 +1,659 @@
+/* Manages interpreters for gdb.
+   Copyright 2000, 2002 Free Software Foundation, Inc.
+   Written by Jim Ingham <jingham@apple.com> of Apple Computer, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA. */
+
+/* This is just a first cut at separating out the "interpreter" functions
+   of gdb into self-contained modules.  There are a couple of open areas that
+   need to be sorted out:
+
+   1) The interpreter explicitly contains a UI_OUT, and can insert itself
+   into the event loop, but it doesn't explicitly contain hooks for readline.
+   I did this because it seems to me many interpreters won't want to use
+   the readline command interface, and it is probably simpler to just let
+   them take over the input in their resume proc.  
+
+   2) The event loop insertion is probably wrong.  I just inserted a 
+   do_one_event alongside gdb's do_one_event.  This probably will lead
+   to one or the other event loop getting starved.  It would be better
+   to provide conversion functions for the gdb file handlers, and when
+   an interpreter starts up, it grabs all the gdb created file handlers
+   and inserts them into its select.  This is more complicated, however,
+   and I have run out of time for now.
+*/
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "ui-out.h"
+#include "event-loop.h"
+#include "event-top.h"
+#include "interps.h"
+#include "completer.h"
+#include "gdb_string.h"
+
+struct gdb_interpreter
+{
+  char *name;                  /* This is the name in "-i=" and set interpreter. */
+  struct gdb_interpreter *next;        /* Interpreters are stored in a linked list, 
+                                  this is the next one... */
+  void *data;                  /* This is a cookie that the instance of the 
+                                  interpreter can use, for instance to call 
+                                  itself in hook functions */
+  int inited;                  /* Has the init_proc been run? */
+  struct ui_out *interpreter_out;      /* This is the ui_out used to collect 
+                                          results for this interpreter.  It can 
+                                          be a formatter for stdout, as is the 
+                                          case for the console & mi outputs, or it 
+                                          might be a result formatter. */
+  struct gdb_interpreter_procs procs;
+  int quiet_p;
+};
+
+/* Functions local to this file. */
+static void initialize_interps (void);
+
+static void set_interpreter_cmd (char *args, int from_tty,
+                                struct cmd_list_element *c);
+static void list_interpreter_cmd (char *args, int from_tty);
+static void do_set_interpreter (int not_an_fd);
+static char **interpreter_completer (char *text, char *word);
+
+/* The magic initialization routine for this module. */
+
+void _initialize_interpreter (void);
+
+/* Variables local to this file: */
+
+static struct gdb_interpreter *interp_list = NULL;
+static struct gdb_interpreter *current_interpreter = NULL;
+
+static int interpreter_initialized = 0;
+
+/* gdb_new_interpreter - This allocates space for a new interpreter,
+   fills the fields from the inputs, and returns a pointer to the
+   interpreter. */
+
+struct gdb_interpreter *
+gdb_new_interpreter (char *name,
+                    void *data,
+                    struct ui_out *uiout,
+                    struct gdb_interpreter_procs *procs)
+{
+  struct gdb_interpreter *new_interp;
+
+  new_interp =
+    (struct gdb_interpreter *) xmalloc (sizeof (struct gdb_interpreter));
+
+  new_interp->name = xstrdup (name);
+  new_interp->data = data;
+  new_interp->interpreter_out = uiout;
+  new_interp->quiet_p = 0;
+  new_interp->procs.init_proc = procs->init_proc;
+  new_interp->procs.resume_proc = procs->resume_proc;
+  new_interp->procs.do_one_event_proc = procs->do_one_event_proc;
+  new_interp->procs.suspend_proc = procs->suspend_proc;
+  new_interp->procs.delete_proc = procs->delete_proc;
+  new_interp->procs.exec_proc = procs->exec_proc;
+  new_interp->procs.prompt_proc = procs->prompt_proc;
+  new_interp->inited = 0;
+
+  return new_interp;
+}
+
+/* Add interpreter INTERP to the gdb interpreter list.  If an
+   interpreter of the same name is already on the list, then
+   the new one is NOT added, and the function returns 0.  Otherwise
+   it returns 1. */
+
+int
+gdb_add_interpreter (struct gdb_interpreter *interp)
+{
+  if (!interpreter_initialized)
+    initialize_interps ();
+
+  if (gdb_lookup_interpreter (interp->name) != NULL)
+    return 0;
+
+  interp->next = interp_list;
+  interp_list = interp;
+
+  return 1;
+}
+
+/* Looks for the interpreter INTERP in the interpreter list.  If it exists,
+   runs the delete_proc, and if this is successful, the INTERP is deleted from
+   the interpreter list and the function returns 1.  If the delete_proc fails, the
+   function returns -1 and the interpreter is NOT removed from the list.  If the
+   interp is not found, 0 is returned. */
+
+int
+gdb_delete_interpreter (struct gdb_interpreter *interp)
+{
+  struct gdb_interpreter *cur_ptr, *prev_ptr;
+
+  if (!interpreter_initialized)
+    {
+      ui_out_message (uiout, 0,
+                     "You can't delete an interp before you have added one!");
+      return -1;
+    }
+
+  if (interp_list == NULL)
+    {
+      ui_out_message (uiout, 0, "No interpreters to delete.");
+      return -1;
+    }
+
+  if (interp_list->next == NULL)
+    {
+      ui_out_message (uiout, 0, "You can't delete gdb's only intepreter.");
+      return -1;
+    }
+
+  for (cur_ptr = interp_list, prev_ptr = NULL;
+       cur_ptr != NULL; prev_ptr = cur_ptr, cur_ptr = cur_ptr->next)
+    {
+      if (cur_ptr == interp)
+       {
+         /* Can't currently delete the console interpreter... */
+         if (strcmp (interp->name, "console") == 0)
+           {
+             ui_out_message (uiout, 0,
+                             "You can't delete the console interpreter.");
+             return -1;
+           }
+
+         /* If the interpreter is the current interpreter, switch
+            back to the console interpreter */
+
+         if (interp == current_interpreter)
+           {
+             gdb_set_interpreter (gdb_lookup_interpreter ("console"));
+           }
+
+         /* Don't delete the interpreter if its delete proc fails */
+
+         if ((interp->procs.delete_proc != NULL)
+             && (!interp->procs.delete_proc (interp->data)))
+           return -1;
+
+         if (cur_ptr == interp_list)
+           interp_list = cur_ptr->next;
+         else
+           prev_ptr->next = cur_ptr->next;
+
+         break;
+       }
+    }
+
+  if (cur_ptr == NULL)
+    return 0;
+  else
+    return 1;
+}
+
+/* This sets the current interpreter to be INTERP.  If INTERP has not
+   been initialized, then this will also run the init proc.  If the
+   init proc is successful, return 1, if it fails, set the old
+   interpreter back in place and return 0.  If we can't restore the
+   old interpreter, then raise an internal error, since we are in
+   pretty bad shape at this point. */
+
+int
+gdb_set_interpreter (struct gdb_interpreter *interp)
+{
+  struct gdb_interpreter *old_interp = current_interpreter;
+  int first_time = 0;
+
+
+  char buffer[64];
+
+  if (current_interpreter != NULL)
+    {
+      do_all_continuations ();
+      ui_out_flush (uiout);
+      if (current_interpreter->procs.suspend_proc &&
+         !current_interpreter->procs.suspend_proc (current_interpreter->data))
+       {
+         error ("Could not suspend interpreter \"%s\"\n", current_interpreter->name);
+       }
+    }
+  else
+    {
+      first_time = 1;
+    }
+
+  current_interpreter = interp;
+
+  /* We use interpreter_p for the "set interpreter" variable, so we need
+     to make sure we have a malloc'ed copy for the set command to free. */
+  if (interpreter_p != NULL && strcmp (current_interpreter->name, interpreter_p) != 0)
+    {
+      xfree (interpreter_p);
+
+      interpreter_p = xstrdup (current_interpreter->name);
+    }
+
+  uiout = interp->interpreter_out;
+
+  /* Run the init proc.  If it fails, try to restore the old interp. */
+
+  if (!interp->inited)
+    {
+      if (interp->procs.init_proc != NULL)
+       {
+         if (!interp->procs.init_proc (interp->data))
+           {
+             if (!gdb_set_interpreter (old_interp))
+               internal_error (__FILE__, __LINE__,
+                               "Failed to initialize new interp \"%s\" %s",
+                               interp->name,
+                               "and could not restore old interp!\n");
+             return 0;
+           }
+         else
+           {
+             interp->inited = 1;
+           }
+       }
+      else
+       {
+         interp->inited = 1;
+       }
+    }
+
+  if (interp->procs.resume_proc != NULL
+      && (!interp->procs.resume_proc (interp->data)))
+    {
+      if (!gdb_set_interpreter (old_interp))
+       internal_error (__FILE__, __LINE__,
+                       "Failed to initialize new interp \"%s\" %s",
+                       interp->name, "and could not restore old interp!\n");
+      return 0;
+    }
+
+  /* Finally, put up the new prompt to show that we are indeed here. 
+     Also, display_gdb_prompt for the console does some readline magic
+     which is needed for the console interpreter, at least... */
+
+  if (!first_time)
+    {
+      if (!gdb_interpreter_is_quiet (interp))
+       {
+         sprintf (buffer, "Switching to interpreter \"%.24s\".\n",
+                  interp->name);
+         ui_out_text (uiout, buffer);
+       }
+      display_gdb_prompt (NULL);
+    }
+
+  return 1;
+}
+
+/*
+ * gdb_lookup_interpreter - Looks up the interpreter for NAME.  If
+ * no such interpreter exists, return NULL, otherwise return a pointer
+ * to the interpreter. 
+ */
+
+struct gdb_interpreter *
+gdb_lookup_interpreter (char *name)
+{
+  struct gdb_interpreter *interp;
+
+  if (name == NULL || strlen (name) == 0)
+    return NULL;
+
+  for (interp = interp_list; interp != NULL; interp = interp->next)
+    {
+      if (strcmp (interp->name, name) == 0)
+       return interp;
+    }
+
+  return NULL;
+}
+
+/* Returns the current interpreter. */
+
+struct gdb_interpreter *
+gdb_current_interpreter ()
+{
+  return current_interpreter;
+}
+
+struct ui_out *
+gdb_interpreter_ui_out (struct gdb_interpreter *interp)
+{
+  if (interp != NULL)
+    return interp->interpreter_out;
+
+  return current_interpreter->interpreter_out;
+}
+
+/* Returns true if the current interp is the passed in name. */
+int
+gdb_current_interpreter_is_named (char *interp_name)
+{
+  struct gdb_interpreter *current_interp = gdb_current_interpreter ();
+
+  if (current_interp)
+    return (strcmp (current_interp->name, interp_name) == 0);
+
+  return 0;
+}
+
+/* This is called in display_gdb_prompt.
+   If the current interpreter defines a prompt_proc, then that proc is 
+   run.  If the proc returns a non-zero value, display_gdb_prompt will
+   return without itself displaying the prompt. */
+
+int
+gdb_interpreter_display_prompt (char *new_prompt)
+{
+  if (current_interpreter->procs.prompt_proc == NULL)
+    return 0;
+  else
+    return current_interpreter->procs.prompt_proc (current_interpreter->data,
+                                                  new_prompt);
+}
+
+int
+gdb_interpreter_is_quiet (struct gdb_interpreter *interp)
+{
+  if (interp != NULL)
+    return interp->quiet_p;
+  else
+    return current_interpreter->quiet_p;
+}
+
+int
+gdb_interpreter_set_quiet (struct gdb_interpreter *interp, int quiet)
+{
+  int old_val = interp->quiet_p;
+  interp->quiet_p = quiet;
+  return old_val;
+}
+
+/* gdb_interpreter_exec - This executes COMMAND_STR in the current 
+   interpreter. */
+
+int
+gdb_interpreter_exec (char *command_str)
+{
+  if (current_interpreter->procs.exec_proc != NULL)
+    {
+      return current_interpreter->procs.exec_proc (current_interpreter->data,
+                                                  command_str);
+    }
+
+  return 0;
+}
+
+struct gdb_interpreter_procs *
+gdb_interpreter_get_procs (struct gdb_interpreter *interp)
+{
+  if (interp != NULL)
+    return &interp->procs;
+
+  return &current_interpreter->procs;
+}
+
+void *
+gdb_interpreter_get_data (struct gdb_interpreter *interp)
+{
+  if (interp != NULL)
+    return interp->data;
+
+  return current_interpreter->data;
+}
+
+int
+interpreter_do_one_event ()
+{
+  if (current_interpreter->procs.do_one_event_proc == NULL)
+    return 0;
+
+  return current_interpreter->procs.do_one_event_proc (current_interpreter->data);
+}
+
+/* A convenience routine that nulls out all the
+   common command hooks.  Use it when removing your interpreter in its 
+   suspend proc. */
+
+void
+clear_interpreter_hooks ()
+{
+  init_ui_hook = 0;
+  print_frame_info_listing_hook = 0;
+  /*print_frame_more_info_hook = 0; */
+  query_hook = 0;
+  warning_hook = 0;
+  create_breakpoint_hook = 0;
+  delete_breakpoint_hook = 0;
+  modify_breakpoint_hook = 0;
+  interactive_hook = 0;
+  registers_changed_hook = 0;
+  readline_begin_hook = 0;
+  readline_hook = 0;
+  readline_end_hook = 0;
+  register_changed_hook = 0;
+  memory_changed_hook = 0;
+  context_hook = 0;
+  target_wait_hook = 0;
+  call_command_hook = 0;
+  error_hook = 0;
+  error_begin_hook = 0;
+  command_loop_hook = 0;
+}
+
+/* This is a lazy init routine, called the first time
+   the interpreter module is used.  I put it here just in case, but I haven't
+   thought of a use for it yet.  I will probably bag it soon, since I don't
+   think it will be necessary. */
+
+static void
+initialize_interps (void)
+{
+  interpreter_initialized = 1;
+  /* Don't know if anything needs to be done here... */
+}
+
+/* set_interpreter_cmd - This implements "set interpreter foo". */
+
+static void
+set_interpreter_cmd (char *args, int from_tty, struct cmd_list_element *c)
+{
+  struct gdb_interpreter *interp_ptr;
+
+  dont_repeat ();
+
+  if (cmd_type (c) != set_cmd)
+    return;
+
+  interp_ptr = gdb_lookup_interpreter (interpreter_p);
+  if (interp_ptr != NULL)
+    {
+      if (!gdb_set_interpreter (interp_ptr))
+       error ("\nCould not switch to interpreter \"%s\", %s%s\".\n",
+              interp_ptr->name, "reverting to interpreter \"",
+              current_interpreter->name);
+    }
+  else
+    {
+      char *bad_name = interpreter_p;
+      interpreter_p = xstrdup (current_interpreter->name);
+      error ("Could not find interpreter \"%s\".", bad_name);
+    }
+}
+
+/* list_interpreter_cmd - This implements "info interpreters". */
+
+void
+list_interpreter_cmd (char *args, int from_tty)
+{
+  struct gdb_interpreter *interp_ptr;
+
+  ui_out_list_begin (uiout, "interpreters");
+  for (interp_ptr = interp_list; interp_ptr != NULL;
+       interp_ptr = interp_ptr->next)
+    {
+      ui_out_text (uiout, "  * ");
+      ui_out_field_string (uiout, "interpreter", interp_ptr->name);
+      ui_out_text (uiout, "\n");
+    }
+  ui_out_list_end (uiout);
+}
+
+void
+interpreter_exec_cmd (char *args, int from_tty)
+{
+  struct gdb_interpreter *old_interp, *interp_to_use;
+  char **prules = NULL;
+  char **trule = NULL;
+  unsigned int nrules;
+  unsigned int i;
+  int old_quiet;
+
+  prules = buildargv (args);
+  if (prules == NULL)
+    {
+      error ("unable to parse arguments");
+    }
+
+  nrules = 0;
+  if (prules != NULL)
+    {
+      for (trule = prules; *trule != NULL; trule++)
+       {
+         nrules++;
+       }
+    }
+
+  if (nrules < 2)
+    error ("usage: interpreter-exec <interpreter> [ <command> ... ]");
+
+  old_interp = gdb_current_interpreter ();
+
+  interp_to_use = gdb_lookup_interpreter (prules[0]);
+  if (interp_to_use == NULL)
+    error ("Could not find interpreter \"%s\".", prules[0]);
+
+  old_quiet = gdb_interpreter_set_quiet (interp_to_use, 1);
+
+  if (!gdb_set_interpreter (interp_to_use))
+    error ("Could not switch to interpreter \"%s\".", prules[0]);
+
+  for (i = 1; i < nrules; i++)
+    {
+      if (!gdb_interpreter_exec (prules[i]))
+       {
+         gdb_set_interpreter (old_interp);
+         gdb_interpreter_set_quiet (interp_to_use, old_quiet);
+         error
+           ("interpreter-exec: mi_interpreter_execute: error in command: \"%s\".",
+            prules[i]);
+         break;
+       }
+    }
+
+  gdb_set_interpreter (old_interp);
+  gdb_interpreter_set_quiet (interp_to_use, old_quiet);
+}
+
+/* List the possible interpreters which could complete the given text. */
+
+static char **
+interpreter_completer (char *text, char *word)
+{
+  int alloced, textlen;
+  int num_matches;
+  char **matches;
+  struct gdb_interpreter *interp;
+
+  /* We expect only a very limited number of interpreters, so just
+     allocate room for all of them. */
+  for (interp = interp_list; interp != NULL; interp = interp->next)
+    ++alloced;
+  matches = (char **) xmalloc (alloced * sizeof (char *));
+
+  num_matches = 0;
+  textlen = strlen (text);
+  for (interp = interp_list; interp != NULL; interp = interp->next)
+    {
+      if (strncmp (interp->name, text, textlen) == 0)
+       {
+         matches[num_matches] =
+           (char *) xmalloc (strlen (word) + strlen (interp->name) + 1);
+         if (word == text)
+           strcpy (matches[num_matches], interp->name);
+         else if (word > text)
+           {
+             /* Return some portion of interp->name */
+             strcpy (matches[num_matches], interp->name + (word - text));
+           }
+         else
+           {
+             /* Return some of text plus interp->name */
+             strncpy (matches[num_matches], word, text - word);
+             matches[num_matches][text - word] = '\0';
+             strcat (matches[num_matches], interp->name);
+           }
+         ++num_matches;
+       }
+    }
+
+  if (num_matches == 0)
+    {
+      xfree (matches);
+      matches = NULL;
+    }
+  else if (num_matches < alloced)
+    {
+      matches = (char **) xrealloc ((char *) matches, ((num_matches + 1)
+                                                      * sizeof (char *)));
+      matches[num_matches] = NULL;
+    }
+
+  return matches;
+}
+
+/* This just adds the "set interpreter" and "info interpreters" commands. */
+
+void
+_initialize_interpreter (void)
+{
+  struct cmd_list_element *c;
+
+  c = add_set_cmd ("interpreter", class_support,
+                  var_string,
+                  &interpreter_p, "Set the interpreter for gdb.", &setlist);
+  set_cmd_sfunc (c, set_interpreter_cmd);
+  add_show_from_set (c, &showlist);
+
+  add_cmd ("interpreters", class_support,
+          list_interpreter_cmd,
+          "List the interpreters currently available in gdb.", &infolist);
+
+  c = add_cmd ("interpreter-exec", class_support,
+              interpreter_exec_cmd,
+              "Execute a command in an interpreter.  It takes two arguments:\n\
+The first argument is the name of the interpreter to use.\n\
+The second argument is the command to execute.\n", &cmdlist);
+  set_cmd_completer (c, interpreter_completer);
+}
diff --git a/gdb/interps.h b/gdb/interps.h
new file mode 100644 (file)
index 0000000..05420b1
--- /dev/null
@@ -0,0 +1,74 @@
+/* Manages interpreters for gdb.
+   Copyright 2000,2002 Free Software Foundation, Inc.
+   Written by Jim Ingham <jingham@apple.com> of Apple Computer, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA. */
+
+#ifndef GDB_INTERPRETER_H
+#define GDB_INTERPRETER_H
+
+typedef int (*interp_init_ftype) (void *data);
+typedef int (*interp_resume_ftype) (void *data);
+typedef int (*interp_do_one_event_ftype) (void *data);
+typedef int (*interp_suspend_ftype) (void *data);
+typedef int (*interp_delete_ftype) (void *data);
+typedef int (*interp_prompt_ftype) (void *data, char *new_prompt);
+typedef int (*interp_exec_ftype) (void *data, char *command);
+
+struct ui_out;
+struct gdb_interpreter;
+
+struct gdb_interpreter_procs
+{
+  interp_init_ftype init_proc;
+  interp_resume_ftype resume_proc;
+  interp_do_one_event_ftype do_one_event_proc;
+  interp_suspend_ftype suspend_proc;
+  interp_delete_ftype delete_proc;
+  interp_exec_ftype exec_proc;
+  interp_prompt_ftype prompt_proc;
+};
+
+extern struct gdb_interpreter
+  *gdb_new_interpreter (char *name, void *data, struct ui_out *uiout,
+                       struct gdb_interpreter_procs *procs);
+
+extern int gdb_add_interpreter (struct gdb_interpreter *interp);
+extern int gdb_delete_interpreter (struct gdb_interpreter *interp);
+extern int gdb_set_interpreter (struct gdb_interpreter *interp);
+extern struct gdb_interpreter *gdb_lookup_interpreter (char *name);
+extern struct gdb_interpreter *gdb_current_interpreter ();
+extern struct ui_out *gdb_interpreter_ui_out (struct gdb_interpreter *interp);
+extern int gdb_current_interpreter_is_named (char *interp_name);
+extern int gdb_interpreter_exec (char *command_str);
+extern int gdb_interpreter_display_prompt (char *new_prompt);
+extern int gdb_interpreter_set_quiet (struct gdb_interpreter *interp,
+                                     int quiet);
+extern int gdb_interpreter_is_quiet (struct gdb_interpreter *interp);
+extern struct gdb_interpreter_procs *gdb_interpreter_get_procs (struct gdb_interpreter *interp);
+extern void *gdb_interpreter_get_data (struct gdb_interpreter *interp);
+extern int interpreter_do_one_event ();
+
+void clear_interpreter_hooks ();
+
+/* well-known interpreters */
+#define GDB_INTERPRETER_CONSOLE                "console"
+#define GDB_INTERPRETER_MI             "mi"
+#define GDB_INTERPRETER_MI0            "mi0"
+
+#endif /* GDB_INTERPRETER_H */
diff --git a/gdb/mi/mi-events.c b/gdb/mi/mi-events.c
new file mode 100644 (file)
index 0000000..1d942a4
--- /dev/null
@@ -0,0 +1,148 @@
+/* MI Event Handlers
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "ui-out.h"
+#include "interps.h"
+#include "gdb.h"
+#include "breakpoint.h"
+
+#include "mi.h"
+
+void 
+mi_interp_stack_changed_hook (void)
+{
+  struct ui_out *saved_ui_out = uiout;
+  struct mi_out *tmp_mi_out;
+
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    uiout = gdb_interpreter_ui_out (mi0_interp);
+  else
+    uiout = gdb_interpreter_ui_out (mi_interp);
+
+  ui_out_list_begin (uiout, "MI_HOOK_RESULT");
+  ui_out_field_string (uiout, "HOOK_TYPE", "stack_changed");
+  ui_out_list_end (uiout);
+  uiout = saved_ui_out;
+}
+
+void 
+mi_interp_frame_changed_hook (int new_frame_number)
+{
+  struct ui_out *saved_ui_out = uiout;
+  struct mi_out *tmp_mi_out;
+
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    uiout = gdb_interpreter_ui_out (mi0_interp);
+  else
+    uiout = gdb_interpreter_ui_out (mi_interp);
+
+  ui_out_list_begin (uiout, "MI_HOOK_RESULT");
+  ui_out_field_string (uiout, "HOOK_TYPE", "frame_changed");
+  ui_out_field_int (uiout, "frame", new_frame_number);
+  ui_out_list_end (uiout);
+  uiout = saved_ui_out;
+
+}
+
+void
+mi_interp_context_hook (int thread_id)
+{
+  struct ui_out *saved_ui_out = uiout;
+  struct mi_out *tmp_mi_out;
+
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    uiout = gdb_interpreter_ui_out (mi0_interp);
+  else
+    uiout = gdb_interpreter_ui_out (mi_interp);
+
+  ui_out_list_begin (uiout, "MI_HOOK_RESULT");
+  ui_out_field_string (uiout, "HOOK_TYPE", "thread_changed");
+  ui_out_field_int (uiout, "thread", thread_id);
+  ui_out_list_end (uiout);
+  uiout = saved_ui_out;
+}
+
+void
+mi_interp_create_breakpoint_hook (struct breakpoint *bpt)
+{
+  CORE_ADDR unusued_addr;
+  struct ui_out *saved_ui_out = uiout;
+  struct mi_out *tmp_mi_out;
+
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    uiout = gdb_interpreter_ui_out (mi0_interp);
+  else
+    uiout = gdb_interpreter_ui_out (mi_interp);
+
+  /* This is a little inefficient, but it probably isn't worth adding
+     a gdb_breakpoint_query that takes a bpt structure... */
+
+  ui_out_list_begin (uiout, "MI_HOOK_RESULT");
+  ui_out_field_string (uiout, "HOOK_TYPE", "breakpoint_create");
+  gdb_breakpoint_query (uiout, bpt->number);
+  ui_out_list_end (uiout);
+  uiout = saved_ui_out; 
+}
+
+void
+mi_interp_modify_breakpoint_hook (struct breakpoint *bpt)
+{
+
+  CORE_ADDR unusued_addr;
+  struct ui_out *saved_ui_out = uiout;
+  struct mi_out *tmp_mi_out;
+
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    uiout = gdb_interpreter_ui_out (mi0_interp);
+  else
+    uiout = gdb_interpreter_ui_out (mi_interp);
+
+  /* This is a little inefficient, but it probably isn't worth adding
+     a gdb_breakpoint_query that takes a bpt structure... */
+
+  ui_out_list_begin (uiout, "MI_HOOK_RESULT");
+  ui_out_field_string (uiout, "HOOK_TYPE", "breakpoint_modify");
+  gdb_breakpoint_query (uiout, bpt->number);
+  ui_out_list_end (uiout);
+  uiout = saved_ui_out; 
+}
+
+void
+mi_interp_delete_breakpoint_hook (struct breakpoint *bpt)
+{
+  CORE_ADDR unusued_addr;
+  struct ui_out *saved_ui_out = uiout;
+  struct mi_out *tmp_mi_out;
+
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    uiout = gdb_interpreter_ui_out (mi0_interp);
+  else
+    uiout = gdb_interpreter_ui_out (mi_interp);
+
+  /* This is a little inefficient, but it probably isn't worth adding
+     a gdb_breakpoint_query that takes a bpt structure... */
+
+  ui_out_list_begin (uiout, "MI_HOOK_RESULT");
+  ui_out_field_string (uiout, "HOOK_TYPE", "breakpoint_delete");
+  ui_out_field_int (uiout, "bkptno", bpt->number);
+  ui_out_list_end (uiout);
+  uiout = saved_ui_out; 
+}
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
new file mode 100644 (file)
index 0000000..9a91833
--- /dev/null
@@ -0,0 +1,500 @@
+/* MI Interpreter Definitions and Commands
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "interps.h"
+#include "event-top.h"
+#include "event-loop.h"
+#include "inferior.h"
+#include "ui-out.h"
+#include "top.h"
+
+#include "mi.h"
+#include "mi-cmds.h"
+#include "mi-out.h"
+#include "mi-console.h"
+
+/* MI's output channels */
+struct ui_file *mi_stdout;
+struct ui_file *mi_stderr;
+struct ui_file *mi_stdlog;
+struct ui_file *mi_stdtarg;
+
+/* This is the interpreter for the mi... */
+struct gdb_interpreter *mi0_interp;
+struct gdb_interpreter *mi_interp;
+
+/* These are the interpreter setup, etc. functions for the MI interpreter */
+static int mi_interpreter_init (void *data);
+static int mi_interpreter_resume (void *data);
+static int mi_interpreter_do_one_event (void *data);
+static int mi_interpreter_suspend (void *data);
+static int mi_interpreter_delete (void *data);
+static int mi_interpreter_prompt (void *data, char *new_prompt);
+
+static void mi_execute_command_wrapper (char *cmd);
+static void mi_command_loop (int mi_version);
+static char *mi_input (char *);
+
+/* These are hooks that we put in place while doing interpreter_exec
+   so we can report interesting things that happened "behind the mi's
+   back" in this command */
+static int mi_interp_query_hook (const char *ctlstr, va_list ap);
+static void mi_interp_stack_changed_hook (void);
+static char *mi_interp_read_one_line_hook (char *prompt, int repeat,
+                                          char *anno);
+
+static void mi0_command_loop (void);
+static void mi1_command_loop (void);
+
+static void mi_insert_notify_hooks (void);
+static void mi_remove_notify_hooks (void);
+
+int
+mi_interpreter_init (void *data)
+{
+  /* Why is this a part of the mi architecture? */
+
+  mi_setup_architecture_data ();
+
+  /* HACK: We need to force stdout/stderr to point at the console.  This avoids
+     any potential side effects caused by legacy code that is still
+     using the TUI / fputs_unfiltered_hook.  So we set up output channels for
+     this now, and swap them in when we are run. */
+
+  raw_stdout = stdio_fileopen (stdout);
+  /* Route normal output through the MIx */
+  mi_stdout = mi_console_file_new (raw_stdout, "~");
+  /* Route error and log output through the MI */
+  mi_stderr = mi_console_file_new (raw_stdout, "&");
+  mi_stdlog = mi_stderr;
+  /* Route target output through the MI. */
+  mi_stdtarg = mi_console_file_new (raw_stdout, "@");
+
+  return 1;
+}
+
+int
+mi_interpreter_resume (void *data)
+{
+  /* As per hack note in mi_interpreter_init, swap in the output channels... */
+
+  gdb_setup_readline ();
+  mi_register_gdbarch_swap ();
+
+  if (event_loop_p)
+    {
+      /* These overwrite some of the initialization done in
+         _intialize_event_loop. */
+      call_readline = gdb_readline2;
+      input_handler = mi_execute_command_wrapper;
+      add_file_handler (input_fd, stdin_event_handler, 0);
+      async_command_editing_p = 0;
+      /* FIXME: This is a total hack for now.  PB's use of the MI implicitly
+         relies on a bug in the async support which allows asynchronous
+         commands to leak through the commmand loop.  The bug involves
+         (but is not limited to) the fact that sync_execution was
+         erroneously initialized to 0.  Duplicate by initializing it
+         thus here... */
+      sync_execution = 0;
+    }
+
+  gdb_stdout = mi_stdout;
+  /* Route error and log output through the MI */
+  gdb_stderr = mi_stderr;
+  gdb_stdlog = mi_stdlog;
+  /* Route target output through the MI. */
+  gdb_stdtarg = mi_stdtarg;
+
+  /* Replace all the hooks that we know about.  There really needs to be a better way
+     of doing this... */
+  clear_interpreter_hooks ();
+
+  show_load_progress = mi_load_progress;
+
+  /* If we're _the_ interpreter, take control. */
+  if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0))
+    command_loop_hook = mi0_command_loop;
+  else if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI))
+    command_loop_hook = mi1_command_loop;
+  else
+    return 0;
+
+  return 1;
+}
+
+int
+mi_interpreter_suspend (void *data)
+{
+  gdb_disable_readline ();
+  return 1;
+}
+
+int
+mi_interpreter_delete (void *data)
+{
+  return 1;
+}
+
+int
+mi_interpreter_prompt (void *data, char *new_prompt)
+{
+  return 1;
+}
+
+int
+mi_do_one_event (void *data)
+{
+  return 1;
+}
+
+void
+mi_interpreter_exec_continuation (struct continuation_arg *arg)
+{
+  bpstat_do_actions (&stop_bpstat);
+  if (!target_executing)
+    {
+      fputs_unfiltered ("*stopped", raw_stdout);
+      mi_out_put (uiout, raw_stdout);
+      fputs_unfiltered ("\n", raw_stdout);
+      fputs_unfiltered ("(gdb) \n", raw_stdout);
+      gdb_flush (raw_stdout);
+      do_exec_cleanups (ALL_CLEANUPS);
+    }
+  else if (target_can_async_p ())
+    {
+      add_continuation (mi_interpreter_exec_continuation, NULL);
+    }
+}
+
+enum mi_cmd_result
+mi_cmd_interpreter_exec (char *command, char **argv, int argc)
+{
+  struct gdb_interpreter *old_interp, *interp_to_use;
+  enum mi_cmd_result result = MI_CMD_DONE;
+  int i, old_quiet;
+  struct gdb_interpreter_procs *procs;
+
+  if (argc < 2)
+    {
+      xasprintf (&mi_error_message,
+                "Wrong # or arguments, should be \"%s interp cmd <cmd ...>\".",
+                command);
+      return MI_CMD_ERROR;
+    }
+
+  old_interp = gdb_current_interpreter ();
+
+  interp_to_use = gdb_lookup_interpreter (argv[0]);
+  if (interp_to_use == NULL)
+    {
+      xasprintf (&mi_error_message,
+                "Could not find interpreter \"%s\".", argv[0]);
+      return MI_CMD_ERROR;
+    }
+
+  procs = gdb_interpreter_get_procs (interp_to_use);
+  if (!procs->exec_proc)
+    {
+      xasprintf (&mi_error_message,
+                "Interpreter \"%s\" does not support command execution.",
+                argv[0]);
+      return MI_CMD_ERROR;
+    }
+  old_quiet = gdb_interpreter_set_quiet (interp_to_use, 1);
+
+  if (!gdb_set_interpreter (interp_to_use))
+    {
+      xasprintf (&mi_error_message,
+                "Could not switch to interpreter \"%s\".", argv[0]);
+      return MI_CMD_ERROR;
+    }
+
+  /* Insert the MI out hooks, making sure to also call the interpreter's hooks
+     if it has any. */
+
+  mi_insert_notify_hooks ();
+
+  /* Now run the code... */
+
+  for (i = 1; i < argc; i++)
+    {
+      char *buff = NULL;
+      /* Do this in a cleaner way...  We want to force execution to be
+         asynchronous for commands that run the target.  */
+      if (target_can_async_p () && (strcmp (argv[0], "console") == 0))
+       {
+         int len = strlen (argv[i]);
+         buff = xmalloc (len + 2);
+         memcpy (buff, argv[i], len);
+         buff[len] = '&';
+         buff[len + 1] = '\0';
+       }
+
+      /* We had to set sync_execution = 0 for the mi (well really for Project
+         Builder's use of the mi - particularly so interrupting would work.
+         But for console commands to work, we need to initialize it to 1 -
+         since that is what the cli expects - before running the command,
+         and then set it back to 0 when we are done. */
+      sync_execution = 1;
+      if (!procs->exec_proc (gdb_interpreter_get_data (interp_to_use), argv[i]))
+       {
+         xasprintf (&mi_error_message,
+                    "mi_interpreter_execute: error in command: \"%s\".",
+                    argv[i]);
+
+         result = MI_CMD_ERROR;
+         break;
+       }
+      xfree (buff);
+      do_exec_error_cleanups (ALL_CLEANUPS);
+      sync_execution = 0;
+
+    }
+
+  /* Now do the switch... */
+
+  gdb_set_interpreter (old_interp);
+  mi_remove_notify_hooks ();
+  gdb_interpreter_set_quiet (interp_to_use, old_quiet);
+
+  /* Okay, now let's see if the command set the inferior going...
+     Tricky point - have to do this AFTER resetting the interpreter, since
+     changing the interpreter will clear out all the continuations for
+     that interpreter... */
+
+  if (target_can_async_p () && target_executing)
+    {
+      fputs_unfiltered ("^running\n", raw_stdout);
+      add_continuation (mi_interpreter_exec_continuation, NULL);
+    }
+
+  return result;
+}
+
+enum mi_cmd_result
+mi_cmd_interpreter_set (char *command, char **argv, int argc)
+{
+  struct gdb_interpreter *interp;
+  int result;
+
+  if (argc != 1)
+    {
+      xasprintf (&mi_error_message,
+                "mi_cmd_interpreter_set: wrong #of args, should be 1 ");
+      return MI_CMD_ERROR;
+    }
+  interp = gdb_lookup_interpreter (argv[0]);
+  if (interp == NULL)
+    {
+      xasprintf (&mi_error_message,
+                "mi_cmd_interpreter_set: could not find interpreter %s",
+                argv[0]);
+      return MI_CMD_ERROR;
+    }
+
+  if (interp != gdb_current_interpreter ())
+    {
+      result = gdb_set_interpreter (interp);
+      if (result != 1)
+       {
+         xasprintf (&mi_error_message,
+                    "mi_cmd_interpreter_set: error setting interpreter %s",
+                    argv[0]);
+         return MI_CMD_ERROR;
+       }
+    }
+
+  /* We don't want to put up the "done" and whatnot here, since we
+   * are going over to another interpreter.
+   */
+  return MI_CMD_QUIET;
+}
+
+/*
+ * mi_insert_notify_hooks - This inserts a number of hooks that are meant to produce
+ * async-notify ("=") MI messages while running commands in another interpreter
+ * using mi_interpreter_exec.  The canonical use for this is to allow access to
+ * the gdb CLI interpreter from within the MI, while still producing MI style output
+ * when actions in the CLI command change gdb's state.
+*/
+
+static void
+mi_insert_notify_hooks (void)
+{
+
+  create_breakpoint_hook = mi_interp_create_breakpoint_hook;
+  delete_breakpoint_hook = mi_interp_delete_breakpoint_hook;
+  modify_breakpoint_hook = mi_interp_modify_breakpoint_hook;
+  selected_frame_level_changed_hook = mi_interp_frame_changed_hook;
+  context_hook = mi_interp_context_hook;
+  query_hook = mi_interp_query_hook;
+}
+
+static void
+mi_remove_notify_hooks ()
+{
+  create_breakpoint_hook = NULL;
+  delete_breakpoint_hook = NULL;
+  modify_breakpoint_hook = NULL;
+  selected_frame_level_changed_hook = NULL;
+  context_hook = NULL;
+  query_hook = NULL;
+}
+
+int
+mi_interp_query_hook (const char *ctlstr, va_list ap)
+{
+  return 1;
+}
+
+char *
+mi_interp_read_one_line_hook (char *prompt, int repeat, char *anno)
+{
+  static char buff[256];
+  printf_unfiltered ("=read-one-line,prompt=\"%s\"\n", prompt);
+  gdb_flush (gdb_stdout);
+  (void) fgets (buff, sizeof (buff), stdin);
+  buff[(strlen (buff) - 1)] = 0;
+  return buff;
+}
+
+static void
+output_control_change_notification (char *notification)
+{
+  printf_unfiltered ("^");
+  printf_unfiltered ("%s\n", notification);
+  gdb_flush (gdb_stdout);
+}
+
+static void
+mi_execute_command_wrapper (char *cmd)
+{
+  mi_execute_command (cmd, stdin == instream);
+}
+
+static void
+mi0_command_loop (void)
+{
+  mi_command_loop (0);
+}
+
+static void
+mi1_command_loop (void)
+{
+  mi_command_loop (1);
+}
+
+static void
+mi_command_loop (int mi_version)
+{
+  /* HACK: Force stdout/stderr to point at the console.  This avoids
+     any potential side effects caused by legacy code that is still
+     using the TUI / fputs_unfiltered_hook */
+  raw_stdout = stdio_fileopen (stdout);
+  /* Route normal output through the MIx */
+  gdb_stdout = mi_console_file_new (raw_stdout, "~");
+  /* Route error and log output through the MI */
+  gdb_stderr = mi_console_file_new (raw_stdout, "&");
+  gdb_stdlog = gdb_stderr;
+  /* Route target output through the MI. */
+  gdb_stdtarg = mi_console_file_new (raw_stdout, "@");
+  /* HACK: Poke the ui_out table directly.  Should we be creating a
+     mi_out object wired up to the above gdb_stdout / gdb_stderr? */
+  uiout = mi_out_new (mi_version);
+  /* HACK: Override any other interpreter hooks.  We need to create a
+     real event table and pass in that. */
+  init_ui_hook = 0;
+  /* command_loop_hook = 0; */
+  print_frame_info_listing_hook = 0;
+  query_hook = 0;
+  warning_hook = 0;
+  create_breakpoint_hook = 0;
+  delete_breakpoint_hook = 0;
+  modify_breakpoint_hook = 0;
+  interactive_hook = 0;
+  registers_changed_hook = 0;
+  readline_begin_hook = 0;
+  readline_hook = 0;
+  readline_end_hook = 0;
+  register_changed_hook = 0;
+  memory_changed_hook = 0;
+  context_hook = 0;
+  target_wait_hook = 0;
+  call_command_hook = 0;
+  error_hook = 0;
+  error_begin_hook = 0;
+  show_load_progress = mi_load_progress;
+  /* Turn off 8 bit strings in quoted output.  Any character with the
+     high bit set is printed using C's octal format. */
+  sevenbit_strings = 1;
+  /* Tell the world that we're alive */
+  fputs_unfiltered ("(gdb) \n", raw_stdout);
+  gdb_flush (raw_stdout);
+  if (!event_loop_p)
+    simplified_command_loop (mi_input, mi_execute_command);
+  else
+    start_event_loop ();
+}
+
+static char *
+mi_input (char *buf)
+{
+  return gdb_readline (NULL);
+}
+
+void
+_initialize_mi_interp (void)
+{
+  struct gdb_interpreter_procs procs =
+    {
+      mi_interpreter_init,     /* init_proc */
+      mi_interpreter_resume,   /* resume_proc */
+      NULL,                    /* do_one_event_proc */
+      mi_interpreter_suspend,  /* suspend_proc */
+      mi_interpreter_delete,   /* delete_proc */
+      NULL,                    /* exec_proc */
+      mi_interpreter_prompt    /* prompt_proc */
+    };
+
+  if (mi0_interp == NULL)
+    {
+      mi0_interp =
+       gdb_new_interpreter (GDB_INTERPRETER_MI0, NULL, mi_out_new (0),
+                            &procs);
+      if (mi0_interp == NULL)
+       error
+         ("Couldn't allocate a new interpreter for the mi0 interpreter\n");
+      if (gdb_add_interpreter (mi0_interp) != 1)
+       error ("Couldn't add the mi0 interpreter to gdb.\n");
+    }
+
+  if (mi_interp == NULL)
+    {
+      mi_interp =
+       gdb_new_interpreter (GDB_INTERPRETER_MI, NULL, mi_out_new (1),
+                            &procs);
+      if (mi_interp == NULL)
+       error
+         ("Couldn't allocate a new interpreter for the mi interpreter\n");
+      if (gdb_add_interpreter (mi_interp) != 1)
+       error ("Couldn't add the mi interpreter to gdb.\n");
+    }
+}
diff --git a/gdb/mi/mi.h b/gdb/mi/mi.h
new file mode 100644 (file)
index 0000000..cc921e7
--- /dev/null
@@ -0,0 +1,43 @@
+/* MI Internal Functions
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef MI_H
+#define MI_H
+/* The mi interpreters. */
+struct gdb_interpreter;
+extern struct gdb_interpreter *mi_interp;
+extern struct gdb_interpreter *mi0_interp;
+
+extern void mi_setup_architecture_data (void);
+extern void mi_register_gdbarch_swap (void);
+
+/* Events/Hooks */
+extern void mi_load_progress (const char *section_name,
+                             unsigned long sent_so_far,
+                             unsigned long total_section,
+                             unsigned long total_sent,
+                             unsigned long grand_total);
+extern void mi_interp_create_breakpoint_hook (struct breakpoint *bpt);
+extern void mi_interp_delete_breakpoint_hook (struct breakpoint *bpt);
+extern void mi_interp_modify_breakpoint_hook (struct breakpoint *bpt);
+extern void mi_interp_frame_changed_hook (int new_frame_number);
+extern void mi_interp_context_hook (int thread_id);
+
+#endif /* MI_H */