Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.263 diff -p -r1.263 Makefile.in *** Makefile.in 20 Sep 2002 18:14:49 -0000 1.263 --- Makefile.in 23 Sep 2002 19:37:36 -0000 *************** LIBICONV = @LIBICONV@ *** 145,155 **** # CLI sub directory definitons # SUBDIR_CLI_OBS = \ ! cli-dump.o \ ! cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o SUBDIR_CLI_SRCS = \ ! cli/cli-dump.c \ ! cli/cli-decode.c cli/cli-script.c cli/cli-cmds.c cli/cli-setshow.c \ cli/cli-utils.c SUBDIR_CLI_DEPS = SUBDIR_CLI_INITS = \ --- 145,155 ---- # CLI sub directory definitons # SUBDIR_CLI_OBS = \ ! cli-dump.o cli-decode.o \ ! cli-interp.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o SUBDIR_CLI_SRCS = \ ! cli/cli-dump.c cli/cli-decode.c \ ! cli/cli-interp.c cli/cli-script.c cli/cli-cmds.c cli/cli-setshow.c \ cli/cli-utils.c SUBDIR_CLI_DEPS = SUBDIR_CLI_INITS = \ *************** SUBDIR_CLI_UNINSTALL= *** 167,179 **** SUBDIR_MI_OBS = \ mi-out.o mi-console.o \ mi-cmds.o mi-cmd-var.o mi-cmd-break.o mi-cmd-stack.o \ ! mi-cmd-disas.o \ mi-main.o mi-parse.o mi-getopt.o SUBDIR_MI_SRCS = \ mi/mi-out.c mi/mi-console.c \ mi/mi-cmds.c \ mi/mi-cmd-var.c mi/mi-cmd-break.c mi/mi-cmd-stack.c \ ! mi/mi-cmd-disas.c \ mi/mi-main.c mi/mi-parse.c mi/mi-getopt.c SUBDIR_MI_DEPS = SUBDIR_MI_INITS = \ --- 167,179 ---- SUBDIR_MI_OBS = \ mi-out.o mi-console.o \ mi-cmds.o mi-cmd-var.o mi-cmd-break.o mi-cmd-stack.o \ ! mi-cmd-disas.o mi-events.o mi-interp.o \ mi-main.o mi-parse.o mi-getopt.o SUBDIR_MI_SRCS = \ mi/mi-out.c mi/mi-console.c \ mi/mi-cmds.c \ mi/mi-cmd-var.c mi/mi-cmd-break.c mi/mi-cmd-stack.c \ ! mi/mi-cmd-disas.c mi/mi-events.c mi/mi-interp.c \ mi/mi-main.c mi/mi-parse.c mi/mi-getopt.c SUBDIR_MI_DEPS = SUBDIR_MI_INITS = \ *************** SFILES = ada-exp.y ada-lang.c ada-typepr *** 540,546 **** findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \ inf-loop.c infcmd.c inflow.c infrun.c language.c \ kod.c kod-cisco.c \ ! ui-out.c cli-out.c \ varobj.c wrapper.c \ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ --- 540,546 ---- findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \ inf-loop.c infcmd.c inflow.c infrun.c language.c \ kod.c kod-cisco.c \ ! ui-out.c cli-out.c interps.c \ varobj.c wrapper.c \ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ *************** i386_tdep_h = i386-tdep.h $(osabi_h) *** 671,676 **** --- 671,677 ---- i387_tdep_h = i387-tdep.h inf_loop_h = inf-loop.h inferior_h = inferior.h $(breakpoint_h) $(target_h) + interps_h = interps.h jv_lang_h = jv-lang.h kod_h = kod.h language_h = language.h *************** cli_utils_h = $(srcdir)/cli/cli-utils.h *** 747,752 **** --- 748,754 ---- # gdb/mi/ headers # + mi_h = $(srcdir)/mi/mi.h mi_cmds_h = $(srcdir)/mi/mi-cmds.h mi_console_h = $(srcdir)/mi/mi-console.h mi_getopt_h = $(srcdir)/mi/mi-getopt.h *************** COMMON_OBS = version.o blockframe.o brea *** 841,847 **** dbxread.o coffread.o elfread.o \ dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \ c-lang.o f-lang.o \ ! ui-out.o cli-out.o \ varobj.o wrapper.o \ jv-lang.o jv-valprint.o jv-typeprint.o \ m2-lang.o p-lang.o p-typeprint.o p-valprint.o \ --- 843,849 ---- dbxread.o coffread.o elfread.o \ dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \ c-lang.o f-lang.o \ ! ui-out.o cli-out.o interps.o \ varobj.o wrapper.o \ jv-lang.o jv-valprint.o jv-typeprint.o \ m2-lang.o p-lang.o p-typeprint.o p-valprint.o \ *************** eval.o: eval.c $(defs_h) $(gdb_string_h) *** 1660,1666 **** event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \ $(gdb_string_h) event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \ ! $(terminal_h) $(event_loop_h) $(event_top_h) $(gdbcmd_h) exec.o: exec.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) $(gdbcmd_h) \ $(language_h) $(symfile_h) $(objfiles_h) $(completer_h) $(value_h) \ $(gdb_string_h) $(gdbcore_h) $(gdb_stat_h) $(xcoffsolib_h) --- 1662,1668 ---- event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \ $(gdb_string_h) event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \ ! $(terminal_h) $(event_loop_h) $(event_top_h) $(gdbcmd_h) $(interps_h) exec.o: exec.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) $(gdbcmd_h) \ $(language_h) $(symfile_h) $(objfiles_h) $(completer_h) $(value_h) \ $(gdb_string_h) $(gdbcore_h) $(gdb_stat_h) $(xcoffsolib_h) *************** inftarg.o: inftarg.c $(defs_h) $(frame_h *** 1809,1814 **** --- 1811,1818 ---- $(gdbcore_h) $(command_h) $(gdb_stat_h) $(gdb_wait_h) infttrace.o: infttrace.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ $(gdb_string_h) $(gdb_wait_h) $(command_h) $(gdbcore_h) + interps.o: interps.c $(defs_h) $(gdbcmd_h) $(ui_out_h) $(event_loop_h) \ + $(event_top_h) $(interps_h) $(gdb_h) $(wrapper_h) $(gdb_events_h) irix4-nat.o: irix4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) \ $(gregset_h) irix5-nat.o: irix5-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \ *************** cli-dump.o: $(srcdir)/cli/cli-dump.c $(d *** 2324,2329 **** --- 2328,2336 ---- $(cli_decode_h) $(cli_cmds_h) $(value_h) $(completer_h) \ $(cli_dump_h) $(gdb_assert_h) $(target_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-dump.c + cli-interp.o: $(srcdir)/cli/cli-interp.c $(defs_h) $(value_h) \ + $(wrapper_h) $(event_top_h) $(ui_out_h) $(cli_out_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-interp.c cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \ $(ui_out_h) $(gdb_string_h) $(top_h) $(cli_cmds_h) $(cli_decode_h) \ $(cli_script_h) *************** mi-cmds.o: $(srcdir)/mi/mi-cmds.c $(defs *** 2441,2449 **** --- 2448,2463 ---- mi-console.o: $(srcdir)/mi/mi-console.c $(defs_h) $(mi_console_h) \ $(gdb_string_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-console.c + mi-events.o: $(srcdir)/mi/mi-events.c $(defs_h) $(ui_out_h) $(interps_h) \ + $(gdb_h) $(breakpoint_h) $(mi_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-events.c mi-getopt.o: $(srcdir)/mi/mi-getopt.c $(defs_h) $(mi_getopt_h) \ $(gdb_string_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-getopt.c + mi-interp.o: $(srcdir)/mi/mi-interp.c $(defs_h) $(interps_h) \ + $(event_top_h) $(event_loop_h) $(inferior_h) $(ui_out_h) \ + $(top_h) $(mi_h) $(mi_cmds_h) $(mi_out_h) $(mi_console_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-interp.c mi-main.o: $(srcdir)/mi/mi-main.c $(defs_h) $(target_h) $(inferior_h) \ $(gdb_string_h) $(top_h) $(gdbthread_h) $(mi_cmds_h) $(mi_parse_h) \ $(mi_getopt_h) $(mi_console_h) $(ui_out_h) $(mi_out_h) \ Index: cli-out.c =================================================================== RCS file: /cvs/src/src/gdb/cli-out.c,v retrieving revision 1.14 diff -p -r1.14 cli-out.c *** cli-out.c 19 Mar 2002 02:51:04 -0000 1.14 --- cli-out.c 23 Sep 2002 19:37:36 -0000 *************** cli_out_new (struct ui_file *stream) *** 365,370 **** --- 365,379 ---- return ui_out_new (&cli_ui_out_impl, data, flags); } + struct ui_file * + cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream) + { + struct ui_out_data *data = ui_out_data (uiout); + struct ui_file *old = data->stream; + data->stream = stream; + return old; + } + /* standard gdb initialization hook */ void _initialize_cli_out (void) Index: cli-out.h =================================================================== RCS file: /cvs/src/src/gdb/cli-out.h,v retrieving revision 1.2 diff -p -r1.2 cli-out.h *** cli-out.h 6 Mar 2001 08:21:06 -0000 1.2 --- cli-out.h 23 Sep 2002 19:37:36 -0000 *************** *** 23,27 **** #define CLI_OUT_H extern struct ui_out *cli_out_new (struct ui_file *stream); ! #endif --- 23,28 ---- #define CLI_OUT_H extern struct ui_out *cli_out_new (struct ui_file *stream); ! extern struct ui_file *cli_out_set_stream (struct ui_out *uiout, ! struct ui_file *stream); #endif Index: event-loop.c =================================================================== RCS file: /cvs/src/src/gdb/event-loop.c,v retrieving revision 1.19 diff -p -r1.19 event-loop.c *** event-loop.c 10 Sep 2002 19:53:24 -0000 1.19 --- event-loop.c 23 Sep 2002 19:37:37 -0000 *************** *** 22,27 **** --- 22,28 ---- #include "defs.h" #include "event-loop.h" #include "event-top.h" + #include "interps.h" #ifdef HAVE_POLL #if defined (HAVE_POLL_H) *************** static void create_file_handler (int fd, *** 210,215 **** --- 211,217 ---- static void invoke_async_signal_handler (void); static void handle_file_event (int event_file_desc); static int gdb_wait_for_event (void); + static int gdb_do_one_event (void *data); static int check_async_ready (void); static void async_queue_event (gdb_event * event_ptr, queue_position position); static gdb_event *create_file_event (int fd); *************** process_event (void) *** 345,351 **** can happen if there are no event sources to wait for). If an error occurs catch_errors() which calls this function returns zero. */ ! int gdb_do_one_event (void *data) { /* Any events already waiting in the queue? */ --- 347,353 ---- can happen if there are no event sources to wait for). If an error occurs catch_errors() which calls this function returns zero. */ ! static int gdb_do_one_event (void *data) { /* Any events already waiting in the queue? */ *************** start_event_loop (void) *** 392,401 **** longer any event sources registered. */ while (1) { ! int result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); ! if (result < 0) break; ! if (result == 0) { /* FIXME: this should really be a call to a hook that is interface specific, because interfaces can display the --- 394,416 ---- longer any event sources registered. */ while (1) { ! int gdb_result, interp_result; ! ! gdb_result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); ! if (gdb_result < 0) break; ! ! interp_result = catch_errors (interpreter_do_one_event, 0, "", RETURN_MASK_ALL); ! if (interp_result < 0) ! { ! /* FIXME - kill the interpreter */ ! } ! ! /* If we long-jumped out of do_one_event, we probably ! didn't get around to resetting the prompt, which leaves ! readline in a messed-up state. Reset it here. */ ! ! if (gdb_result == 0) { /* FIXME: this should really be a call to a hook that is interface specific, because interfaces can display the Index: event-top.c =================================================================== RCS file: /cvs/src/src/gdb/event-top.c,v retrieving revision 1.22 diff -p -r1.22 event-top.c *** event-top.c 3 Jul 2002 20:27:12 -0000 1.22 --- event-top.c 23 Sep 2002 19:37:37 -0000 *************** *** 26,31 **** --- 26,32 ---- #include "terminal.h" /* for job_control */ #include "event-loop.h" #include "event-top.h" + #include "interps.h" #include /* For dont_repeat() */ *************** display_gdb_prompt (char *new_prompt) *** 252,258 **** /* When an alternative interpreter has been installed, do not display the comand prompt. */ ! if (interpreter_p) return; if (target_executing && sync_execution) --- 253,259 ---- /* When an alternative interpreter has been installed, do not display the comand prompt. */ ! if (gdb_interpreter_display_prompt (new_prompt)) return; if (target_executing && sync_execution) *************** set_async_prompt (char *args, int from_t *** 1113,1126 **** PROMPT (0) = savestring (new_async_prompt, strlen (new_async_prompt)); } /* Set things up for readline to be invoked via the alternate interface, i.e. via a callback function (rl_callback_read_char), and hook up instream to the event loop. */ void ! _initialize_event_loop (void) { if (event_loop_p) { /* If the input stream is connected to a terminal, turn on editing. */ if (ISATTY (instream)) --- 1114,1144 ---- PROMPT (0) = savestring (new_async_prompt, strlen (new_async_prompt)); } + void + _initialize_event_loop (void) + { + /* Tell gdb to use the cli_command_loop as the main loop. */ + if (event_loop_p && command_loop_hook == NULL) + command_loop_hook = cli_command_loop; + } + /* Set things up for readline to be invoked via the alternate interface, i.e. via a callback function (rl_callback_read_char), and hook up instream to the event loop. */ void ! gdb_setup_readline (void) { + /* This function is a noop for the async case. The assumption is that + the async setup is ALL done in gdb_init, and we would only mess it up + here. The async stuff should really go away over time. */ + if (event_loop_p) { + gdb_stdout = stdio_fileopen (stdout); + gdb_stderr = stdio_fileopen (stderr); + gdb_stdlog = gdb_stderr; /* for moment */ + gdb_stdtarg = gdb_stderr; /* for moment */ + /* If the input stream is connected to a terminal, turn on editing. */ if (ISATTY (instream)) *************** _initialize_event_loop (void) *** 1153,1161 **** register it with the event loop. */ input_fd = fileno (instream); - /* Tell gdb to use the cli_command_loop as the main loop. */ - command_loop_hook = cli_command_loop; - /* Now we need to create the event sources for the input file descriptor. */ /* At this point in time, this is the only event source that we --- 1171,1176 ---- *************** _initialize_event_loop (void) *** 1166,1168 **** --- 1181,1211 ---- add_file_handler (input_fd, stdin_event_handler, 0); } } + + /* Disable command input through the standard CLI channels. Used in + the suspend proc for interpreters that use the standard gdb readline + interface, like the cli & the mi. */ + + void + gdb_disable_readline (void) + { + if (event_loop_p) + { + /* FIXME - It is too heavyweight to delete and remake these + every time you run an interpreter that needs readline. + It is probably better to have the interpreters cache these, + which in turn means that this needs to be moved into interpreter + specific code. */ + + #if 0 + ui_file_delete (gdb_stdout); + ui_file_delete (gdb_stderr); + gdb_stdlog = NULL; + gdb_stdtarg = NULL; + #endif + + rl_callback_handler_remove (); + delete_file_handler (input_fd); + } + } + Index: event-top.h =================================================================== RCS file: /cvs/src/src/gdb/event-top.h,v retrieving revision 1.4 diff -p -r1.4 event-top.h *** event-top.h 27 Nov 2001 04:15:09 -0000 1.4 --- event-top.h 23 Sep 2002 19:37:37 -0000 *************** struct prompts *** 71,76 **** --- 71,78 ---- FIXME: these should really go into top.h. */ extern void display_gdb_prompt (char *new_prompt); + extern void gdb_setup_readline (void); + extern void gdb_disable_readline (void); extern void async_init_signals (void); extern void set_async_editing_command (char *args, int from_tty, struct cmd_list_element *c); Index: interps.c =================================================================== RCS file: interps.c diff -N interps.c *** interps.c 1 Jan 1970 00:00:00 -0000 --- interps.c 23 Sep 2002 19:37:37 -0000 *************** *** 0 **** --- 1,661 ---- + /* Manages interpreters for gdb. + Copyright 2000, 2002 Free Software Foundation, Inc. + Written by Jim Ingham 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" + #include "gdb-events.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; + } + } + + /* Clear out any installed interpreter hooks/event handlers. */ + clear_interpreter_hooks (); + + 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 ¤t_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; + 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... */ + } + + /* 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, 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 [ ... ]"); + + 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]); + + /* Temporarily set interpreters quiet */ + old_quiet = gdb_interpreter_set_quiet (old_interp, 1); + use_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, use_quiet); + gdb_interpreter_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, 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_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); + } Index: interps.h =================================================================== RCS file: interps.h diff -N interps.h *** interps.h 1 Jan 1970 00:00:00 -0000 --- interps.h 23 Sep 2002 19:37:37 -0000 *************** *** 0 **** --- 1,76 ---- + /* Manages interpreters for gdb. + Copyright 2000,2002 Free Software Foundation, Inc. + Written by Jim Ingham 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_MI0 "mi0" + #define GDB_INTERPRETER_MI1 "mi1" + #define GDB_INTERPRETER_MI "mi" + #endif /* GDB_INTERPRETER_H */ Index: top.c =================================================================== RCS file: /cvs/src/src/gdb/top.c,v retrieving revision 1.67 diff -p -r1.67 top.c *** top.c 9 Sep 2002 21:03:26 -0000 1.67 --- top.c 23 Sep 2002 19:37:37 -0000 *************** *** 63,68 **** --- 63,69 ---- #include #include "ui-out.h" #include "cli-out.h" + #include "interps.h" /* Default command line prompt. This is overriden in some configs. */ *************** gdb_init (char *argv0) *** 2126,2142 **** init_ui_hook (argv0); /* Install the default UI */ ! if (!init_ui_hook) ! { ! uiout = cli_out_new (gdb_stdout); ! /* All the interpreters should have had a look at things by now. ! Initialize the selected interpreter. */ ! if (interpreter_p) ! { ! fprintf_unfiltered (gdb_stderr, "Interpreter `%s' unrecognized.\n", ! interpreter_p); ! exit (1); ! } ! } } --- 2127,2152 ---- init_ui_hook (argv0); /* Install the default UI */ ! /* All the interpreters should have had a look at things by now. ! Initialize the selected interpreter. */ ! { ! struct gdb_interpreter *interp; ! if (interpreter_p == NULL) ! interpreter_p = xstrdup (GDB_INTERPRETER_CONSOLE); ! interp = gdb_lookup_interpreter (interpreter_p); ! ! if (interp == NULL) ! { ! fprintf_unfiltered (gdb_stderr, "Interpreter `%s' unrecognized.\n", ! interpreter_p); ! exit (1); ! } ! if (!gdb_set_interpreter (interp)) ! { ! fprintf_unfiltered (gdb_stderr, "Interpreter `%s' failed to initialize.\n", ! interpreter_p); ! exit (1); ! } ! } } Index: wrapper.c =================================================================== RCS file: /cvs/src/src/gdb/wrapper.c,v retrieving revision 1.14 diff -p -r1.14 wrapper.c *** wrapper.c 31 Oct 2001 03:16:04 -0000 1.14 --- wrapper.c 23 Sep 2002 19:37:38 -0000 *************** *** 19,24 **** --- 19,25 ---- #include "defs.h" #include "value.h" #include "wrapper.h" + #include "top.h" /* for execute_command */ /* Use this struct to pass arguments to wrapper routines. We assume (arbitrarily) that no gdb function takes more than ten arguments. */ *************** struct captured_value_struct_elt_args *** 51,56 **** --- 52,63 ---- struct value **result_ptr; }; + struct captured_execute_command_args + { + char *command; + int from_tty; + }; + static int wrap_parse_exp_1 (char *); static int wrap_evaluate_expression (char *); *************** do_captured_value_struct_elt (struct ui_ *** 331,333 **** --- 338,357 ---- return GDB_RC_OK; } + static int + do_captured_execute_command (struct ui_out *uiout, void *data) + { + struct captured_execute_command_args *args = data; + execute_command (args->command, args->from_tty); + return GDB_RC_OK; + } + + enum gdb_rc + gdb_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); + } Index: wrapper.h =================================================================== RCS file: /cvs/src/src/gdb/wrapper.h,v retrieving revision 1.12 diff -p -r1.12 wrapper.h *** wrapper.h 31 Oct 2001 03:16:04 -0000 1.12 --- wrapper.h 23 Sep 2002 19:37:38 -0000 *************** *** 21,26 **** --- 21,30 ---- #include "gdb.h" struct value; + struct block; + struct expression; + struct ui_out; + struct type; /* Use this struct to pass arguments to wrapper routines. */ struct gdb_wrapper_arguments; *************** extern int gdb_value_ind (struct value * *** 46,49 **** --- 50,55 ---- extern int gdb_parse_and_eval_type (char *, int, struct type **); + extern enum gdb_rc gdb_execute_command (struct ui_out *uiout, char *command, + int from_tty); #endif /* WRAPPER_H */ Index: cli/cli-interp.c =================================================================== RCS file: cli/cli-interp.c diff -N cli/cli-interp.c *** cli/cli-interp.c 1 Jan 1970 00:00:00 -0000 --- cli/cli-interp.c 23 Sep 2002 19:37:38 -0000 *************** *** 0 **** --- 1,127 ---- + /* 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. */ + static struct ui_out *cli_uiout; + static 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) + { + int result; + struct ui_file *old_stream; + + /* 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 = gdb_execute_command (cli_uiout, command_str, 1); + cli_out_set_stream (cli_uiout, old_stream); + return result; + } + + /* 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 */ + }; + + /* Create a default uiout builder for the CLI. */ + cli_uiout = cli_out_new (gdb_stdout); + cli_interp = gdb_new_interpreter (GDB_INTERPRETER_CONSOLE, NULL, cli_uiout, + &procs); + gdb_add_interpreter (cli_interp); + } Index: mi/mi-cmds.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-cmds.c,v retrieving revision 1.8 diff -p -r1.8 mi-cmds.c *** mi/mi-cmds.c 6 Mar 2001 08:21:45 -0000 1.8 --- mi/mi-cmds.c 23 Sep 2002 19:37:38 -0000 *************** struct mi_cmd mi_cmds[] = *** 88,93 **** --- 88,94 ---- {"gdb-show", "show %s", 0}, {"gdb-source", 0, 0}, {"gdb-version", "show version", 0}, + {"interpreter-exec", 0, 0, mi_cmd_interpreter_exec}, {"kod-info", 0, 0}, {"kod-list", 0, 0}, {"kod-list-object-types", 0, 0}, Index: mi/mi-cmds.h =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-cmds.h,v retrieving revision 1.5 diff -p -r1.5 mi-cmds.h *** mi/mi-cmds.h 6 Mar 2001 08:21:45 -0000 1.5 --- mi/mi-cmds.h 23 Sep 2002 19:37:38 -0000 *************** extern mi_cmd_args_ftype mi_cmd_exec_ste *** 75,80 **** --- 75,81 ---- extern mi_cmd_args_ftype mi_cmd_exec_until; extern mi_cmd_args_ftype mi_cmd_exec_interrupt; extern mi_cmd_argv_ftype mi_cmd_gdb_exit; + extern mi_cmd_argv_ftype mi_cmd_interpreter_exec; extern mi_cmd_argv_ftype mi_cmd_stack_info_depth; extern mi_cmd_argv_ftype mi_cmd_stack_list_args; extern mi_cmd_argv_ftype mi_cmd_stack_list_frames; *************** extern int mi_debug_p; *** 122,125 **** --- 123,129 ---- /* Raw console output - FIXME: should this be a parameter? */ extern struct ui_file *raw_stdout; + extern char *mi_error_message; + extern void mi_error_last_message (void); + extern void mi_execute_command (char *cmd, int from_tty); #endif Index: mi/mi-console.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-console.c,v retrieving revision 1.8 diff -p -r1.8 mi-console.c *** mi/mi-console.c 19 Mar 2002 02:51:08 -0000 1.8 --- mi/mi-console.c 23 Sep 2002 19:37:38 -0000 *************** struct mi_console_file *** 37,49 **** struct ui_file *raw; struct ui_file *buffer; const char *prefix; }; int mi_console_file_magic; struct ui_file * mi_console_file_new (struct ui_file *raw, ! const char *prefix) { struct ui_file *ui_file = ui_file_new (); struct mi_console_file *mi_console = XMALLOC (struct mi_console_file); --- 37,50 ---- struct ui_file *raw; struct ui_file *buffer; const char *prefix; + char quote; }; int mi_console_file_magic; struct ui_file * mi_console_file_new (struct ui_file *raw, ! const char *prefix, char quote) { struct ui_file *ui_file = ui_file_new (); struct mi_console_file *mi_console = XMALLOC (struct mi_console_file); *************** mi_console_file_new (struct ui_file *raw *** 51,56 **** --- 52,58 ---- mi_console->raw = raw; mi_console->buffer = mem_fileopen (); mi_console->prefix = prefix; + mi_console->quote = quote; set_ui_file_fputs (ui_file, mi_console_file_fputs); set_ui_file_flush (ui_file, mi_console_file_flush); set_ui_file_data (ui_file, mi_console, mi_console_file_delete); *************** mi_console_raw_packet (void *data, *** 96,104 **** if (length_buf > 0) { fputs_unfiltered (mi_console->prefix, mi_console->raw); ! fputs_unfiltered ("\"", mi_console->raw); ! fputstrn_unfiltered (buf, length_buf, '"', mi_console->raw); ! fputs_unfiltered ("\"\n", mi_console->raw); gdb_flush (mi_console->raw); } } --- 98,114 ---- if (length_buf > 0) { fputs_unfiltered (mi_console->prefix, mi_console->raw); ! if (mi_console->quote) ! { ! fputs_unfiltered ("\"", mi_console->raw); ! fputstrn_unfiltered (buf, length_buf, mi_console->quote, mi_console->raw); ! fputs_unfiltered ("\"\n", mi_console->raw); ! } ! else ! { ! fputstrn_unfiltered (buf, length_buf, 0, mi_console->raw); ! fputs_unfiltered ("\n", mi_console->raw); ! } gdb_flush (mi_console->raw); } } Index: mi/mi-console.h =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-console.h,v retrieving revision 1.4 diff -p -r1.4 mi-console.h *** mi/mi-console.h 6 Mar 2001 08:21:45 -0000 1.4 --- mi/mi-console.h 23 Sep 2002 19:37:38 -0000 *************** *** 22,27 **** #ifndef MI_CONSOLE_H #define MI_CONSOLE_H ! extern struct ui_file *mi_console_file_new (struct ui_file *raw, const char *prefix); #endif --- 22,28 ---- #ifndef MI_CONSOLE_H #define MI_CONSOLE_H ! extern struct ui_file *mi_console_file_new (struct ui_file *raw, const char *prefix, ! char quote); #endif Index: mi/mi-events.c =================================================================== RCS file: mi/mi-events.c diff -N mi/mi-events.c *** mi/mi-events.c 1 Jan 1970 00:00:00 -0000 --- mi/mi-events.c 23 Sep 2002 19:37:38 -0000 *************** *** 0 **** --- 1,120 ---- + /* 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; + } + + static void + event_notify (const char *string, ...) + { + va_list args; + + if (!gdb_current_interpreter_is_named (GDB_INTERPRETER_MI0) + && !gdb_current_interpreter_is_named (GDB_INTERPRETER_MI1)) + { + va_start (args, string); + vfprintf_unfiltered (mi_event_channel, string, args); + va_end (args); + gdb_flush (mi_event_channel); + } + } + + /* breakpoint-create,number=bpnum */ + void + mi_create_breakpoint (int bpnum) + { + event_notify ("breakpoint-create,number=\"%d\"", bpnum); + } + + void + mi_modify_breakpoint (int bpnum) + { + event_notify ("breakpoint-modify,number=\"%d\"", bpnum); + } + + void + mi_delete_breakpoint (int bpnum) + { + event_notify ("breakpoint-delete,number=\"%d\"", bpnum); + } + + void + mi_create_tracepoint (int tpnum) + { + event_notify ("tracepoint-create,number=\"%d\"", tpnum); + } + + void + mi_modify_tracepoint (int tpnum) + { + event_notify ("tracepoint-modify,number=\"%d\"", tpnum); + } + + void + mi_delete_tracepoint (int tpnum) + { + event_notify ("tracepoint-delete,number=\"%d\"", tpnum); + } + + void + mi_architecture_changed (void) + { + event_notify ("architecture-changed"); + } + + void + mi_target_changed (void) + { + event_notify ("target-changed"); + } + + void + mi_selected_frame_level_changed (int level) + { + event_notify ("selected-frame-level-changed,level=\"%d\"", level); + } + + void + mi_context_changed (int thread_id) + { + event_notify ("context-changed,thread=\"%d\"", thread_id); + } Index: mi/mi-interp.c =================================================================== RCS file: mi/mi-interp.c diff -N mi/mi-interp.c *** mi/mi-interp.c 1 Jan 1970 00:00:00 -0000 --- mi/mi-interp.c 23 Sep 2002 19:37:38 -0000 *************** *** 0 **** --- 1,477 ---- + /* 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; + struct ui_file *mi_event_channel; + + /* This is the interpreter for the mi... */ + struct gdb_interpreter *mi0_interp; + struct gdb_interpreter *mi1_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_exec (void *data, char *command); + 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 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); + + static struct gdb_events mi_event_handlers = + { + mi_create_breakpoint, + mi_delete_breakpoint, + mi_modify_breakpoint, + mi_create_tracepoint, + mi_delete_tracepoint, + mi_modify_tracepoint, + mi_architecture_changed, + mi_target_changed, + mi_selected_frame_level_changed + }; + + static int + mi_interpreter_init (void *data) + { + static struct gdb_events handlers; + + /* 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_stdout = mi_console_file_new (raw_stdout, "~", '"'); + mi_stderr = mi_console_file_new (raw_stdout, "&", '"'); + mi_stdlog = mi_stderr; + mi_stdtarg = mi_console_file_new (raw_stdout, "@", '"'); + mi_event_channel = mi_console_file_new (raw_stdout, "=", 0); + + return 1; + } + + static 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 (); + set_gdb_event_hooks (&mi_event_handlers); + + 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_MI1)) + command_loop_hook = mi1_command_loop; + else if (gdb_current_interpreter_is_named (GDB_INTERPRETER_MI)) + command_loop_hook = mi1_command_loop; + else + return 0; + + return 1; + } + + static int + mi_interpreter_suspend (void *data) + { + gdb_disable_readline (); + return 1; + } + + static int + mi_interpreter_delete (void *data) + { + return 1; + } + + static int + mi_interpreter_exec (void *data, char *command) + { + mi_execute_command_wrapper (command); + return 1; + } + + static int + mi_interpreter_prompt (void *data, char *new_prompt) + { + return 1; + } + + static int + mi_do_one_event (void *data) + { + return 1; + } + + 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 gdb_interpreter *interp_to_use; + enum mi_cmd_result result = MI_CMD_DONE; + int i; + struct gdb_interpreter_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 = gdb_lookup_interpreter (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; + } + + procs = gdb_interpreter_get_procs (interp_to_use); + if (!procs->exec_proc) + { + 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 (procs->exec_proc (gdb_interpreter_get_data (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 + 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) + { + #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) + { + 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 */ + mi_interpreter_exec, /* exec_proc */ + mi_interpreter_prompt /* prompt_proc */ + }; + + /* Create MI0 interpreter */ + 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"); + } + + /* Create MI1 interpreter */ + if (mi1_interp == NULL) + { + mi1_interp = + gdb_new_interpreter (GDB_INTERPRETER_MI1, NULL, mi_out_new (1), + &procs); + if (mi1_interp == NULL) + error + ("Couldn't allocate a new interpreter for the mi1 interpreter\n"); + if (gdb_add_interpreter (mi1_interp) != 1) + error ("Couldn't add the mi1 interpreter to gdb.\n"); + } + + /* Create MI2 interpreter */ + if (mi_interp == NULL) + { + mi_interp = + gdb_new_interpreter (GDB_INTERPRETER_MI, NULL, mi_out_new (2), + &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"); + } + } Index: mi/mi-main.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-main.c,v retrieving revision 1.31 diff -p -r1.31 mi-main.c *** mi/mi-main.c 11 Sep 2002 21:49:04 -0000 1.31 --- mi/mi-main.c 23 Sep 2002 19:37:38 -0000 *************** *** 33,38 **** --- 33,39 ---- #include "mi-console.h" #include "ui-out.h" #include "mi-out.h" + #include "interps.h" #include "event-loop.h" #include "event-top.h" #include "gdbcore.h" /* for write_memory() */ *************** struct ui_file *raw_stdout; *** 77,103 **** /* The token of the last asynchronous command */ static char *last_async_command; static char *previous_async_command; ! static char *mi_error_message; static char *old_regs; extern void _initialize_mi_main (void); ! static char *mi_input (char *); ! static void mi_execute_command (char *cmd, int from_tty); static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse); static void mi_execute_cli_command (const char *cli, char *args); static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty); - static void mi_execute_command_wrapper (char *cmd); void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg); static int register_changed_p (int regnum); static int get_register (int regnum, int format); ! static 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); /* FIXME: these should go in some .h file, but infcmd.c doesn't have a corresponding .h file. These wrappers will be obsolete anyway, once --- 78,102 ---- /* The token of the last asynchronous command */ static char *last_async_command; static char *previous_async_command; ! char *mi_error_message; static char *old_regs; extern void _initialize_mi_main (void); ! void mi_execute_command (char *cmd, int from_tty); static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse); static void mi_execute_cli_command (const char *cli, char *args); static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty); void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg); static int register_changed_p (int regnum); static int get_register (int regnum, int format); ! 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); /* FIXME: these should go in some .h file, but infcmd.c doesn't have a corresponding .h file. These wrappers will be obsolete anyway, once *************** static void mi_load_progress (const char *** 105,110 **** --- 104,118 ---- extern void interrupt_target_command_wrapper (char *, int); extern void return_command_wrapper (char *, int); + /* A helper function which will set mi_error_message to error_last_message. */ + void + mi_error_last_message (void) + { + char *s = error_last_message (); + xasprintf (&mi_error_message, s); + xfree (s); + } + /* Command implementations. FIXME: Is this libgdb? No. This is the MI layer that calls libgdb. Any operation used in the below should be formalized. */ *************** mi_execute_command (char *cmd, int from_ *** 1165,1171 **** struct mi_parse *command; struct captured_mi_execute_command_args args; struct ui_out *saved_uiout = uiout; ! int result, rc; /* This is to handle EOF (^D). We just quit gdb. */ /* FIXME: we should call some API function here. */ --- 1173,1179 ---- struct mi_parse *command; struct captured_mi_execute_command_args args; struct ui_out *saved_uiout = uiout; ! int result; /* This is to handle EOF (^D). We just quit gdb. */ /* FIXME: we should call some API function here. */ *************** mi_cmd_execute (struct mi_parse *parse) *** 1273,1284 **** } } - static void - mi_execute_command_wrapper (char *cmd) - { - mi_execute_command (cmd, stdin == instream); - } - /* FIXME: This is just a hack so we can get some extra commands going. We don't want to channel things through the CLI, but call libgdb directly */ /* Use only for synchronous commands */ --- 1281,1286 ---- *************** mi_exec_async_cli_cmd_continuation (stru *** 1381,1393 **** do_exec_cleanups (ALL_CLEANUPS); } ! static char * ! mi_input (char *buf) ! { ! return gdb_readline (NULL); ! } ! ! static void mi_load_progress (const char *section_name, unsigned long sent_so_far, unsigned long total_section, --- 1383,1389 ---- do_exec_cleanups (ALL_CLEANUPS); } ! void mi_load_progress (const char *section_name, unsigned long sent_so_far, unsigned long total_section, *************** mi_load_progress (const char *section_na *** 1456,1573 **** } } ! 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 void ! mi0_command_loop (void) ! { ! mi_command_loop (0); ! } ! ! static void ! mi1_command_loop (void) ! { ! mi_command_loop (1); ! } ! ! static void ! setup_architecture_data (void) { /* don't trust REGISTER_BYTES to be zero. */ old_regs = xmalloc (REGISTER_BYTES + 1); memset (old_regs, 0, REGISTER_BYTES + 1); } - static void - mi_init_ui (char *arg0) - { - /* Eventually this will contain code that takes control of the - console. */ - } - void ! _initialize_mi_main (void) { - if (interpreter_p == NULL) - return; - - /* If we're _the_ interpreter, take control. */ - if (strcmp (interpreter_p, "mi0") == 0) - command_loop_hook = mi0_command_loop; - else if (strcmp (interpreter_p, "mi") == 0 - || strcmp (interpreter_p, "mi1") == 0) - command_loop_hook = mi1_command_loop; - else - return; - - init_ui_hook = mi_init_ui; - setup_architecture_data (); register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL); ! register_gdbarch_swap (NULL, 0, setup_architecture_data); ! 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: Should we notify main that we are here as a possible ! interpreter? */ } --- 1452,1468 ---- } } ! void ! mi_setup_architecture_data (void) { /* don't trust REGISTER_BYTES to be zero. */ old_regs = xmalloc (REGISTER_BYTES + 1); memset (old_regs, 0, REGISTER_BYTES + 1); } void ! mi_register_gdbarch_swap (void) { register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL); ! register_gdbarch_swap (NULL, 0, mi_setup_architecture_data); } Index: mi/mi.h =================================================================== RCS file: mi/mi.h diff -N mi/mi.h *** mi/mi.h 1 Jan 1970 00:00:00 -0000 --- mi/mi.h 23 Sep 2002 19:37:38 -0000 *************** *** 0 **** --- 1,59 ---- + /* 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 ui_file; + struct breakpoint; + 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); + + /* MI's output channels */ + extern struct ui_file *mi_stdout; + extern struct ui_file *mi_stderr; + extern struct ui_file *mi_stdlog; + extern struct ui_file *mi_stdtarg; + extern struct ui_file *mi_event_channel; + + /* 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_frame_changed_hook (int new_frame_number); + extern void mi_interp_context_hook (int thread_id); + + extern void mi_create_breakpoint (int bpnum); + extern void mi_modify_breakpoint (int bpnum); + extern void mi_delete_breakpoint (int bpnum); + extern void mi_create_tracepoint (int bpnum); + extern void mi_modify_tracepoint (int bpnum); + extern void mi_delete_tracepoint (int bpnum); + extern void mi_architecture_changed (void); + extern void mi_target_changed (void); + extern void mi_selected_frame_level_changed (int level); + extern void mi_context_changed (int thread_id); + #endif /* MI_H */