static void reschedule (struct serial *scb) { if (serial_is_async_p (scb)) { int next_state; switch (scb->async_state) { case FD_SCHEDULED: if (scb->bufcnt == 0) next_state = FD_SCHEDULED; else { delete_file_handler (scb->fd); next_state = create_timer (0, push_event, scb); } break; case NOTHING_SCHEDULED: if (scb->bufcnt == 0) { add_file_handler (scb->fd, fd_event, scb); next_state = FD_SCHEDULED; } else { next_state = create_timer (0, push_event, scb); } break; default: /* TIMER SCHEDULED */ if (scb->bufcnt == 0) { delete_timer (scb->async_state); add_file_handler (scb->fd, fd_event, scb); next_state = FD_SCHEDULED; } else next_state = scb->async_state; break; } if (serial_debug_p (scb)) { switch (next_state) { case FD_SCHEDULED: if (scb->async_state != FD_SCHEDULED) fprintf_unfiltered (gdb_stdlog, "[fd%d->fd-scheduled]\n", scb->fd); break; default: /* TIMER SCHEDULED */ if (scb->async_state == FD_SCHEDULED) fprintf_unfiltered (gdb_stdlog, "[fd%d->timer-scheduled]\n", scb->fd); break; } } scb->async_state = next_state; } }
void initialize_async_signal_handlers (void) { async_signal_handlers_serial_event = make_serial_event (); add_file_handler (serial_event_fd (async_signal_handlers_serial_event), async_signals_handler, NULL); }
/* 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 sync case. The assumption is that the sync setup is ALL done in gdb_init, and we would only mess it up here. The sync stuff should really go away over time. */ extern int batch_silent; if (!batch_silent) 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)) { /* Tell gdb that we will be using the readline library. This could be overwritten by a command in .gdbinit like 'set editing on' or 'off'. */ async_command_editing_p = 1; /* When a character is detected on instream by select or poll, readline will be invoked via this callback function. */ call_readline = rl_callback_read_char_wrapper; } else { async_command_editing_p = 0; call_readline = gdb_readline2; } /* When readline has read an end-of-line character, it passes the complete line to gdb for processing. command_line_handler is the function that does this. */ input_handler = command_line_handler; /* Tell readline to use the same input stream that gdb uses. */ rl_instream = instream; /* Get a file descriptor for the input stream, so that we can register it with the event loop. */ input_fd = fileno (instream); /* 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 register with the even loop. Another source is going to be the target program (inferior), but that must be registered only when it actually exists (I.e. after we say 'run' or after we connect to a remote target. */ add_file_handler (input_fd, stdin_event_handler, 0); }
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 (); /* 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; /* Route target error through the MI as well. */ gdb_stdtargerr = mi->targ; /* Replace all the hooks that we know about. There really needs to be a better way of doing this... */ clear_interpreter_hooks (); deprecated_show_load_progress = mi_load_progress; /* If we're _the_ interpreter, take control. */ if (current_interp_named_p (INTERP_MI1)) deprecated_command_loop_hook = mi1_command_loop; else if (current_interp_named_p (INTERP_MI2)) deprecated_command_loop_hook = mi2_command_loop; else if (current_interp_named_p (INTERP_MI3)) deprecated_command_loop_hook = mi3_command_loop; else deprecated_command_loop_hook = mi2_command_loop; return 1; }
/* Initialize the IO for gdb in curses mode. */ void tui_initialize_io (void) { #ifdef SIGCONT signal (SIGCONT, tui_cont_sig); #endif /* Create tui output streams. */ tui_stdout = tui_fileopen (stdout); tui_stderr = tui_fileopen (stderr); tui_out = tui_out_new (tui_stdout); /* Create the default UI. It is not created because we installed a deprecated_init_ui_hook. */ tui_old_uiout = uiout = cli_out_new (gdb_stdout); #ifdef TUI_USE_PIPE_FOR_READLINE /* Temporary solution for readline writing to stdout: redirect readline output in a pipe, read that pipe and output the content in the curses command window. */ if (pipe (tui_readline_pipe) != 0) { fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline"); exit (1); } tui_rl_outstream = fdopen (tui_readline_pipe[1], "w"); if (tui_rl_outstream == 0) { fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output"); exit (1); } setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0); #ifdef O_NONBLOCK (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK); #else #ifdef O_NDELAY (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY); #endif #endif add_file_handler (tui_readline_pipe[0], tui_readline_output, 0); #else tui_rl_outstream = stdout; #endif }
/* Initialize the IO for gdb in curses mode. */ void tui_initialize_io (void) { #ifdef SIGCONT signal (SIGCONT, tui_cont_sig); #endif /* Create tui output streams. */ tui_stdout = new tui_file (stdout); tui_stderr = new tui_file (stderr); tui_out = tui_out_new (tui_stdout); /* Create the default UI. */ tui_old_uiout = cli_out_new (gdb_stdout); #ifdef TUI_USE_PIPE_FOR_READLINE /* Temporary solution for readline writing to stdout: redirect readline output in a pipe, read that pipe and output the content in the curses command window. */ if (gdb_pipe_cloexec (tui_readline_pipe) != 0) error (_("Cannot create pipe for readline")); tui_rl_outstream = fdopen (tui_readline_pipe[1], "w"); if (tui_rl_outstream == 0) error (_("Cannot redirect readline output")); setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0); #ifdef O_NONBLOCK (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK); #else #ifdef O_NDELAY (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY); #endif #endif add_file_handler (tui_readline_pipe[0], tui_readline_output, 0); #else tui_rl_outstream = stdout; #endif }
void ser_base_async (struct serial *scb, int async_p) { if (async_p) { /* Force a re-schedule. */ scb->async_state = NOTHING_SCHEDULED; if (serial_debug_p (scb)) fprintf_unfiltered (gdb_stdlog, "[fd%d->asynchronous]\n", scb->fd); reschedule (scb); if (scb->error_fd != -1) add_file_handler (scb->error_fd, handle_error_fd, scb); } else { if (serial_debug_p (scb)) fprintf_unfiltered (gdb_stdlog, "[fd%d->synchronous]\n", scb->fd); /* De-schedule whatever tasks are currently scheduled. */ switch (scb->async_state) { case FD_SCHEDULED: delete_file_handler (scb->fd); break; case NOTHING_SCHEDULED: break; default: /* TIMER SCHEDULED */ delete_timer (scb->async_state); break; } if (scb->error_fd != -1) delete_file_handler (scb->error_fd); } }
void ui_register_input_event_handler (struct ui *ui) { add_file_handler (ui->input_fd, stdin_event_handler, ui); }
/* Displays the prompt. The prompt that is displayed is the current top of the prompt stack, if the argument NEW_PROMPT is 0. Otherwise, it displays whatever NEW_PROMPT is. This is used after each gdb command has completed, and in the following cases: 1. when the user enters a command line which is ended by '\' indicating that the command will continue on the next line. In that case the prompt that is displayed is the empty string. 2. When the user is entering 'commands' for a breakpoint, or actions for a tracepoint. In this case the prompt will be '>' 3. Other???? FIXME: 2. & 3. not implemented yet for async. */ void display_gdb_prompt (char *new_prompt) { int prompt_length = 0; char *gdb_prompt = get_prompt (); static int stdin_handler_removed = 0; /* APPLE LOCAL begin Inform user about debugging optimized code */ if (strcmp (gdb_prompt, "") != 0) { adjust_prompts_for_optimized_code (); gdb_prompt = get_prompt (); } /* APPLE LOCAL end Inform user about debugging optimized code */ /* Each interpreter has its own rules on displaying the command prompt. */ if (!current_interp_display_prompt_p ()) return; if (target_executing && sync_execution) { /* This is to trick readline into not trying to display the prompt. Even though we display the prompt using this function, readline still tries to do its own display if we don't call rl_callback_handler_install and rl_callback_handler_remove (which readline detects because a global variable is not set). If readline did that, it could mess up gdb signal handlers for SIGINT. Readline assumes that between calls to rl_set_signals and rl_clear_signals gdb doesn't do anything with the signal handlers. Well, that's not the case, because when the target executes we change the SIGINT signal handler. If we allowed readline to display the prompt, the signal handler change would happen exactly between the calls to the above two functions. Calling rl_callback_handler_remove(), does the job. */ delete_file_handler (input_fd); stdin_handler_removed = 1; rl_callback_handler_remove (); return; } if (!new_prompt) { /* Just use the top of the prompt stack. */ prompt_length = strlen (PREFIX (0)) + strlen (SUFFIX (0)) + strlen (gdb_prompt) + 1; new_prompt = (char *) alloca (prompt_length); /* Prefix needs to have new line at end. */ strcpy (new_prompt, PREFIX (0)); strcat (new_prompt, gdb_prompt); /* Suffix needs to have a new line at end and \032 \032 at beginning. */ strcat (new_prompt, SUFFIX (0)); } if (async_command_editing_p) { /* Claim the terminal before we reset it. It is quick if the terminal is already ours, and if not, we are going to lose when we try to install the callback handler otherwise. We can get here with the terminal still belonging to the inferior if it dies an unexpected death, and somebody forgets to clean up properly. Better safe than sorry... */ target_terminal_ours (); if (stdin_handler_removed) { add_file_handler (input_fd, stdin_event_handler, 0); stdin_handler_removed = 0; } rl_callback_handler_remove (); rl_callback_handler_install (new_prompt, input_handler); } /* new_prompt at this point can be the top of the stack or the one passed in */ else if (new_prompt) { /* Don't use a _filtered function here. It causes the assumed character position to be off, since the newline we read from the user is not accounted for. */ fputs_unfiltered (new_prompt, gdb_stdout); gdb_flush (gdb_stdout); } }