This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [RFA]: Make gdb_do_one_event public and fix uiout setting for TUI
- From: Elena Zannoni <ezannoni at redhat dot com>
- To: Stephane Carrez <stcarrez at nerim dot fr>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Mon, 26 Aug 2002 18:50:43 -0400
- Subject: Re: [RFA]: Make gdb_do_one_event public and fix uiout setting for TUI
- References: <3D6AB1C8.5050403@nerim.fr>
Stephane Carrez writes:
> Hi!
>
> The TUI relies on the modification of the 'uiout' to switch correctly
> between TUI mode and normal mode. It installs its own ui-out function to
> catch the output and redirect it in the appropriate curses window.
> It installs gdb's normal ui-out function when using the plain terminal
> (non-TUI mode).
I am a bit confused here about the uiout switch. I see that it does it
when you start up the TUI, but there is also a mode switch with
tui_switch_mode. How does this interact with your change?
Elena
>
> Since 2001-09-07, the 'do_catch_errors' function preserve the 'uiout' (for safety
> reasons I guess). This breaks the TUI mode switching because the 'uiout' is
> always restored to its origin.
>
> To solve the problem it's necessary to update the 'uiout' according to the TUI
> mode at the gdb top level. The simplest way is to make TUI provide its own
> command loop, install a 'command_loop_hook' and do its special 'uiout' management
> there. To do this we have everything except that 'gdb_do_one_event' is private.
> (It makes sense to make it public, see 'XtAppProcessEvent' for example).
>
> In short, I would like approval to make 'gdb_do_one_event' a public function.
>
> Ok to commit?
>
> Stephane
>
> gdb/ChangeLog
>
> 2002-08-27 Stephane Carrez <stcarrez@nerim.fr>
>
> * event-loop.c (gdb_do_one_event): Make public.
> * event-loop.h (gdb_do_one_event): Declare.
>
> tui/ChangeLog
>
> 2002-08-27 Stephane Carrez <stcarrez@nerim.fr>
>
> * tui-hooks.c (tui_event_loop): New function.
> (tui_command_loop): New function to override gdb loop and make sure
> uiout is set according to TUI mode.
> (tui_command_loop): Install the specific TUI command hook.
> * tuiIO.c (tui_initialize_io): Initialize tui_old_uiout.
> (tui_uiout, tui_old_uiout): Make public.
> * tuiIO.h (tui_uiout, tui_old_uiout): Declare.
> Index: event-loop.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/event-loop.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 event-loop.c
> --- event-loop.c 14 May 2002 15:21:10 -0000 1.18
> +++ event-loop.c 26 Aug 2002 20:24:38 -0000
> @@ -210,7 +210,6 @@ static void create_file_handler (int fd,
> 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);
> @@ -346,7 +345,7 @@ process_event (void)
> 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
> +int
> gdb_do_one_event (void *data)
> {
> /* Any events already waiting in the queue? */
> Index: event-loop.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/event-loop.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 event-loop.h
> --- event-loop.h 6 Mar 2001 08:21:07 -0000 1.3
> +++ event-loop.h 26 Aug 2002 20:24:38 -0000
> @@ -85,6 +85,7 @@ queue_position;
> /* Exported functions from event-loop.c */
>
> extern void start_event_loop (void);
> +extern int gdb_do_one_event (void *data);
> extern void delete_file_handler (int fd);
> extern void add_file_handler (int fd, handler_func * proc, gdb_client_data client_data);
> extern void mark_async_signal_handler (struct async_signal_handler *async_handler_ptr);
> Index: tui/tui-hooks.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/tui/tui-hooks.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 tui-hooks.c
> --- tui/tui-hooks.c 25 Aug 2002 19:19:50 -0000 1.5
> +++ tui/tui-hooks.c 26 Aug 2002 20:24:39 -0000
> @@ -46,9 +46,13 @@
> #include "target.h"
> #include "gdbcore.h"
> #include "event-loop.h"
> +#include "event-top.h"
> #include "frame.h"
> #include "breakpoint.h"
> #include "gdb-events.h"
> +#include "ui-out.h"
> +#include "top.h"
> +#include <readline/readline.h>
> #include <unistd.h>
> #include <fcntl.h>
>
> @@ -66,6 +70,8 @@ int tui_target_has_run = 0;
>
> static void (* tui_target_new_objfile_chain) (struct objfile*);
> extern void (*selected_frame_level_changed_hook) (int);
> +static void tui_event_loop (void);
> +static void tui_command_loop (void);
>
> static void
> tui_new_objfile_hook (struct objfile* objfile)
> @@ -372,6 +378,86 @@ tui_exit (void)
> tui_disable ();
> }
>
> +/* Initialize all the necessary variables, start the event loop,
> + register readline, and stdin, start the loop. */
> +static void
> +tui_command_loop (void)
> +{
> + int length;
> + char *a_prompt;
> + char *gdb_prompt = get_prompt ();
> +
> + /* If we are using readline, set things up and display the first
> + prompt, otherwise just print the prompt. */
> + if (async_command_editing_p)
> + {
> + /* Tell readline what the prompt to display is and what function it
> + will need to call after a whole line is read. This also displays
> + the first prompt. */
> + length = strlen (PREFIX (0)) + strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1;
> + a_prompt = (char *) xmalloc (length);
> + strcpy (a_prompt, PREFIX (0));
> + strcat (a_prompt, gdb_prompt);
> + strcat (a_prompt, SUFFIX (0));
> + rl_callback_handler_install (a_prompt, input_handler);
> + }
> + else
> + display_gdb_prompt (0);
> +
> + /* Now it's time to start the event loop. */
> + tui_event_loop ();
> +}
> +
> +/* Start up the event loop. This is the entry point to the event loop
> + from the command loop. */
> +
> +static void
> +tui_event_loop (void)
> +{
> + /* Loop until there is nothing to do. This is the entry point to the
> + event loop engine. gdb_do_one_event, called via catch_errors()
> + will process one event for each invocation. It blocks waits for
> + an event and then processes it. >0 when an event is processed, 0
> + when catch_errors() caught an error and <0 when there are no
> + longer any event sources registered. */
> + while (1)
> + {
> + int result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL);
> + if (result < 0)
> + break;
> +
> + /* Update gdb output according to TUI mode. Since catch_errors
> + preserves the uiout from changing, this must be done at top
> + level of event loop. */
> + if (tui_active)
> + uiout = tui_out;
> + else
> + uiout = tui_old_uiout;
> +
> + if (result == 0)
> + {
> + /* FIXME: this should really be a call to a hook that is
> + interface specific, because interfaces can display the
> + prompt in their own way. */
> + display_gdb_prompt (0);
> + /* This call looks bizarre, but it is required. If the user
> + entered a command that caused an error,
> + after_char_processing_hook won't be called from
> + rl_callback_read_char_wrapper. Using a cleanup there
> + won't work, since we want this function to be called
> + after a new prompt is printed. */
> + if (after_char_processing_hook)
> + (*after_char_processing_hook) ();
> + /* Maybe better to set a flag to be checked somewhere as to
> + whether display the prompt or not. */
> + }
> + }
> +
> + /* We are done with the event loop. There are no more event sources
> + to listen to. So we exit GDB. */
> + return;
> +}
> +
> /* Initialize the tui by installing several gdb hooks, initializing
> the tui IO and preparing the readline with the kind binding. */
> static void
> @@ -388,6 +474,9 @@ tui_init_hook (char *argv0)
>
> tui_initialize_io ();
> tui_initialize_readline ();
> +
> + /* Tell gdb to use the tui_command_loop as the main loop. */
> + command_loop_hook = tui_command_loop;
>
> /* Decide in which mode to start using GDB (based on -tui). */
> if (tui_version)
> Index: tui/tuiIO.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/tui/tuiIO.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 tuiIO.c
> --- tui/tuiIO.c 1 Mar 2002 06:19:28 -0000 1.12
> +++ tui/tuiIO.c 26 Aug 2002 20:24:39 -0000
> @@ -87,12 +87,12 @@
> /* TUI output files. */
> static struct ui_file *tui_stdout;
> static struct ui_file *tui_stderr;
> -static struct ui_out *tui_out;
> +struct ui_out *tui_out;
>
> /* GDB output files in non-curses mode. */
> static struct ui_file *tui_old_stdout;
> static struct ui_file *tui_old_stderr;
> -static struct ui_out *tui_old_uiout;
> +struct ui_out *tui_old_uiout;
>
> /* Readline previous hooks. */
> static Function *tui_old_rl_getc_function;
> @@ -357,7 +357,7 @@ tui_initialize_io ()
>
> /* Create the default UI. It is not created because we installed
> a init_ui_hook. */
> - uiout = cli_out_new (gdb_stdout);
> + tui_old_uiout = uiout = cli_out_new (gdb_stdout);
>
> /* Temporary solution for readline writing to stdout:
> redirect readline output in a pipe, read that pipe and
> Index: tui/tuiIO.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/tui/tuiIO.h,v
> retrieving revision 1.4
> diff -u -p -r1.4 tuiIO.h
> --- tui/tuiIO.h 21 Jul 2001 19:56:54 -0000 1.4
> +++ tui/tuiIO.h 26 Aug 2002 20:24:39 -0000
> @@ -36,6 +36,8 @@ extern void tui_initialize_io (void);
> /* Get a character from the command window. */
> extern int tui_getc (FILE*);
>
> +extern struct ui_out *tui_out;
> +extern struct ui_out *tui_old_uiout;
>
> #define m_tuiStartNewLine tuiStartNewLines(1)
> #define m_isStartSequence(ch) (ch == 27)