Add missing files from last commit :-(

This commit is contained in:
Andrew Cagney 2003-02-06 05:30:17 +00:00
parent 92851186c3
commit 4a8f6654af
6 changed files with 1141 additions and 1 deletions

View File

@ -145,7 +145,7 @@ TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@
#
SUBDIR_CLI_OBS = \
cli-dump.o \
cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o
cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o \
cli-interp.o
SUBDIR_CLI_SRCS = \
cli/cli-dump.c \

138
gdb/cli/cli-interp.c Normal file
View File

@ -0,0 +1,138 @@
/* CLI Definitions for GDB, the GNU debugger.
Copyright 2002, 2003 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"
#include "top.h" /* for "execute_command" */
#include "gdb_string.h"
struct ui_out *cli_uiout;
/* These are the ui_out and the interpreter for the console interpreter. */
/* Longjmp-safe wrapper for "execute_command" */
static int do_captured_execute_command (struct ui_out *uiout, void *data);
static enum gdb_rc safe_execute_command (struct ui_out *uiout, char *command,
int from_tty);
struct captured_execute_command_args
{
char *command;
int from_tty;
};
/* These implement the cli out interpreter: */
static void *
cli_interpreter_init (void)
{
return NULL;
}
static int
cli_interpreter_resume (void *data)
{
/*sync_execution = 1; */
gdb_setup_readline ();
return 1;
}
static int
cli_interpreter_suspend (void *data)
{
gdb_disable_readline ();
return 1;
}
/* Don't display the prompt if we are set quiet. */
static int
cli_interpreter_display_prompt_p (void *data)
{
if (interp_quiet_p (NULL))
return 0;
else
return 1;
}
static int
cli_interpreter_exec (void *data, const char *command_str)
{
int result;
struct ui_file *old_stream;
/* FIXME: cagney/2003-02-01: Need to const char *propogate
safe_execute_command. */
char *str = strcpy (alloca (strlen (command_str) + 1), command_str);
/* gdb_stdout could change between the time cli_uiout was initialized
and now. Since we're probably using a different interpreter which has
a new ui_file for gdb_stdout, use that one instead of the default.
It is important that it gets reset everytime, since the user could
set gdb to use a different interpreter. */
old_stream = cli_out_set_stream (cli_uiout, gdb_stdout);
result = safe_execute_command (cli_uiout, str, 1);
cli_out_set_stream (cli_uiout, old_stream);
return result;
}
static int
do_captured_execute_command (struct ui_out *uiout, void *data)
{
struct captured_execute_command_args *args =
(struct captured_execute_command_args *) data;
execute_command (args->command, args->from_tty);
return GDB_RC_OK;
}
static enum gdb_rc
safe_execute_command (struct ui_out *uiout, char *command, int from_tty)
{
struct captured_execute_command_args args;
args.command = command;
args.from_tty = from_tty;
return catch_exceptions (uiout, do_captured_execute_command, &args,
NULL, RETURN_MASK_ALL);
}
/* standard gdb initialization hook */
void
_initialize_cli_interp (void)
{
static const struct interp_procs procs = {
cli_interpreter_init, /* init_proc */
cli_interpreter_resume, /* resume_proc */
cli_interpreter_suspend, /* suspend_proc */
cli_interpreter_exec, /* exec_proc */
cli_interpreter_display_prompt_p /* prompt_proc_p */
};
struct interp *cli_interp;
/* Create a default uiout builder for the CLI. */
cli_uiout = cli_out_new (gdb_stdout);
cli_interp = interp_new (INTERP_CONSOLE, NULL, cli_uiout, &procs);
interp_add (cli_interp);
}

484
gdb/interps.c Normal file
View File

@ -0,0 +1,484 @@
/* Manages interpreters for GDB, the GNU debugger.
Copyright 2000, 2002, 2003 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. */
#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"
#include "gdb-events.h"
#include "gdb_assert.h"
#include "top.h" /* For command_loop. */
struct interp
{
/* This is the name in "-i=" and set interpreter. */
const char *name;
/* Interpreters are stored in a linked list, this is the next
one... */
struct interp *next;
/* This is a cookie that an instance of the interpreter can use.
This is a bit confused right now as the exact initialization
sequence for it, and how it relates to the interpreter's uiout
object is a bit confused. */
void *data;
/* Has the init_proc been run? */
int inited;
/* 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 ui_out *interpreter_out;
const struct interp_procs *procs;
int quiet_p;
};
/* Functions local to this file. */
static void initialize_interps (void);
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 interp *interp_list = NULL;
static struct interp *current_interpreter = NULL;
static int interpreter_initialized = 0;
/* interp_new - This allocates space for a new interpreter,
fills the fields from the inputs, and returns a pointer to the
interpreter. */
struct interp *
interp_new (const char *name, void *data, struct ui_out *uiout,
const struct interp_procs *procs)
{
struct interp *new_interp;
new_interp = XMALLOC (struct interp);
new_interp->name = xstrdup (name);
new_interp->data = data;
new_interp->interpreter_out = uiout;
new_interp->quiet_p = 0;
new_interp->procs = procs;
new_interp->inited = 0;
return new_interp;
}
/* Add interpreter INTERP to the gdb interpreter list. The
interpreter must not have previously been added. */
void
interp_add (struct interp *interp)
{
if (!interpreter_initialized)
initialize_interps ();
gdb_assert (interp_lookup (interp->name) == NULL);
interp->next = interp_list;
interp_list = interp;
}
/* 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
interp_set (struct interp *interp)
{
struct interp *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)
{
interp->data = interp->procs->init_proc ();
}
interp->inited = 1;
}
/* Clear out any installed interpreter hooks/event handlers. */
clear_interpreter_hooks ();
if (interp->procs->resume_proc != NULL
&& (!interp->procs->resume_proc (interp->data)))
{
if (!interp_set (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 (!interp_quiet_p (interp))
{
sprintf (buffer, "Switching to interpreter \"%.24s\".\n",
interp->name);
ui_out_text (uiout, buffer);
}
display_gdb_prompt (NULL);
}
return 1;
}
/* interp_lookup - Looks up the interpreter for NAME. If no such
interpreter exists, return NULL, otherwise return a pointer to the
interpreter. */
struct interp *
interp_lookup (const char *name)
{
struct interp *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 ui_out *
interp_ui_out (struct interp *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
current_interp_named_p (const char *interp_name)
{
if (current_interpreter)
return (strcmp (current_interpreter->name, interp_name) == 0);
return 0;
}
/* This is called in display_gdb_prompt. If the proc returns a zero
value, display_gdb_prompt will return without displaying the
prompt. */
int
current_interp_display_prompt_p (void)
{
if (current_interpreter == NULL
|| current_interpreter->procs->prompt_proc_p == NULL)
return 0;
else
return current_interpreter->procs->prompt_proc_p (current_interpreter->
data);
}
/* Run the current command interpreter's main loop. */
void
current_interp_command_loop (void)
{
/* Somewhat messy. For the moment prop up all the old ways of
selecting the command loop. `command_loop_hook' should be
deprecated. */
if (command_loop_hook != NULL)
command_loop_hook ();
else if (current_interpreter != NULL
&& current_interpreter->procs->command_loop_proc != NULL)
current_interpreter->procs->command_loop_proc (current_interpreter->data);
else
command_loop ();
}
int
interp_quiet_p (struct interp *interp)
{
if (interp != NULL)
return interp->quiet_p;
else
return current_interpreter->quiet_p;
}
int
interp_set_quiet (struct interp *interp, int quiet)
{
int old_val = interp->quiet_p;
interp->quiet_p = quiet;
return old_val;
}
/* interp_exec - This executes COMMAND_STR in the current
interpreter. */
int
interp_exec_p (struct interp *interp)
{
return interp->procs->exec_proc != NULL;
}
int
interp_exec (struct interp *interp, const char *command_str)
{
if (interp->procs->exec_proc != NULL)
{
return interp->procs->exec_proc (interp->data, command_str);
}
return 0;
}
/* 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;
clear_gdb_event_hooks ();
}
/* 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... */
}
void
interpreter_exec_cmd (char *args, int from_tty)
{
struct interp *old_interp, *interp_to_use;
char **prules = NULL;
char **trule = NULL;
unsigned int nrules;
unsigned int i;
int old_quiet, use_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 = current_interpreter;
interp_to_use = interp_lookup (prules[0]);
if (interp_to_use == NULL)
error ("Could not find interpreter \"%s\".", prules[0]);
/* Temporarily set interpreters quiet */
old_quiet = interp_set_quiet (old_interp, 1);
use_quiet = interp_set_quiet (interp_to_use, 1);
if (!interp_set (interp_to_use))
error ("Could not switch to interpreter \"%s\".", prules[0]);
for (i = 1; i < nrules; i++)
{
if (!interp_exec (interp_to_use, prules[i]))
{
interp_set (old_interp);
interp_set_quiet (interp_to_use, old_quiet);
error ("error in command: \"%s\".", prules[i]);
break;
}
}
interp_set (old_interp);
interp_set_quiet (interp_to_use, use_quiet);
interp_set_quiet (old_interp, old_quiet);
}
/* List the possible interpreters which could complete the given text. */
static char **
interpreter_completer (char *text, char *word)
{
int alloced = 0;
int textlen;
int num_matches;
char **matches;
struct interp *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 "interpreter-exec" command. */
void
_initialize_interpreter (void)
{
struct cmd_list_element *c;
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);
}

73
gdb/interps.h Normal file
View File

@ -0,0 +1,73 @@
/* Manages interpreters for GDB, the GNU debugger.
Copyright 2000, 2002, 2003 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 INTERPS_H
#define INTERPS_H
struct ui_out;
struct interp;
extern int interp_resume (struct interp *interp);
extern int interp_suspend (struct interp *interp);
extern int interp_prompt_p (struct interp *interp);
extern int interp_exec_p (struct interp *interp);
extern int interp_exec (struct interp *interp, const char *command);
extern int interp_quiet_p (struct interp *interp);
typedef void *(interp_init_ftype) (void);
typedef int (interp_resume_ftype) (void *data);
typedef int (interp_suspend_ftype) (void *data);
typedef int (interp_prompt_p_ftype) (void *data);
typedef int (interp_exec_ftype) (void *data, const char *command);
typedef int (interp_command_loop_ftype) (void *data);
struct interp_procs
{
interp_init_ftype *init_proc;
interp_resume_ftype *resume_proc;
interp_suspend_ftype *suspend_proc;
interp_exec_ftype *exec_proc;
interp_prompt_p_ftype *prompt_proc_p;
interp_command_loop_ftype *command_loop_proc;
};
extern struct interp *interp_new (const char *name, void *data,
struct ui_out *uiout,
const struct interp_procs *procs);
extern void interp_add (struct interp *interp);
extern int interp_set (struct interp *interp);
extern struct interp *interp_lookup (const char *name);
extern struct ui_out *interp_ui_out (struct interp *interp);
extern int current_interp_named_p (const char *name);
extern int current_interp_display_prompt_p (void);
extern void current_interp_command_loop (void);
extern void clear_interpreter_hooks ();
/* well-known interpreters */
#define INTERP_CONSOLE "console"
#define INTERP_MI1 "mi1"
#define INTERP_MI "mi"
#endif

412
gdb/mi/mi-interp.c Normal file
View File

@ -0,0 +1,412 @@
/* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
Copyright 2002, 2003 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 "gdb_string.h"
#include "interps.h"
#include "event-top.h"
#include "event-loop.h"
#include "inferior.h"
#include "ui-out.h"
#include "top.h"
#include "mi-main.h"
#include "mi-cmds.h"
#include "mi-out.h"
#include "mi-console.h"
struct mi_interp
{
/* MI's output channels */
struct ui_file *out;
struct ui_file *err;
struct ui_file *log;
struct ui_file *targ;
struct ui_file *event_channel;
/* This is the interpreter for the mi... */
struct interp *mi2_interp;
struct interp *mi1_interp;
struct interp *mi_interp;
};
/* These are the interpreter setup, etc. functions for the MI interpreter */
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 char *mi_interp_read_one_line_hook (char *prompt, int repeat,
char *anno);
static void mi2_command_loop (void);
static void mi1_command_loop (void);
static void mi_insert_notify_hooks (void);
static void mi_remove_notify_hooks (void);
static void *
mi_interpreter_init (void)
{
struct mi_interp *mi = XMALLOC (struct mi_interp);
/* 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);
/* Create MI channels */
mi->out = mi_console_file_new (raw_stdout, "~", '"');
mi->err = mi_console_file_new (raw_stdout, "&", '"');
mi->log = mi->err;
mi->targ = mi_console_file_new (raw_stdout, "@", '"');
mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
return mi;
}
static int
mi_interpreter_resume (void *data)
{
struct mi_interp *mi = data;
/* As per hack note in mi_interpreter_init, swap in the output channels... */
gdb_setup_readline ();
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->out;
/* Route error and log output through the MI */
gdb_stderr = mi->err;
gdb_stdlog = mi->log;
/* Route target output through the MI. */
gdb_stdtarg = mi->targ;
/* 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 (current_interp_named_p (INTERP_MI1))
command_loop_hook = mi1_command_loop;
else if (current_interp_named_p (INTERP_MI))
command_loop_hook = mi2_command_loop;
else
return 0;
return 1;
}
static int
mi_interpreter_suspend (void *data)
{
gdb_disable_readline ();
return 1;
}
static int
mi_interpreter_exec (void *data, const char *command)
{
char *tmp = alloca (strlen (command) + 1);
strcpy (tmp, command);
mi_execute_command_wrapper (tmp);
return 1;
}
/* Never display the default gdb prompt in mi case. */
static int
mi_interpreter_prompt_p (void *data)
{
return 0;
}
static 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 interp *interp_to_use;
enum mi_cmd_result result = MI_CMD_DONE;
int i;
struct interp_procs *procs;
if (argc < 2)
{
xasprintf (&mi_error_message,
"mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command");
return MI_CMD_ERROR;
}
interp_to_use = interp_lookup (argv[0]);
if (interp_to_use == NULL)
{
xasprintf (&mi_error_message,
"mi_cmd_interpreter_exec: could not find interpreter \"%s\"",
argv[0]);
return MI_CMD_ERROR;
}
if (!interp_exec_p (interp_to_use))
{
xasprintf (&mi_error_message,
"mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution",
argv[0]);
return MI_CMD_ERROR;
}
/* Insert the MI out hooks, making sure to also call the interpreter's hooks
if it has any. */
/* KRS: We shouldn't need this... Events should be installed and they should
just ALWAYS fire something out down the MI channel... */
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 (interp_exec (interp_to_use, argv[i]) < 0)
{
mi_error_last_message ();
result = MI_CMD_ERROR;
break;
}
xfree (buff);
do_exec_error_cleanups (ALL_CLEANUPS);
sync_execution = 0;
}
mi_remove_notify_hooks ();
/* 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;
}
/*
* 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)
{
query_hook = mi_interp_query_hook;
}
static void
mi_remove_notify_hooks ()
{
query_hook = NULL;
}
static int
mi_interp_query_hook (const char *ctlstr, va_list ap)
{
return 1;
}
static 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
mi1_command_loop (void)
{
mi_command_loop (1);
}
static void
mi2_command_loop (void)
{
mi_command_loop (2);
}
static void
mi_command_loop (int mi_version)
{
#if 0
/* 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;
#endif
/* 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)
{
static const struct interp_procs procs =
{
mi_interpreter_init, /* init_proc */
mi_interpreter_resume, /* resume_proc */
mi_interpreter_suspend, /* suspend_proc */
mi_interpreter_exec, /* exec_proc */
mi_interpreter_prompt_p /* prompt_proc_p */
};
/* Create MI1 interpreter */
interp_add (interp_new (INTERP_MI1, NULL, mi_out_new (1), &procs));
interp_add (interp_new (INTERP_MI, NULL, mi_out_new (3), &procs));
}

33
gdb/mi/mi-main.h Normal file
View File

@ -0,0 +1,33 @@
/* MI Internal Functions for GDB, the GNU debugger.
Copyright 2003 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_MAIN_H
#define MI_MAIN_H
extern void mi_setup_architecture_data (void);
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);
#endif