//===-- CommandInterpreter.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_CommandInterpreter_h_ #define liblldb_CommandInterpreter_h_ // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/Log.h" #include "lldb/Interpreter/CommandHistory.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Core/Event.h" #include "lldb/Interpreter/Args.h" #include "lldb/Core/StringList.h" namespace lldb_private { class CommandInterpreterRunOptions { public: //------------------------------------------------------------------ /// Construct a CommandInterpreterRunOptions object. /// This class is used to control all the instances where we run multiple commands, e.g. /// HandleCommands, HandleCommandsFromFile, RunCommandInterpreter. /// The meanings of the options in this object are: /// /// @param[in] stop_on_continue /// If \b true execution will end on the first command that causes the process in the /// execution context to continue. If \false, we won't check the execution status. /// @param[in] stop_on_error /// If \b true execution will end on the first command that causes an error. /// @param[in] stop_on_crash /// If \b true when a command causes the target to run, and the end of the run is a /// signal or exception, stop executing the commands. /// @param[in] echo_commands /// If \b true echo the command before executing it. If \false, execute silently. /// @param[in] print_results /// If \b true print the results of the command after executing it. If \false, execute silently. /// @param[in] add_to_history /// If \b true add the commands to the command history. If \false, don't add them. //------------------------------------------------------------------ CommandInterpreterRunOptions (LazyBool stop_on_continue, LazyBool stop_on_error, LazyBool stop_on_crash, LazyBool echo_commands, LazyBool print_results, LazyBool add_to_history) : m_stop_on_continue(stop_on_continue), m_stop_on_error(stop_on_error), m_stop_on_crash(stop_on_crash), m_echo_commands(echo_commands), m_print_results(print_results), m_add_to_history(add_to_history) {} CommandInterpreterRunOptions () : m_stop_on_continue(eLazyBoolCalculate), m_stop_on_error(eLazyBoolCalculate), m_stop_on_crash(eLazyBoolCalculate), m_echo_commands(eLazyBoolCalculate), m_print_results(eLazyBoolCalculate), m_add_to_history(eLazyBoolCalculate) {} void SetSilent (bool silent) { LazyBool value = silent ? eLazyBoolNo : eLazyBoolYes; m_echo_commands = value; m_print_results = value; m_add_to_history = value; } // These return the default behaviors if the behavior is not eLazyBoolCalculate. // But I've also left the ivars public since for different ways of running the // interpreter you might want to force different defaults... In that case, just grab // the LazyBool ivars directly and do what you want with eLazyBoolCalculate. bool GetStopOnContinue () const { return DefaultToNo (m_stop_on_continue); } void SetStopOnContinue (bool stop_on_continue) { m_stop_on_continue = stop_on_continue ? eLazyBoolYes : eLazyBoolNo; } bool GetStopOnError () const { return DefaultToNo (m_stop_on_continue); } void SetStopOnError (bool stop_on_error) { m_stop_on_error = stop_on_error ? eLazyBoolYes : eLazyBoolNo; } bool GetStopOnCrash () const { return DefaultToNo (m_stop_on_crash); } void SetStopOnCrash (bool stop_on_crash) { m_stop_on_crash = stop_on_crash ? eLazyBoolYes : eLazyBoolNo; } bool GetEchoCommands () const { return DefaultToYes (m_echo_commands); } void SetEchoCommands (bool echo_commands) { m_echo_commands = echo_commands ? eLazyBoolYes : eLazyBoolNo; } bool GetPrintResults () const { return DefaultToYes (m_print_results); } void SetPrintResults (bool print_results) { m_print_results = print_results ? eLazyBoolYes : eLazyBoolNo; } bool GetAddToHistory () const { return DefaultToYes (m_add_to_history); } void SetAddToHistory (bool add_to_history) { m_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; } LazyBool m_stop_on_continue; LazyBool m_stop_on_error; LazyBool m_stop_on_crash; LazyBool m_echo_commands; LazyBool m_print_results; LazyBool m_add_to_history; private: static bool DefaultToYes (LazyBool flag) { switch (flag) { case eLazyBoolNo: return false; default: return true; } } static bool DefaultToNo (LazyBool flag) { switch (flag) { case eLazyBoolYes: return true; default: return false; } } }; class CommandInterpreter : public Broadcaster, public Properties, public IOHandlerDelegate { public: typedef std::map OptionArgMap; enum { eBroadcastBitThreadShouldExit = (1 << 0), eBroadcastBitResetPrompt = (1 << 1), eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit eBroadcastBitAsynchronousOutputData = (1 << 3), eBroadcastBitAsynchronousErrorData = (1 << 4) }; enum ChildrenTruncatedWarningStatus // tristate boolean to manage children truncation warning { eNoTruncation = 0, // never truncated eUnwarnedTruncation = 1, // truncated but did not notify eWarnedTruncation = 2 // truncated and notified }; enum CommandTypes { eCommandTypesBuiltin = 0x0001, // native commands such as "frame" eCommandTypesUserDef = 0x0002, // scripted commands eCommandTypesAliases = 0x0004, // aliases such as "po" eCommandTypesAllThem = 0xFFFF // all commands }; // These two functions fill out the Broadcaster interface: static ConstString &GetStaticBroadcasterClass (); virtual ConstString &GetBroadcasterClass() const { return GetStaticBroadcasterClass(); } void SourceInitFile (bool in_cwd, CommandReturnObject &result); CommandInterpreter (Debugger &debugger, lldb::ScriptLanguage script_language, bool synchronous_execution); virtual ~CommandInterpreter (); bool AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace); bool AddUserCommand (std::string name, const lldb::CommandObjectSP &cmd_sp, bool can_replace); lldb::CommandObjectSP GetCommandSPExact (const char *cmd, bool include_aliases); CommandObject * GetCommandObjectExact (const char *cmd_cstr, bool include_aliases); CommandObject * GetCommandObject (const char *cmd, StringList *matches = NULL); bool CommandExists (const char *cmd); bool AliasExists (const char *cmd); bool UserCommandExists (const char *cmd); void AddAlias (const char *alias_name, lldb::CommandObjectSP& command_obj_sp); // Remove a command if it is removable (python or regex command) bool RemoveCommand (const char *cmd); bool RemoveAlias (const char *alias_name); bool GetAliasFullName (const char *cmd, std::string &full_name); bool RemoveUser (const char *alias_name); void RemoveAllUser () { m_user_dict.clear(); } OptionArgVectorSP GetAliasOptions (const char *alias_name); bool ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, const char *options_args, OptionArgVectorSP &option_arg_vector_sp); void RemoveAliasOptions (const char *alias_name); void AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp); CommandObject * BuildAliasResult (const char *alias_name, std::string &raw_input_string, std::string &alias_result, CommandReturnObject &result); bool HandleCommand (const char *command_line, LazyBool add_to_history, CommandReturnObject &result, ExecutionContext *override_context = NULL, bool repeat_on_empty_command = true, bool no_context_switching = false); //------------------------------------------------------------------ /// Execute a list of commands in sequence. /// /// @param[in] commands /// The list of commands to execute. /// @param[in/out] context /// The execution context in which to run the commands. Can be NULL in which case the default /// context will be used. /// @param[in] options /// This object holds the options used to control when to stop, whether to execute commands, /// etc. /// @param[out] result /// This is marked as succeeding with no output if all commands execute safely, /// and failed with some explanation if we aborted executing the commands at some point. //------------------------------------------------------------------ void HandleCommands (const StringList &commands, ExecutionContext *context, CommandInterpreterRunOptions &options, CommandReturnObject &result); //------------------------------------------------------------------ /// Execute a list of commands from a file. /// /// @param[in] file /// The file from which to read in commands. /// @param[in/out] context /// The execution context in which to run the commands. Can be NULL in which case the default /// context will be used. /// @param[in] options /// This object holds the options used to control when to stop, whether to execute commands, /// etc. /// @param[out] result /// This is marked as succeeding with no output if all commands execute safely, /// and failed with some explanation if we aborted executing the commands at some point. //------------------------------------------------------------------ void HandleCommandsFromFile (FileSpec &file, ExecutionContext *context, CommandInterpreterRunOptions &options, CommandReturnObject &result); CommandObject * GetCommandObjectForCommand (std::string &command_line); // This handles command line completion. You are given a pointer to the command string buffer, to the current cursor, // and to the end of the string (in case it is not NULL terminated). // You also passed in an StringList object to fill with the returns. // The first element of the array will be filled with the string that you would need to insert at // the cursor point to complete the cursor point to the longest common matching prefix. // If you want to limit the number of elements returned, set max_return_elements to the number of elements // you want returned. Otherwise set max_return_elements to -1. // If you want to start some way into the match list, then set match_start_point to the desired start // point. // Returns: // -1 if the completion character should be inserted // -2 if the entire command line should be deleted and replaced with matches.GetStringAtIndex(0) // INT_MAX if the number of matches is > max_return_elements, but it is expensive to compute. // Otherwise, returns the number of matches. // // FIXME: Only max_return_elements == -1 is supported at present. int HandleCompletion (const char *current_line, const char *cursor, const char *last_char, int match_start_point, int max_return_elements, StringList &matches); // This version just returns matches, and doesn't compute the substring. It is here so the // Help command can call it for the first argument. // word_complete tells whether the completions are considered a "complete" response (so the // completer should complete the quote & put a space after the word. int HandleCompletionMatches (Args &input, int &cursor_index, int &cursor_char_position, int match_start_point, int max_return_elements, bool &word_complete, StringList &matches); int GetCommandNamesMatchingPartialString (const char *cmd_cstr, bool include_aliases, StringList &matches); void GetHelp (CommandReturnObject &result, uint32_t types = eCommandTypesAllThem); void GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string); void OutputFormattedHelpText (Stream &stream, const char *command_word, const char *separator, const char *help_text, size_t max_word_len); // this mimics OutputFormattedHelpText but it does perform a much simpler // formatting, basically ensuring line alignment. This is only good if you have // some complicated layout for your help text and want as little help as reasonable // in properly displaying it. Most of the times, you simply want to type some text // and have it printed in a reasonable way on screen. If so, use OutputFormattedHelpText void OutputHelpText (Stream &stream, const char *command_word, const char *separator, const char *help_text, uint32_t max_word_len); Debugger & GetDebugger () { return m_debugger; } ExecutionContext GetExecutionContext() { const bool thread_and_frame_only_if_stopped = true; return m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped); } void UpdateExecutionContext (ExecutionContext *override_context); lldb::PlatformSP GetPlatform (bool prefer_target_platform); const char * ProcessEmbeddedScriptCommands (const char *arg); void UpdatePrompt (const char *); bool Confirm (const char *message, bool default_answer); void LoadCommandDictionary (); void Initialize (); void Clear (); void SetScriptLanguage (lldb::ScriptLanguage lang); bool HasCommands (); bool HasAliases (); bool HasUserCommands (); bool HasAliasOptions (); void BuildAliasCommandArgs (CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args, std::string &raw_input_string, CommandReturnObject &result); int GetOptionArgumentPosition (const char *in_string); ScriptInterpreter * GetScriptInterpreter (bool can_create = true); void SkipLLDBInitFiles (bool skip_lldbinit_files) { m_skip_lldbinit_files = skip_lldbinit_files; } void SkipAppInitFiles (bool skip_app_init_files) { m_skip_app_init_files = m_skip_lldbinit_files; } bool GetSynchronous (); size_t FindLongestCommandWord (CommandObject::CommandMap &dict); void FindCommandsForApropos (const char *word, StringList &commands_found, StringList &commands_help, bool search_builtin_commands, bool search_user_commands); bool GetBatchCommandMode () { return m_batch_command_mode; } bool SetBatchCommandMode (bool value) { const bool old_value = m_batch_command_mode; m_batch_command_mode = value; return old_value; } void ChildrenTruncated () { if (m_truncation_warning == eNoTruncation) m_truncation_warning = eUnwarnedTruncation; } bool TruncationWarningNecessary () { return (m_truncation_warning == eUnwarnedTruncation); } void TruncationWarningGiven () { m_truncation_warning = eWarnedTruncation; } const char * TruncationWarningText () { return "*** Some of your variables have more members than the debugger will show by default. To show all of them, you can either use the --show-all-children option to %s or raise the limit by changing the target.max-children-count setting.\n"; } const CommandHistory& GetCommandHistory () const { return m_command_history; } CommandHistory& GetCommandHistory () { return m_command_history; } bool IsActive (); void RunCommandInterpreter (bool auto_handle_events, bool spawn_thread, CommandInterpreterRunOptions &options); void GetLLDBCommandsFromIOHandler (const char *prompt, IOHandlerDelegate &delegate, bool asynchronously, void *baton); void GetPythonCommandsFromIOHandler (const char *prompt, IOHandlerDelegate &delegate, bool asynchronously, void *baton); //------------------------------------------------------------------ // Properties //------------------------------------------------------------------ bool GetExpandRegexAliases () const; bool GetPromptOnQuit () const; bool GetStopCmdSourceOnError () const; uint32_t GetNumErrors() const { return m_num_errors; } bool GetQuitRequested () const { return m_quit_requested; } lldb::IOHandlerSP GetIOHandler(bool force_create = false, CommandInterpreterRunOptions *options = NULL); bool GetStoppedForCrash () const { return m_stopped_for_crash; } protected: friend class Debugger; //------------------------------------------------------------------ // IOHandlerDelegate functions //------------------------------------------------------------------ virtual void IOHandlerInputComplete (IOHandler &io_handler, std::string &line); virtual ConstString IOHandlerGetControlSequence (char ch) { if (ch == 'd') return ConstString("quit\n"); return ConstString(); } virtual bool IOHandlerInterrupt (IOHandler &io_handler); size_t GetProcessOutput (); void SetSynchronous (bool value); lldb::CommandObjectSP GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL); private: Error PreprocessCommand (std::string &command); Debugger &m_debugger; // The debugger session that this interpreter is associated with ExecutionContextRef m_exe_ctx_ref; // The current execution context to use when handling commands bool m_synchronous_execution; bool m_skip_lldbinit_files; bool m_skip_app_init_files; CommandObject::CommandMap m_command_dict; // Stores basic built-in commands (they cannot be deleted, removed or overwritten). CommandObject::CommandMap m_alias_dict; // Stores user aliases/abbreviations for commands CommandObject::CommandMap m_user_dict; // Stores user-defined commands OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias. CommandHistory m_command_history; std::string m_repeat_command; // Stores the command that will be executed for an empty command string. std::unique_ptr m_script_interpreter_ap; lldb::IOHandlerSP m_command_io_handler_sp; char m_comment_char; bool m_batch_command_mode; ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated children and whether the user has been told uint32_t m_command_source_depth; std::vector m_command_source_flags; uint32_t m_num_errors; bool m_quit_requested; bool m_stopped_for_crash; }; } // namespace lldb_private #endif // liblldb_CommandInterpreter_h_