| /* 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/intrusive_list.h" | |
| #include "gdbsupport/next-iterator.h" | |
| struct interp; | |
| /* 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. */ | |
| intrusive_list<interp> interp_list; | |
| interp *current_interpreter = nullptr; | |
| interp *top_level_interpreter = nullptr; | |
| /* The interpreter that is active while `interp_exec' is active, NULL | |
| at all other times. */ | |
| interp *command_interpreter = 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 */ |