diff options
Diffstat (limited to 'gdb/ui.h')
-rw-r--r-- | gdb/ui.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/gdb/ui.h b/gdb/ui.h new file mode 100644 index 0000000..8da4b2d --- /dev/null +++ b/gdb/ui.h @@ -0,0 +1,218 @@ +/* Copyright (C) 2023 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 3 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, see <http://www.gnu.org/licenses/>. */ + +#ifndef UI_H +#define UI_H + +#include "gdbsupport/event-loop.h" +#include "gdbsupport/next-iterator.h" + +/* Prompt state. */ + +enum prompt_state +{ + /* The command line is blocked simulating synchronous execution. + This is used to implement the foreground execution commands + ('run', 'continue', etc.). We won't display the prompt and + accept further commands until the execution is actually over. */ + PROMPT_BLOCKED, + + /* The command finished; display the prompt before returning back to + the top level. */ + PROMPT_NEEDED, + + /* We've displayed the prompt already, ready for input. */ + PROMPTED, +}; + +/* All about a user interface instance. Each user interface has its + own I/O files/streams, readline state, its own top level + interpreter (for the main UI, this is the interpreter specified + with -i on the command line) and secondary interpreters (for + interpreter-exec ...), etc. There's always one UI associated with + stdin/stdout/stderr, but the user can create secondary UIs, for + example, to create a separate MI channel on its own stdio + streams. */ + +struct ui +{ + /* Create a new UI. */ + ui (FILE *instream, FILE *outstream, FILE *errstream); + ~ui (); + + DISABLE_COPY_AND_ASSIGN (ui); + + /* Pointer to next in singly-linked list. */ + struct ui *next = nullptr; + + /* Convenient handle (UI number). Unique across all UIs. */ + int num; + + /* The UI's command line buffer. This is to used to accumulate + input until we have a whole command line. */ + std::string line_buffer; + + /* The callback used by the event loop whenever an event is detected + on the UI's input file descriptor. This function incrementally + builds a buffer where it accumulates the line read up to the + point of invocation. In the special case in which the character + read is newline, the function invokes the INPUT_HANDLER callback + (see below). */ + void (*call_readline) (gdb_client_data) = nullptr; + + /* The function to invoke when a complete line of input is ready for + processing. */ + void (*input_handler) (gdb::unique_xmalloc_ptr<char> &&) = nullptr; + + /* True if this UI is using the readline library for command + editing; false if using GDB's own simple readline emulation, with + no editing support. */ + int command_editing = 0; + + /* Each UI has its own independent set of interpreters. */ + struct ui_interp_info *interp_info = nullptr; + + /* True if the UI is in async mode, false if in sync mode. If in + sync mode, a synchronous execution command (e.g, "next") does not + return until the command is finished. If in async mode, then + running a synchronous command returns right after resuming the + target. Waiting for the command's completion is later done on + the top event loop. For the main UI, this starts out disabled, + until all the explicit command line arguments (e.g., `gdb -ex + "start" -ex "next"') are processed. */ + int async = 0; + + /* The number of nested readline secondary prompts that are + currently active. */ + int secondary_prompt_depth = 0; + + /* The UI's stdin. Set to stdin for the main UI. */ + FILE *stdin_stream; + + /* stdio stream that command input is being read from. Set to stdin + normally. Set by source_command to the file we are sourcing. + Set to NULL if we are executing a user-defined command or + interacting via a GUI. */ + FILE *instream; + /* Standard output stream. */ + FILE *outstream; + /* Standard error stream. */ + FILE *errstream; + + /* The file descriptor for the input stream, so that we can register + it with the event loop. This can be set to -1 to prevent this + registration. */ + int input_fd; + + /* Whether ISATTY returns true on input_fd. Cached here because + quit_force needs to know this _after_ input_fd might be + closed. */ + bool m_input_interactive_p; + + /* See enum prompt_state's description. */ + enum prompt_state prompt_state = PROMPT_NEEDED; + + /* The fields below that start with "m_" are "private". They're + meant to be accessed through wrapper macros that make them look + like globals. */ + + /* The ui_file streams. */ + /* Normal results */ + struct ui_file *m_gdb_stdout; + /* Input stream */ + struct ui_file *m_gdb_stdin; + /* Serious error notifications */ + struct ui_file *m_gdb_stderr; + /* Log/debug/trace messages that should bypass normal stdout/stderr + filtering. */ + struct ui_file *m_gdb_stdlog; + + /* The current ui_out. */ + struct ui_out *m_current_uiout = nullptr; + + /* Register the UI's input file descriptor in the event loop. */ + void register_file_handler (); + + /* Unregister the UI's input file descriptor from the event loop. */ + void unregister_file_handler (); + + /* Return true if this UI's input fd is a tty. */ + bool input_interactive_p () const; +}; + +/* The main UI. This is the UI that is bound to stdin/stdout/stderr. + It always exists and is created automatically when GDB starts + up. */ +extern struct ui *main_ui; + +/* The current UI. */ +extern struct ui *current_ui; + +/* The list of all UIs. */ +extern struct ui *ui_list; + +/* State for SWITCH_THRU_ALL_UIS. */ +class switch_thru_all_uis +{ +public: + + switch_thru_all_uis () : m_iter (ui_list), m_save_ui (¤t_ui) + { + current_ui = ui_list; + } + + DISABLE_COPY_AND_ASSIGN (switch_thru_all_uis); + + /* If done iterating, return true; otherwise return false. */ + bool done () const + { + return m_iter == NULL; + } + + /* Move to the next UI, setting current_ui if iteration is not yet + complete. */ + void next () + { + m_iter = m_iter->next; + if (m_iter != NULL) + current_ui = m_iter; + } + + private: + + /* Used to iterate through the UIs. */ + struct ui *m_iter; + + /* Save and restore current_ui. */ + scoped_restore_tmpl<struct ui *> m_save_ui; +}; + + /* Traverse through all UI, and switch the current UI to the one + being iterated. */ +#define SWITCH_THRU_ALL_UIS() \ + for (switch_thru_all_uis stau_state; !stau_state.done (); stau_state.next ()) + +using ui_range = next_range<ui>; + +/* An adapter that can be used to traverse over all UIs. */ +static inline +ui_range all_uis () +{ + return ui_range (ui_list); +} + +#endif /* UI_H */ |